From e61fa1aed1a1adb0475d80855ef7059960538925 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Thu, 4 Feb 2016 17:33:03 -0800 Subject: [PATCH 01/12] Add some sneaky missing deps --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 1e615127d..806a018eb 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,8 @@ updatedeps: fi go get -u github.com/mitchellh/gox go get -u golang.org/x/tools/cmd/stringer + go get -u golang.org/x/sys/unix + go get -u google.golang.org/appengine go list ./... \ | xargs go list -f '{{join .Deps "\n"}}' \ | grep -v github.com/mitchellh/packer \ From 4ba54d97c5a613824be6b4799fbac78f9ecb9ee5 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Thu, 4 Feb 2016 17:33:21 -0800 Subject: [PATCH 02/12] Add godeps --- Godeps/Godeps.json | 321 +++++++++++++++++++++++++++++++++++++++++++++ Godeps/Readme | 5 + 2 files changed, 326 insertions(+) create mode 100644 Godeps/Godeps.json create mode 100644 Godeps/Readme diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json new file mode 100644 index 000000000..3d48bdff7 --- /dev/null +++ b/Godeps/Godeps.json @@ -0,0 +1,321 @@ +{ + "ImportPath": "github.com/mitchellh/packer", + "GoVersion": "go1.5", + "Deps": [ + { + "ImportPath": "github.com/ActiveState/tail", + "Comment": "v0-41-g1a0242e", + "Rev": "1a0242e795eeefe54261ff308dc685f7d29cc58c" + }, + { + "ImportPath": "github.com/armon/go-radix", + "Rev": "4239b77079c7b5d1243b7b4736304ce8ddb6f0f2" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/aws", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/private/endpoints", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/private/protocol", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/private/waiter", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/service/ec2", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/aws/aws-sdk-go/service/sts", + "Comment": "v1.1.0-15-ga170e9c", + "Rev": "a170e9cb76475a0da7c0326a13cc2b39e9244b3b" + }, + { + "ImportPath": "github.com/bgentry/speakeasy", + "Rev": "36e9cfdd690967f4f690c6edcc9ffacd006014a0" + }, + { + "ImportPath": "github.com/digitalocean/godo", + "Comment": "v0.9.0-24-g6ca5b77", + "Rev": "6ca5b770f203b82a0fca68d0941736458efa8a4f" + }, + { + "ImportPath": "github.com/dylanmei/iso8601", + "Rev": "2075bf119b58e5576c6ed9f867b8f3d17f2e54d4" + }, + { + "ImportPath": "github.com/dylanmei/winrmtest", + "Rev": "025617847eb2cf9bd1d851bc3b22ed28e6245ce5" + }, + { + "ImportPath": "github.com/go-ini/ini", + "Comment": "v1.8.6", + "Rev": "afbd495e5aaea13597b5e14fe514ddeaa4d76fc3" + }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Rev": "b982704f8bb716bb608144408cff30e15fbde841" + }, + { + "ImportPath": "github.com/google/go-querystring/query", + "Rev": "2a60fc2ba6c19de80291203597d752e9ba58e4c0" + }, + { + "ImportPath": "github.com/hashicorp/atlas-go/archive", + "Comment": "20141209094003-90-g0008886", + "Rev": "0008886ebfa3b424bed03e2a5cbe4a2568ea0ff6" + }, + { + "ImportPath": "github.com/hashicorp/atlas-go/v1", + "Comment": "20141209094003-90-g0008886", + "Rev": "0008886ebfa3b424bed03e2a5cbe4a2568ea0ff6" + }, + { + "ImportPath": "github.com/hashicorp/errwrap", + "Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55" + }, + { + "ImportPath": "github.com/hashicorp/go-checkpoint", + "Rev": "e4b2dc34c0f698ee04750bf2035d8b9384233e1b" + }, + { + "ImportPath": "github.com/hashicorp/go-cleanhttp", + "Rev": "ce617e79981a8fff618bb643d155133a8f38db96" + }, + { + "ImportPath": "github.com/hashicorp/go-multierror", + "Rev": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5" + }, + { + "ImportPath": "github.com/hashicorp/go-version", + "Rev": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38" + }, + { + "ImportPath": "github.com/hashicorp/yamux", + "Rev": "df949784da9ed028ee76df44652e42d37a09d7e4" + }, + { + "ImportPath": "github.com/hpcloud/tail/ratelimiter", + "Comment": "v0-41-g1a0242e", + "Rev": "1a0242e795eeefe54261ff308dc685f7d29cc58c" + }, + { + "ImportPath": "github.com/hpcloud/tail/util", + "Comment": "v0-41-g1a0242e", + "Rev": "1a0242e795eeefe54261ff308dc685f7d29cc58c" + }, + { + "ImportPath": "github.com/hpcloud/tail/watch", + "Comment": "v0-41-g1a0242e", + "Rev": "1a0242e795eeefe54261ff308dc685f7d29cc58c" + }, + { + "ImportPath": "github.com/hpcloud/tail/winfile", + "Comment": "v0-41-g1a0242e", + "Rev": "1a0242e795eeefe54261ff308dc685f7d29cc58c" + }, + { + "ImportPath": "github.com/jmespath/go-jmespath", + "Comment": "0.2.2-2-gc01cf91", + "Rev": "c01cf91b011868172fdcd9f41838e80c9d716264" + }, + { + "ImportPath": "github.com/kardianos/osext", + "Rev": "29ae4ffbc9a6fe9fb2bc5029050ce6996ea1d3bc" + }, + { + "ImportPath": "github.com/klauspost/compress/flate", + "Rev": "f86d2e6d8a77c6a2c4e42a87ded21c6422f7557e" + }, + { + "ImportPath": "github.com/klauspost/cpuid", + "Rev": "349c675778172472f5e8f3a3e0fe187e302e5a10" + }, + { + "ImportPath": "github.com/klauspost/crc32", + "Rev": "999f3125931f6557b991b2f8472172bdfa578d38" + }, + { + "ImportPath": "github.com/klauspost/pgzip", + "Rev": "47f36e165cecae5382ecf1ec28ebf7d4679e307d" + }, + { + "ImportPath": "github.com/kr/fs", + "Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b" + }, + { + "ImportPath": "github.com/masterzen/simplexml/dom", + "Rev": "95ba30457eb1121fa27753627c774c7cd4e90083" + }, + { + "ImportPath": "github.com/masterzen/winrm/soap", + "Rev": "54ea5d01478cfc2afccec1504bd0dfcd8c260cfa" + }, + { + "ImportPath": "github.com/masterzen/winrm/winrm", + "Rev": "54ea5d01478cfc2afccec1504bd0dfcd8c260cfa" + }, + { + "ImportPath": "github.com/masterzen/xmlpath", + "Rev": "13f4951698adc0fa9c1dda3e275d489a24201161" + }, + { + "ImportPath": "github.com/mattn/go-isatty", + "Rev": "56b76bdf51f7708750eac80fa38b952bb9f32639" + }, + { + "ImportPath": "github.com/mitchellh/cli", + "Rev": "5c87c51cedf76a1737bf5ca3979e8644871598a6" + }, + { + "ImportPath": "github.com/mitchellh/go-fs", + "Rev": "a34c1b9334e86165685a9449b782f20465eb8c69" + }, + { + "ImportPath": "github.com/mitchellh/go-homedir", + "Rev": "d682a8f0cf139663a984ff12528da460ca963de9" + }, + { + "ImportPath": "github.com/mitchellh/go-vnc", + "Rev": "723ed9867aed0f3209a81151e52ddc61681f0b01" + }, + { + "ImportPath": "github.com/mitchellh/iochan", + "Rev": "87b45ffd0e9581375c491fef3d32130bb15c5bd7" + }, + { + "ImportPath": "github.com/mitchellh/mapstructure", + "Rev": "281073eb9eb092240d33ef253c404f1cca550309" + }, + { + "ImportPath": "github.com/mitchellh/multistep", + "Rev": "162146fc57112954184d90266f4733e900ed05a5" + }, + { + "ImportPath": "github.com/mitchellh/panicwrap", + "Rev": "a1e50bc201f387747a45ffff020f1af2d8759e88" + }, + { + "ImportPath": "github.com/mitchellh/prefixedio", + "Rev": "6e6954073784f7ee67b28f2d22749d6479151ed7" + }, + { + "ImportPath": "github.com/mitchellh/reflectwalk", + "Rev": "eecf4c70c626c7cfbb95c90195bc34d386c74ac6" + }, + { + "ImportPath": "github.com/nu7hatch/gouuid", + "Rev": "179d4d0c4d8d407a32af483c2354df1d2c91e6c3" + }, + { + "ImportPath": "github.com/packer-community/winrmcp/winrmcp", + "Rev": "3d184cea22ee1c41ec1697e0d830ff0c78f7ea97" + }, + { + "ImportPath": "github.com/pierrec/lz4", + "Rev": "383c0d87b5dd7c090d3cddefe6ff0c2ffbb88470" + }, + { + "ImportPath": "github.com/pierrec/xxHash/xxHash32", + "Rev": "5a004441f897722c627870a981d02b29924215fa" + }, + { + "ImportPath": "github.com/pkg/sftp", + "Rev": "e84cc8c755ca39b7b64f510fe1fffc1b51f210a5" + }, + { + "ImportPath": "github.com/rackspace/gophercloud", + "Comment": "v1.0.0-774-g680aa02", + "Rev": "680aa02616313d8399abc91f17a444cf9292f0e1" + }, + { + "ImportPath": "github.com/satori/go.uuid", + "Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048" + }, + { + "ImportPath": "github.com/tent/http-link-go", + "Rev": "ac974c61c2f990f4115b119354b5e0b47550e888" + }, + { + "ImportPath": "github.com/ugorji/go/codec", + "Rev": "646ae4a518c1c3be0739df898118d9bccf993858" + }, + { + "ImportPath": "golang.org/x/crypto/curve25519", + "Rev": "1f22c0103821b9390939b6776727195525381532" + }, + { + "ImportPath": "golang.org/x/crypto/ssh", + "Rev": "1f22c0103821b9390939b6776727195525381532" + }, + { + "ImportPath": "golang.org/x/net/context", + "Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1" + }, + { + "ImportPath": "golang.org/x/net/html", + "Rev": "6ccd6698c634f5d835c40c1c31848729e0cecda1" + }, + { + "ImportPath": "golang.org/x/oauth2", + "Rev": "8a57ed94ffd43444c0879fe75701732a38afc985" + }, + { + "ImportPath": "golang.org/x/sys/unix", + "Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e" + }, + { + "ImportPath": "google.golang.org/api/compute/v1", + "Rev": "ddff2aff599105a55549cf173852507dfa094b7f" + }, + { + "ImportPath": "google.golang.org/api/gensupport", + "Rev": "ddff2aff599105a55549cf173852507dfa094b7f" + }, + { + "ImportPath": "google.golang.org/api/googleapi", + "Rev": "ddff2aff599105a55549cf173852507dfa094b7f" + }, + { + "ImportPath": "google.golang.org/appengine", + "Rev": "6bde959377a90acb53366051d7d587bfd7171354" + }, + { + "ImportPath": "google.golang.org/cloud/compute/metadata", + "Rev": "5a3b06f8b5da3b7c3a93da43163b872c86c509ef" + }, + { + "ImportPath": "google.golang.org/cloud/internal", + "Rev": "5a3b06f8b5da3b7c3a93da43163b872c86c509ef" + }, + { + "ImportPath": "gopkg.in/fsnotify.v1", + "Comment": "v1.2.9", + "Rev": "8611c35ab31c1c28aa903d33cf8b6e44a399b09e" + }, + { + "ImportPath": "gopkg.in/tomb.v1", + "Rev": "dd632973f1e7218eb1089048e0798ec9ae7dceb8" + }, + { + "ImportPath": "gopkg.in/xmlpath.v2", + "Rev": "860cbeca3ebcc600db0b213c0e83ad6ce91f5739" + } + ] +} diff --git a/Godeps/Readme b/Godeps/Readme new file mode 100644 index 000000000..4cdaa53d5 --- /dev/null +++ b/Godeps/Readme @@ -0,0 +1,5 @@ +This directory tree is generated automatically by godep. + +Please do not edit. + +See https://github.com/tools/godep for more information. From dbdb98863480b904c0655d222e55b6102103e464 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Thu, 4 Feb 2016 17:33:36 -0800 Subject: [PATCH 03/12] Vendor all dependencies --- vendor/github.com/ActiveState/tail/.gitignore | 3 + .../github.com/ActiveState/tail/.travis.yml | 13 + vendor/github.com/ActiveState/tail/CHANGES.md | 57 + vendor/github.com/ActiveState/tail/Dockerfile | 19 + .../github.com/ActiveState/tail/LICENSE.txt | 23 + vendor/github.com/ActiveState/tail/Makefile | 11 + vendor/github.com/ActiveState/tail/README.md | 27 + .../ActiveState/tail/cmd/gotail/.gitignore | 1 + .../ActiveState/tail/cmd/gotail/Makefile | 4 + .../ActiveState/tail/cmd/gotail/gotail.go | 64 + vendor/github.com/ActiveState/tail/deps.json | 14 + .../ActiveState/tail/ratelimiter/Licence | 7 + .../tail/ratelimiter/leakybucket.go | 97 + .../ActiveState/tail/ratelimiter/memory.go | 58 + .../ActiveState/tail/ratelimiter/storage.go | 6 + vendor/github.com/ActiveState/tail/tail.go | 419 + .../github.com/ActiveState/tail/tail_posix.go | 11 + .../ActiveState/tail/tail_windows.go | 12 + .../github.com/ActiveState/tail/util/util.go | 47 + .../ActiveState/tail/watch/filechanges.go | 42 + .../ActiveState/tail/watch/inotify.go | 119 + .../ActiveState/tail/watch/inotify_tracker.go | 254 + .../ActiveState/tail/watch/polling.go | 119 + .../ActiveState/tail/watch/watch.go | 19 + .../ActiveState/tail/winfile/winfile.go | 92 + vendor/github.com/armon/go-radix/.gitignore | 22 + vendor/github.com/armon/go-radix/.travis.yml | 3 + vendor/github.com/armon/go-radix/LICENSE | 20 + vendor/github.com/armon/go-radix/README.md | 38 + vendor/github.com/armon/go-radix/radix.go | 496 + vendor/github.com/aws/aws-sdk-go/LICENSE.txt | 202 + vendor/github.com/aws/aws-sdk-go/NOTICE.txt | 3 + .../aws/aws-sdk-go/aws/awserr/error.go | 127 + .../aws/aws-sdk-go/aws/awserr/types.go | 197 + .../aws/aws-sdk-go/aws/awsutil/copy.go | 100 + .../aws/aws-sdk-go/aws/awsutil/equal.go | 27 + .../aws/aws-sdk-go/aws/awsutil/path_value.go | 222 + .../aws/aws-sdk-go/aws/awsutil/prettify.go | 103 + .../aws-sdk-go/aws/awsutil/string_value.go | 89 + .../aws/aws-sdk-go/aws/client/client.go | 120 + .../aws-sdk-go/aws/client/default_retryer.go | 45 + .../aws/client/metadata/client_info.go | 12 + .../github.com/aws/aws-sdk-go/aws/config.go | 311 + .../aws/aws-sdk-go/aws/convert_types.go | 357 + .../aws-sdk-go/aws/corehandlers/handlers.go | 139 + .../aws/corehandlers/param_validator.go | 144 + .../aws/credentials/chain_provider.go | 100 + .../aws-sdk-go/aws/credentials/credentials.go | 223 + .../ec2rolecreds/ec2_role_provider.go | 178 + .../aws/credentials/env_provider.go | 77 + .../aws-sdk-go/aws/credentials/example.ini | 12 + .../shared_credentials_provider.go | 151 + .../aws/credentials/static_provider.go | 48 + .../stscreds/assume_role_provider.go | 134 + .../aws/aws-sdk-go/aws/defaults/defaults.go | 96 + .../aws/aws-sdk-go/aws/ec2metadata/api.go | 43 + .../aws/aws-sdk-go/aws/ec2metadata/service.go | 117 + .../github.com/aws/aws-sdk-go/aws/errors.go | 17 + .../github.com/aws/aws-sdk-go/aws/logger.go | 98 + .../aws/aws-sdk-go/aws/request/handlers.go | 140 + .../aws/aws-sdk-go/aws/request/request.go | 294 + .../aws/request/request_pagination.go | 104 + .../aws/aws-sdk-go/aws/request/retryer.go | 82 + .../aws/aws-sdk-go/aws/session/session.go | 120 + vendor/github.com/aws/aws-sdk-go/aws/types.go | 88 + .../github.com/aws/aws-sdk-go/aws/version.go | 8 + .../aws-sdk-go/private/endpoints/endpoints.go | 65 + .../private/endpoints/endpoints.json | 92 + .../private/endpoints/endpoints_map.go | 104 + .../private/protocol/ec2query/build.go | 35 + .../private/protocol/ec2query/unmarshal.go | 63 + .../private/protocol/idempotency.go | 75 + .../private/protocol/json/jsonutil/build.go | 251 + .../protocol/json/jsonutil/unmarshal.go | 213 + .../private/protocol/jsonrpc/jsonrpc.go | 111 + .../private/protocol/query/build.go | 36 + .../protocol/query/queryutil/queryutil.go | 230 + .../private/protocol/query/unmarshal.go | 35 + .../private/protocol/query/unmarshal_error.go | 40 + .../aws-sdk-go/private/protocol/rest/build.go | 257 + .../private/protocol/rest/payload.go | 45 + .../private/protocol/rest/unmarshal.go | 193 + .../private/protocol/restjson/restjson.go | 91 + .../private/protocol/restxml/restxml.go | 69 + .../aws-sdk-go/private/protocol/unmarshal.go | 21 + .../private/protocol/xml/xmlutil/build.go | 293 + .../private/protocol/xml/xmlutil/unmarshal.go | 260 + .../protocol/xml/xmlutil/xml_to_struct.go | 105 + .../private/signer/v4/header_rules.go | 82 + .../aws/aws-sdk-go/private/signer/v4/v4.go | 438 + .../aws/aws-sdk-go/private/waiter/waiter.go | 134 + .../aws/aws-sdk-go/service/ec2/api.go | 25097 ++++++++++ .../aws-sdk-go/service/ec2/customizations.go | 55 + .../service/ec2/ec2iface/interface.go | 832 + .../aws/aws-sdk-go/service/ec2/service.go | 89 + .../aws/aws-sdk-go/service/ec2/waiters.go | 761 + .../aws/aws-sdk-go/service/sts/api.go | 1094 + .../aws-sdk-go/service/sts/customizations.go | 12 + .../aws/aws-sdk-go/service/sts/service.go | 130 + .../service/sts/stsiface/interface.go | 38 + .../github.com/bgentry/speakeasy/.gitignore | 2 + .../bgentry/speakeasy/LICENSE_WINDOWS | 201 + vendor/github.com/bgentry/speakeasy/Readme.md | 30 + .../bgentry/speakeasy/example/main.go | 18 + .../github.com/bgentry/speakeasy/speakeasy.go | 47 + .../bgentry/speakeasy/speakeasy_unix.go | 93 + .../bgentry/speakeasy/speakeasy_windows.go | 43 + .../github.com/digitalocean/godo/.travis.yml | 6 + .../digitalocean/godo/CONTRIBUTING.md | 23 + .../github.com/digitalocean/godo/LICENSE.txt | 55 + vendor/github.com/digitalocean/godo/README.md | 136 + .../github.com/digitalocean/godo/account.go | 53 + vendor/github.com/digitalocean/godo/action.go | 100 + vendor/github.com/digitalocean/godo/doc.go | 2 + .../github.com/digitalocean/godo/domains.go | 323 + .../digitalocean/godo/droplet_actions.go | 238 + .../github.com/digitalocean/godo/droplets.go | 495 + vendor/github.com/digitalocean/godo/errors.go | 24 + .../digitalocean/godo/floating_ips.go | 131 + .../digitalocean/godo/floating_ips_actions.go | 105 + vendor/github.com/digitalocean/godo/godo.go | 341 + .../digitalocean/godo/image_actions.go | 71 + vendor/github.com/digitalocean/godo/images.go | 194 + vendor/github.com/digitalocean/godo/keys.go | 222 + vendor/github.com/digitalocean/godo/links.go | 86 + .../github.com/digitalocean/godo/regions.go | 63 + vendor/github.com/digitalocean/godo/sizes.go | 63 + .../github.com/digitalocean/godo/strings.go | 83 + .../github.com/digitalocean/godo/timestamp.go | 35 + .../digitalocean/godo/util/droplet.go | 47 + vendor/github.com/dylanmei/iso8601/LICENSE | 21 + vendor/github.com/dylanmei/iso8601/README.md | 9 + .../github.com/dylanmei/iso8601/duration.go | 96 + vendor/github.com/dylanmei/winrmtest/LICENSE | 22 + .../github.com/dylanmei/winrmtest/README.md | 48 + .../github.com/dylanmei/winrmtest/remote.go | 79 + vendor/github.com/dylanmei/winrmtest/wsman.go | 170 + vendor/github.com/go-ini/ini/.gitignore | 4 + vendor/github.com/go-ini/ini/LICENSE | 191 + vendor/github.com/go-ini/ini/README.md | 590 + vendor/github.com/go-ini/ini/README_ZH.md | 577 + vendor/github.com/go-ini/ini/ini.go | 1027 + vendor/github.com/go-ini/ini/parser.go | 312 + vendor/github.com/go-ini/ini/struct.go | 351 + vendor/github.com/golang/protobuf/LICENSE | 31 + .../github.com/golang/protobuf/proto/Makefile | 43 + .../github.com/golang/protobuf/proto/clone.go | 223 + .../golang/protobuf/proto/decode.go | 867 + .../golang/protobuf/proto/encode.go | 1325 + .../github.com/golang/protobuf/proto/equal.go | 276 + .../golang/protobuf/proto/extensions.go | 399 + .../github.com/golang/protobuf/proto/lib.go | 894 + .../golang/protobuf/proto/message_set.go | 280 + .../golang/protobuf/proto/pointer_reflect.go | 479 + .../golang/protobuf/proto/pointer_unsafe.go | 266 + .../golang/protobuf/proto/properties.go | 842 + .../protobuf/proto/proto3_proto/proto3.pb.go | 122 + .../protobuf/proto/proto3_proto/proto3.proto | 68 + .../github.com/golang/protobuf/proto/text.go | 751 + .../golang/protobuf/proto/text_parser.go | 806 + .../github.com/google/go-querystring/LICENSE | 27 + .../google/go-querystring/query/encode.go | 311 + vendor/github.com/hashicorp/atlas-go/LICENSE | 353 + .../hashicorp/atlas-go/archive/archive.go | 500 + .../test-fixtures/archive-dir-mode/file.txt | 1 + .../archive-file-compressed/file.tar.gz | Bin 0 -> 144 bytes .../test-fixtures/archive-file/foo.txt | 1 + .../test-fixtures/archive-flat/baz.txt | 1 + .../test-fixtures/archive-flat/foo.txt | 1 + .../archive-git/DOTgit/COMMIT_EDITMSG | 12 + .../test-fixtures/archive-git/DOTgit/HEAD | 1 + .../test-fixtures/archive-git/DOTgit/config | 13 + .../archive-git/DOTgit/description | 1 + .../DOTgit/hooks/applypatch-msg.sample | 15 + .../DOTgit/hooks/commit-msg.sample | 24 + .../DOTgit/hooks/post-update.sample | 8 + .../DOTgit/hooks/pre-applypatch.sample | 14 + .../DOTgit/hooks/pre-commit.sample | 49 + .../archive-git/DOTgit/hooks/pre-push.sample | 54 + .../DOTgit/hooks/pre-rebase.sample | 169 + .../DOTgit/hooks/prepare-commit-msg.sample | 36 + .../archive-git/DOTgit/hooks/update.sample | 128 + .../test-fixtures/archive-git/DOTgit/index | Bin 0 -> 256 bytes .../archive-git/DOTgit/info/exclude | 6 + .../archive-git/DOTgit/logs/HEAD | 1 + .../archive-git/DOTgit/logs/refs/heads/master | 1 + .../25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 | Bin 0 -> 19 bytes .../57/16ca5987cbf97d6bb54920bea6adde242d87e6 | Bin 0 -> 19 bytes .../75/25d17cbbb56f3253a20903ffddc07c6c935c76 | 4 + .../7e/49ea5550b356e32b63c044201f5f7da1e0925f | Bin 0 -> 54 bytes .../7f/7402c7d2a6e71ca3db3e236099771b160b8ad1 | Bin 0 -> 113 bytes .../archive-git/DOTgit/refs/heads/master | 1 + .../archive/test-fixtures/archive-git/bar.txt | 1 + .../archive/test-fixtures/archive-git/foo.txt | 1 + .../archive-git/subdir/hello.txt | 1 + .../test-fixtures/archive-git/untracked.txt | 1 + .../archive/test-fixtures/archive-hg/bar.txt | 1 + .../archive/test-fixtures/archive-hg/foo.txt | 1 + .../test-fixtures/archive-hg/subdir/hello.txt | 1 + .../archive-subdir-splat/bar.txt | 1 + .../build/darwin-amd64/build.txt | 1 + .../build/linux-amd64/build.txt | 1 + .../test-fixtures/archive-subdir/bar.txt | 1 + .../test-fixtures/archive-subdir/foo.txt | 1 + .../archive-subdir/subdir/hello.txt | 1 + .../test-fixtures/archive-symlink/link/link | 1 + .../archive-symlink/real/foo.txt | 0 .../hashicorp/atlas-go/archive/vcs.go | 365 + .../hashicorp/atlas-go/v1/application.go | 164 + .../hashicorp/atlas-go/v1/artifact.go | 248 + .../hashicorp/atlas-go/v1/authentication.go | 88 + .../hashicorp/atlas-go/v1/build_config.go | 183 + .../hashicorp/atlas-go/v1/client.go | 301 + .../hashicorp/atlas-go/v1/terraform.go | 97 + .../github.com/hashicorp/atlas-go/v1/util.go | 22 + vendor/github.com/hashicorp/errwrap/LICENSE | 354 + vendor/github.com/hashicorp/errwrap/README.md | 89 + .../github.com/hashicorp/errwrap/errwrap.go | 169 + .../hashicorp/go-checkpoint/LICENSE | 354 + .../hashicorp/go-checkpoint/README.md | 22 + .../hashicorp/go-checkpoint/checkpoint.go | 359 + .../github.com/hashicorp/go-cleanhttp/LICENSE | 363 + .../hashicorp/go-cleanhttp/README.md | 30 + .../hashicorp/go-cleanhttp/cleanhttp.go | 40 + .../hashicorp/go-multierror/LICENSE | 353 + .../hashicorp/go-multierror/README.md | 91 + .../hashicorp/go-multierror/append.go | 37 + .../hashicorp/go-multierror/flatten.go | 26 + .../hashicorp/go-multierror/format.go | 23 + .../hashicorp/go-multierror/multierror.go | 51 + .../hashicorp/go-multierror/prefix.go | 37 + .../hashicorp/go-version/.travis.yml | 11 + .../github.com/hashicorp/go-version/LICENSE | 354 + .../github.com/hashicorp/go-version/README.md | 65 + .../hashicorp/go-version/constraint.go | 156 + .../hashicorp/go-version/version.go | 251 + .../go-version/version_collection.go | 17 + vendor/github.com/hashicorp/yamux/.gitignore | 23 + vendor/github.com/hashicorp/yamux/LICENSE | 362 + vendor/github.com/hashicorp/yamux/README.md | 86 + vendor/github.com/hashicorp/yamux/addr.go | 60 + vendor/github.com/hashicorp/yamux/const.go | 157 + vendor/github.com/hashicorp/yamux/mux.go | 87 + vendor/github.com/hashicorp/yamux/session.go | 598 + vendor/github.com/hashicorp/yamux/spec.md | 141 + vendor/github.com/hashicorp/yamux/stream.go | 452 + vendor/github.com/hashicorp/yamux/util.go | 28 + vendor/github.com/hpcloud/tail/LICENSE.txt | 23 + .../hpcloud/tail/ratelimiter/Licence | 7 + .../hpcloud/tail/ratelimiter/leakybucket.go | 97 + .../hpcloud/tail/ratelimiter/memory.go | 58 + .../hpcloud/tail/ratelimiter/storage.go | 6 + vendor/github.com/hpcloud/tail/util/util.go | 47 + .../hpcloud/tail/watch/filechanges.go | 42 + .../github.com/hpcloud/tail/watch/inotify.go | 119 + .../hpcloud/tail/watch/inotify_tracker.go | 254 + .../github.com/hpcloud/tail/watch/polling.go | 119 + vendor/github.com/hpcloud/tail/watch/watch.go | 19 + .../hpcloud/tail/winfile/winfile.go | 92 + .../jmespath/go-jmespath/.gitignore | 4 + .../jmespath/go-jmespath/.travis.yml | 9 + .../github.com/jmespath/go-jmespath/LICENSE | 13 + .../github.com/jmespath/go-jmespath/Makefile | 44 + .../github.com/jmespath/go-jmespath/README.md | 7 + vendor/github.com/jmespath/go-jmespath/api.go | 49 + .../go-jmespath/astnodetype_string.go | 16 + .../go-jmespath/compliance/basic.json | 96 + .../go-jmespath/compliance/boolean.json | 257 + .../go-jmespath/compliance/current.json | 25 + .../go-jmespath/compliance/escape.json | 46 + .../go-jmespath/compliance/filters.json | 468 + .../go-jmespath/compliance/functions.json | 825 + .../go-jmespath/compliance/identifiers.json | 1377 + .../go-jmespath/compliance/indices.json | 346 + .../go-jmespath/compliance/literal.json | 185 + .../go-jmespath/compliance/multiselect.json | 393 + .../go-jmespath/compliance/ormatch.json | 59 + .../jmespath/go-jmespath/compliance/pipe.json | 131 + .../go-jmespath/compliance/slice.json | 187 + .../go-jmespath/compliance/syntax.json | 616 + .../go-jmespath/compliance/unicode.json | 38 + .../go-jmespath/compliance/wildcard.json | 460 + .../jmespath/go-jmespath/functions.go | 840 + .../jmespath/go-jmespath/fuzz/corpus/expr-1 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-10 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-100 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-101 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-102 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-103 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-104 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-105 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-106 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-107 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-108 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-109 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-110 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-112 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-115 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-118 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-119 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-12 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-120 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-121 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-122 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-123 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-126 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-128 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-129 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-13 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-130 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-131 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-132 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-133 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-134 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-135 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-136 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-137 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-138 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-139 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-14 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-140 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-141 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-142 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-143 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-144 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-145 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-146 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-147 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-148 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-149 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-15 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-150 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-151 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-152 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-153 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-155 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-156 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-157 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-158 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-159 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-16 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-160 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-161 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-162 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-163 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-164 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-165 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-166 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-167 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-168 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-169 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-17 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-170 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-171 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-172 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-173 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-174 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-175 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-178 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-179 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-18 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-180 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-181 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-182 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-183 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-184 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-185 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-186 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-187 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-188 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-189 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-19 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-190 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-191 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-192 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-193 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-194 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-195 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-196 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-198 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-199 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-2 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-20 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-200 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-201 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-202 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-203 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-204 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-205 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-206 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-207 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-208 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-209 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-21 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-210 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-211 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-212 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-213 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-214 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-215 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-216 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-217 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-218 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-219 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-22 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-220 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-221 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-222 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-223 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-224 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-225 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-226 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-227 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-228 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-229 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-23 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-230 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-231 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-232 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-233 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-234 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-235 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-236 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-237 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-238 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-239 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-24 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-240 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-241 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-242 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-243 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-244 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-245 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-246 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-247 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-248 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-249 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-25 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-250 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-251 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-252 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-253 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-254 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-255 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-256 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-257 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-258 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-259 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-26 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-260 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-261 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-262 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-263 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-264 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-265 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-266 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-267 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-268 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-269 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-27 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-270 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-271 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-272 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-273 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-274 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-275 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-276 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-277 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-278 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-279 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-28 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-280 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-281 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-282 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-283 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-284 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-285 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-286 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-287 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-288 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-289 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-29 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-290 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-291 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-292 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-293 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-294 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-295 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-296 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-297 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-298 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-299 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-3 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-30 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-300 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-301 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-302 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-303 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-304 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-305 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-306 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-307 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-308 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-309 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-31 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-310 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-311 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-312 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-313 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-314 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-315 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-316 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-317 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-318 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-319 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-32 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-320 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-321 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-322 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-323 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-324 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-325 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-326 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-327 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-328 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-329 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-33 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-330 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-331 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-332 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-333 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-334 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-335 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-336 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-337 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-338 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-339 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-34 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-340 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-341 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-342 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-343 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-344 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-345 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-346 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-347 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-348 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-349 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-35 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-350 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-351 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-352 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-353 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-354 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-355 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-356 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-357 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-358 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-359 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-36 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-360 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-361 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-362 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-363 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-364 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-365 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-366 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-367 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-368 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-369 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-37 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-370 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-371 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-372 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-373 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-374 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-375 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-376 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-377 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-378 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-379 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-38 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-380 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-381 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-382 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-383 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-384 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-385 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-386 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-387 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-388 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-389 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-39 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-390 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-391 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-392 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-393 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-394 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-395 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-396 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-397 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-398 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-399 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-4 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-40 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-400 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-401 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-402 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-403 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-404 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-405 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-406 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-407 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-408 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-409 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-41 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-410 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-411 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-412 | 2 + .../jmespath/go-jmespath/fuzz/corpus/expr-413 | 2 + .../jmespath/go-jmespath/fuzz/corpus/expr-414 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-415 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-416 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-417 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-418 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-419 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-42 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-420 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-421 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-422 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-423 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-424 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-425 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-426 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-427 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-428 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-429 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-43 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-430 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-431 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-432 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-433 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-434 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-435 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-436 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-437 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-438 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-439 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-44 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-440 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-441 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-442 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-443 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-444 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-445 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-446 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-447 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-448 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-449 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-45 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-450 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-451 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-452 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-453 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-454 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-455 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-456 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-457 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-458 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-459 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-46 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-460 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-461 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-462 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-463 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-464 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-465 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-466 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-467 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-468 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-469 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-47 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-470 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-471 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-472 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-473 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-474 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-475 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-476 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-477 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-478 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-479 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-48 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-480 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-481 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-482 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-483 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-484 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-485 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-486 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-487 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-488 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-489 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-49 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-490 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-491 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-492 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-493 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-494 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-495 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-496 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-497 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-498 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-499 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-5 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-50 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-500 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-501 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-502 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-503 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-504 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-505 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-506 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-507 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-508 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-509 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-51 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-510 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-511 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-512 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-513 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-514 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-515 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-516 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-517 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-518 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-519 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-52 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-520 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-521 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-522 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-523 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-524 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-525 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-526 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-527 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-528 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-529 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-53 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-530 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-531 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-532 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-533 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-534 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-535 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-536 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-537 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-538 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-539 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-54 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-540 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-541 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-542 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-543 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-544 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-545 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-546 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-547 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-548 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-549 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-55 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-550 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-551 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-552 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-553 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-554 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-555 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-556 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-557 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-558 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-559 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-56 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-560 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-561 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-562 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-563 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-564 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-565 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-566 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-567 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-568 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-569 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-57 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-570 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-571 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-572 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-573 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-574 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-575 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-576 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-577 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-578 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-579 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-58 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-580 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-581 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-582 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-583 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-584 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-585 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-586 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-587 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-588 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-589 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-59 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-590 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-591 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-592 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-593 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-594 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-595 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-596 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-597 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-598 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-599 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-6 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-60 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-600 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-601 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-602 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-603 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-604 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-605 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-606 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-607 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-608 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-609 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-61 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-610 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-611 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-612 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-613 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-614 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-615 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-616 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-617 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-618 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-619 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-62 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-620 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-621 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-622 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-623 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-624 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-625 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-626 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-627 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-628 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-629 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-63 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-630 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-631 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-632 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-633 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-634 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-635 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-636 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-637 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-638 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-639 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-64 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-640 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-641 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-642 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-643 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-644 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-645 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-646 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-647 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-648 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-649 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-65 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-650 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-651 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-652 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-653 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-654 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-655 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-656 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-66 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-67 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-68 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-69 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-7 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-70 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-71 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-72 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-73 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-74 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-75 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-76 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-77 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-78 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-79 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-8 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-80 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-81 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-82 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-83 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-84 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-85 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-86 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-87 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-88 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-89 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-9 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-90 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-91 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-92 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-93 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-94 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-95 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-96 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-97 | 1 + .../jmespath/go-jmespath/fuzz/corpus/expr-98 | 1 + .../jmespath/go-jmespath/fuzz/jmespath.go | 13 + .../jmespath/go-jmespath/interpreter.go | 418 + .../github.com/jmespath/go-jmespath/lexer.go | 420 + .../github.com/jmespath/go-jmespath/parser.go | 603 + .../jmespath/go-jmespath/toktype_string.go | 16 + .../github.com/jmespath/go-jmespath/util.go | 185 + vendor/github.com/kardianos/osext/LICENSE | 27 + vendor/github.com/kardianos/osext/README.md | 16 + vendor/github.com/kardianos/osext/osext.go | 33 + .../github.com/kardianos/osext/osext_plan9.go | 20 + .../kardianos/osext/osext_procfs.go | 36 + .../kardianos/osext/osext_sysctl.go | 126 + .../kardianos/osext/osext_windows.go | 34 + vendor/github.com/klauspost/compress/LICENSE | 27 + .../klauspost/compress/flate/copy.go | 32 + .../klauspost/compress/flate/crc32_amd64.go | 39 + .../klauspost/compress/flate/crc32_amd64.s | 212 + .../klauspost/compress/flate/crc32_noasm.go | 34 + .../klauspost/compress/flate/deflate.go | 1327 + .../klauspost/compress/flate/fixedhuff.go | 78 + .../klauspost/compress/flate/gen.go | 265 + .../compress/flate/huffman_bit_writer.go | 778 + .../klauspost/compress/flate/huffman_code.go | 363 + .../klauspost/compress/flate/inflate.go | 846 + .../klauspost/compress/flate/reverse_bits.go | 48 + .../klauspost/compress/flate/snappy.go | 96 + .../klauspost/compress/flate/token.go | 105 + vendor/github.com/klauspost/cpuid/.gitignore | 24 + vendor/github.com/klauspost/cpuid/.travis.yml | 7 + vendor/github.com/klauspost/cpuid/LICENSE | 22 + vendor/github.com/klauspost/cpuid/README.md | 145 + vendor/github.com/klauspost/cpuid/cpuid.go | 1022 + vendor/github.com/klauspost/cpuid/cpuid_386.s | 40 + .../github.com/klauspost/cpuid/cpuid_amd64.s | 40 + .../klauspost/cpuid/detect_intel.go | 17 + .../github.com/klauspost/cpuid/detect_ref.go | 23 + vendor/github.com/klauspost/cpuid/generate.go | 3 + .../github.com/klauspost/cpuid/private-gen.go | 476 + .../klauspost/cpuid/private/README.md | 6 + .../klauspost/cpuid/private/cpuid.go | 987 + .../klauspost/cpuid/private/cpuid_386.s | 40 + .../klauspost/cpuid/private/cpuid_amd64.s | 40 + .../cpuid/private/cpuid_detect_intel.go | 17 + .../cpuid/private/cpuid_detect_ref.go | 23 + vendor/github.com/klauspost/crc32/.gitignore | 24 + vendor/github.com/klauspost/crc32/.travis.yml | 11 + vendor/github.com/klauspost/crc32/LICENSE | 28 + vendor/github.com/klauspost/crc32/README.md | 84 + vendor/github.com/klauspost/crc32/crc32.go | 182 + .../github.com/klauspost/crc32/crc32_amd64.go | 62 + .../github.com/klauspost/crc32/crc32_amd64.s | 237 + .../klauspost/crc32/crc32_amd64p32.go | 39 + .../klauspost/crc32/crc32_amd64p32.s | 67 + .../klauspost/crc32/crc32_generic.go | 28 + vendor/github.com/klauspost/pgzip/.gitignore | 24 + vendor/github.com/klauspost/pgzip/.travis.yml | 13 + vendor/github.com/klauspost/pgzip/GO_LICENSE | 27 + vendor/github.com/klauspost/pgzip/LICENSE | 22 + vendor/github.com/klauspost/pgzip/README.md | 115 + vendor/github.com/klauspost/pgzip/circle.yml | 7 + vendor/github.com/klauspost/pgzip/gunzip.go | 564 + vendor/github.com/klauspost/pgzip/gzip.go | 485 + vendor/github.com/kr/fs/LICENSE | 27 + vendor/github.com/kr/fs/Readme | 3 + vendor/github.com/kr/fs/filesystem.go | 36 + vendor/github.com/kr/fs/walk.go | 95 + vendor/github.com/masterzen/simplexml/LICENSE | 202 + .../masterzen/simplexml/dom/document.go | 35 + .../masterzen/simplexml/dom/element.go | 200 + .../masterzen/simplexml/dom/namespace.go | 10 + vendor/github.com/masterzen/winrm/LICENSE | 202 + .../github.com/masterzen/winrm/soap/header.go | 181 + .../masterzen/winrm/soap/message.go | 74 + .../masterzen/winrm/soap/namespaces.go | 37 + .../masterzen/winrm/winrm/client.go | 166 + .../masterzen/winrm/winrm/command.go | 210 + .../masterzen/winrm/winrm/endpoint.go | 22 + .../github.com/masterzen/winrm/winrm/http.go | 60 + .../masterzen/winrm/winrm/parameters.go | 20 + .../masterzen/winrm/winrm/powershell.go | 22 + .../masterzen/winrm/winrm/request.go | 116 + .../masterzen/winrm/winrm/response.go | 111 + .../github.com/masterzen/winrm/winrm/shell.go | 31 + vendor/github.com/masterzen/xmlpath/LICENSE | 185 + vendor/github.com/masterzen/xmlpath/doc.go | 95 + vendor/github.com/masterzen/xmlpath/parser.go | 233 + vendor/github.com/masterzen/xmlpath/path.go | 642 + vendor/github.com/mattn/go-isatty/LICENSE | 9 + vendor/github.com/mattn/go-isatty/README.md | 37 + vendor/github.com/mattn/go-isatty/doc.go | 2 + .../mattn/go-isatty/isatty_appengine.go | 9 + .../github.com/mattn/go-isatty/isatty_bsd.go | 18 + .../mattn/go-isatty/isatty_linux.go | 18 + .../mattn/go-isatty/isatty_solaris.go | 16 + .../mattn/go-isatty/isatty_windows.go | 19 + vendor/github.com/mitchellh/cli/.travis.yml | 14 + vendor/github.com/mitchellh/cli/LICENSE | 354 + vendor/github.com/mitchellh/cli/README.md | 61 + vendor/github.com/mitchellh/cli/cli.go | 440 + vendor/github.com/mitchellh/cli/command.go | 47 + .../github.com/mitchellh/cli/command_mock.go | 42 + vendor/github.com/mitchellh/cli/help.go | 79 + vendor/github.com/mitchellh/cli/ui.go | 187 + vendor/github.com/mitchellh/cli/ui_colored.go | 69 + .../github.com/mitchellh/cli/ui_concurrent.go | 54 + vendor/github.com/mitchellh/cli/ui_mock.go | 64 + vendor/github.com/mitchellh/cli/ui_writer.go | 18 + vendor/github.com/mitchellh/go-fs/LICENSE | 21 + vendor/github.com/mitchellh/go-fs/README.md | 90 + .../mitchellh/go-fs/block_device.go | 22 + .../github.com/mitchellh/go-fs/directory.go | 18 + .../mitchellh/go-fs/fat/boot_sector.go | 347 + .../mitchellh/go-fs/fat/cluster_chain.go | 91 + .../mitchellh/go-fs/fat/directory.go | 278 + .../mitchellh/go-fs/fat/directory_cluster.go | 438 + vendor/github.com/mitchellh/go-fs/fat/fat.go | 268 + vendor/github.com/mitchellh/go-fs/fat/file.go | 26 + .../mitchellh/go-fs/fat/filesystem.go | 57 + .../mitchellh/go-fs/fat/short_name.go | 166 + .../mitchellh/go-fs/fat/super_floppy.go | 250 + vendor/github.com/mitchellh/go-fs/fat/type.go | 26 + vendor/github.com/mitchellh/go-fs/file.go | 9 + .../github.com/mitchellh/go-fs/file_disk.go | 52 + .../github.com/mitchellh/go-fs/filesystem.go | 8 + .../github.com/mitchellh/go-homedir/LICENSE | 21 + .../github.com/mitchellh/go-homedir/README.md | 14 + .../mitchellh/go-homedir/homedir.go | 132 + vendor/github.com/mitchellh/go-vnc/LICENSE | 21 + vendor/github.com/mitchellh/go-vnc/README.md | 16 + vendor/github.com/mitchellh/go-vnc/client.go | 482 + .../mitchellh/go-vnc/client_auth.go | 124 + vendor/github.com/mitchellh/go-vnc/color.go | 6 + .../github.com/mitchellh/go-vnc/encoding.go | 69 + .../mitchellh/go-vnc/pixel_format.go | 151 + vendor/github.com/mitchellh/go-vnc/pointer.go | 16 + .../mitchellh/go-vnc/server_messages.go | 192 + vendor/github.com/mitchellh/iochan/LICENSE.md | 21 + vendor/github.com/mitchellh/iochan/README.md | 13 + vendor/github.com/mitchellh/iochan/iochan.go | 41 + .../mitchellh/mapstructure/.travis.yml | 7 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 151 + .../mitchellh/mapstructure/error.go | 50 + .../mitchellh/mapstructure/mapstructure.go | 745 + .../github.com/mitchellh/multistep/LICENSE.md | 22 + .../github.com/mitchellh/multistep/README.md | 59 + .../mitchellh/multistep/basic_runner.go | 102 + .../mitchellh/multistep/debug_runner.go | 110 + .../mitchellh/multistep/multistep.go | 48 + .../mitchellh/multistep/statebag.go | 47 + vendor/github.com/mitchellh/panicwrap/LICENSE | 21 + .../github.com/mitchellh/panicwrap/README.md | 108 + .../mitchellh/panicwrap/panicwrap.go | 309 + .../github.com/mitchellh/prefixedio/LICENSE | 19 + .../github.com/mitchellh/prefixedio/README.md | 30 + .../github.com/mitchellh/prefixedio/reader.go | 220 + .../github.com/mitchellh/reflectwalk/LICENSE | 21 + .../mitchellh/reflectwalk/README.md | 6 + .../mitchellh/reflectwalk/location.go | 17 + .../mitchellh/reflectwalk/location_string.go | 16 + .../mitchellh/reflectwalk/reflectwalk.go | 279 + vendor/github.com/nu7hatch/gouuid/.gitignore | 11 + vendor/github.com/nu7hatch/gouuid/COPYING | 19 + vendor/github.com/nu7hatch/gouuid/README.md | 21 + vendor/github.com/nu7hatch/gouuid/uuid.go | 173 + .../packer-community/winrmcp/LICENSE | 22 + .../packer-community/winrmcp/winrmcp/cp.go | 200 + .../winrmcp/winrmcp/endpoint.go | 42 + .../packer-community/winrmcp/winrmcp/ls.go | 71 + .../packer-community/winrmcp/winrmcp/path.go | 18 + .../winrmcp/winrmcp/psobject.go | 17 + .../winrmcp/winrmcp/winrmcp.go | 117 + vendor/github.com/pierrec/lz4/.travis.yml | 9 + vendor/github.com/pierrec/lz4/LICENSE | 28 + vendor/github.com/pierrec/lz4/README.md | 31 + vendor/github.com/pierrec/lz4/block.go | 445 + ...1572067d493db8dc8161f05c339a5192b0b4087-22 | Bin 0 -> 105 bytes ...02766f768fbfbd81b752cce427eb5242a44929cc-5 | Bin 0 -> 19 bytes ...32f04032e12567057782672bb12670c20d38439-10 | Bin 0 -> 23 bytes ...367b985641aca66e6e4eeea68acf5e2a02c62a8-16 | Bin 0 -> 38 bytes ...03e85abc49352b2f7cc83efd7e4274da02d78b84-6 | Bin 0 -> 13 bytes ...049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 | Bin 0 -> 19 bytes ...04c05c7956f17e57a91a47909bd0706135cf17a6-1 | Bin 0 -> 46 bytes ...50e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 | Bin 0 -> 84 bytes ...0547c73efb9b6a345fd9a52aa0798b48dd9aca62-2 | Bin 0 -> 33 bytes ...5aae2cf8756f66066cf623618042ebaa92ec745-14 | Bin 0 -> 73 bytes ...07fe3e792f0d2862dccc04db22c0e4aef4d41b49-6 | Bin 0 -> 12 bytes ...990ac54decbca1a97893e83c7feb2be89cb10ea-14 | Bin 0 -> 68 bytes ...9f2eda28ecc97304659afded4d13a188baf2107-22 | Bin 0 -> 51 bytes ...a4ff2ab3a01888686c5bc358b72be108bbb4721-16 | Bin 0 -> 20 bytes ...a7fddf3c8aa1c781223748129c9dc0807de3a6b-28 | Bin 0 -> 51 bytes ...0b5bec228930b2cfcda3be9a39107a6bc8044f1e-3 | Bin 0 -> 16 bytes ...ca5fd3841a6777873c7ef26f65a384e7b15d065-18 | Bin 0 -> 61 bytes ...0ce9c3bac93df0ea1f6343d223d5220f9eb2383a-8 | Bin 0 -> 22 bytes ...cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 | Bin 0 -> 48 bytes ...0d7c02d4e91d82b0355baaca1237062639442db6-3 | 1 + ...0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 | Bin 0 -> 21 bytes .../github.com/pierrec/lz4/fuzz/corpus/1.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/10.bz2 | Bin 0 -> 14 bytes ...06b9d718c97bb7c872847d3070a570e99d9fa3e-22 | Bin 0 -> 82 bytes ...0fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/11.bz2 | Bin 0 -> 14 bytes ...113a12cbb28b83fcee714d58c35bbf52c0740e90-7 | Bin 0 -> 21 bytes .../github.com/pierrec/lz4/fuzz/corpus/12.bz2 | Bin 0 -> 14 bytes ...288161f8ce422490f63f257ce7338ef90fb8827-15 | Bin 0 -> 70 bytes .../github.com/pierrec/lz4/fuzz/corpus/13.bz2 | Bin 0 -> 14 bytes ...36f7224ae337a61df2e72b80af8b1aaa5933af3-10 | Bin 0 -> 21 bytes ...3c3c26f7a34d01fc89c92ca8ba2ba5ae430c225-16 | Bin 0 -> 38 bytes ...3db64707d1ea3070b4a37b6c1291d6125acbbd3-10 | Bin 0 -> 22 bytes .../github.com/pierrec/lz4/fuzz/corpus/14.bz2 | Bin 0 -> 14 bytes ...4193748a7b6cda204b11d042a35635151e90dbb-20 | Bin 0 -> 65 bytes ...42d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 | Bin 0 -> 83 bytes .../github.com/pierrec/lz4/fuzz/corpus/15.bz2 | Bin 0 -> 14 bytes ...5663b854e9a4f193502ea6463dae38b4d8fca90-19 | Bin 0 -> 71 bytes ...15e223354eb5378a7ee74a41dfab28ffc895ca33-1 | Bin 0 -> 55 bytes .../github.com/pierrec/lz4/fuzz/corpus/16.bz2 | Bin 0 -> 14 bytes .../github.com/pierrec/lz4/fuzz/corpus/17.bz2 | Bin 0 -> 14 bytes ...177c1c68fead4507aa47dd2455fd17a10ceda5ea-1 | Bin 0 -> 31 bytes .../github.com/pierrec/lz4/fuzz/corpus/18.bz2 | Bin 0 -> 14 bytes ...80a2772b126d31abcb3ef692a14b13cf47f103e-17 | Bin 0 -> 38 bytes .../github.com/pierrec/lz4/fuzz/corpus/19.bz2 | Bin 0 -> 48 bytes ...91e0dd24b8c7f8babeae4839768df39acc17eb1-17 | Bin 0 -> 32 bytes ...1a582381781f264f551bd6f0f2284a931147e6d9-4 | Bin 0 -> 9 bytes ...c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 | Bin 0 -> 105 bytes ...1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 | 1 + ...1d6b87b52e62cb84be834478ad88129f5e1f247b-9 | Bin 0 -> 32 bytes ...1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 | 1 + ...fc2ba0bb981fec47badea1c80219452c9e3c76c-22 | Bin 0 -> 88 bytes ...1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 | Bin 0 -> 29 bytes .../github.com/pierrec/lz4/fuzz/corpus/2.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/20.bz2 | Bin 0 -> 48 bytes ...02a9c8b188cae90f29bce3bf0438a035c504eb4-20 | Bin 0 -> 62 bytes ...0cf0057443ecb322ff1169ecbe6cf20250f15af-13 | Bin 0 -> 32 bytes ...0d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 | Bin 0 -> 46 bytes .../github.com/pierrec/lz4/fuzz/corpus/21.bz2 | Bin 0 -> 48 bytes .../github.com/pierrec/lz4/fuzz/corpus/22.bz2 | Bin 0 -> 48 bytes ...2201e32d052c15874f0323a09c330f3666029a72-1 | Bin 0 -> 1473 bytes ...26780b32ba8f87ec614fdb376aa0884011c4ca9-17 | Bin 0 -> 32 bytes ...2897c61698649d7570de91613afdc19b66e6965-20 | Bin 0 -> 71 bytes .../github.com/pierrec/lz4/fuzz/corpus/23.bz2 | Bin 0 -> 48 bytes ...34cc427d9be32470f3c2e11a6bc16567f558e55-22 | Bin 0 -> 37 bytes .../github.com/pierrec/lz4/fuzz/corpus/24.bz2 | Bin 0 -> 48 bytes ...2486a84bf0f161f45b050d9c19ea9e35f5def864-8 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/25.bz2 | Bin 0 -> 48 bytes ...5252b16cd4afa8ef86122448688c7095684c86b-12 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/26.bz2 | Bin 0 -> 48 bytes ...63fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 | Bin 0 -> 32 bytes .../github.com/pierrec/lz4/fuzz/corpus/27.bz2 | Bin 0 -> 48 bytes ...76580343a14eec04143e89a778dae3e14df472c-17 | Bin 0 -> 52 bytes ...27fb5dc4016dc640e55a60719a222c38c604fa6b-2 | Bin 0 -> 14 bytes .../github.com/pierrec/lz4/fuzz/corpus/28.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/29.bz2 | Bin 0 -> 157 bytes ...2a08d7c56ff9959698688f19ddd2e1e4d4651270-3 | 1 + ...a33d8514fb512aa20b0a56800cd3e12f3952b6b-26 | Bin 0 -> 51 bytes ...2a52400dd3aa2d2a40657d1e51c47c1929912927-3 | Bin 0 -> 18 bytes ...ab005ac79cd4dada693dd2a747c001898d45e1e-16 | Bin 0 -> 43 bytes ...2b39aa66ecfac58e61185c9664a968233931496a-9 | 1 + ...c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 | Bin 0 -> 70 bytes ...cc2308b75a2e8f7eafcf69370767e5fce314892-13 | Bin 0 -> 32 bytes ...cdafdadb156e2759c389b6b8edf6a402034886c-26 | Bin 0 -> 51 bytes ...2d7f0171116eec9984eaa9138e1312e90a7d67ee-1 | Bin 0 -> 47 bytes ...de93224b5f0db491ced1ec491a9f41d71820671-11 | Bin 0 -> 23 bytes ...2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 | Bin 0 -> 25 bytes ...2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 | Bin 0 -> 23 bytes ...f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 | Bin 0 -> 167 bytes ...fad20024167a500cdb8df5334a614f113efae00-20 | Bin 0 -> 76 bytes .../github.com/pierrec/lz4/fuzz/corpus/3.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/30.bz2 | Bin 0 -> 157 bytes ...00579a548d96d64c9da8470efa15e787f1a36f1-28 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/31.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/32.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/33.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/34.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/35.bz2 | Bin 0 -> 157 bytes .../github.com/pierrec/lz4/fuzz/corpus/36.bz2 | Bin 0 -> 157 bytes ...363d4559cac10516289fe1b6029590c4c7a6d8eb-5 | Bin 0 -> 12 bytes .../github.com/pierrec/lz4/fuzz/corpus/37.bz2 | Bin 0 -> 58 bytes ...771c6e8ea0f20350dae0180a9b14e36b8aef244-22 | Bin 0 -> 71 bytes ...37ee7fab504f2d2039753d73dd0290c884bd57bf-8 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/38.bz2 | Bin 0 -> 58 bytes .../github.com/pierrec/lz4/fuzz/corpus/39.bz2 | Bin 0 -> 58 bytes ...96101a712463bb336a18f4096fc3eb5923600c1-10 | Bin 0 -> 74 bytes ...97127b75cb59b253ed49206082b0428b6b23d02-17 | Bin 0 -> 43 bytes ...9ccf446395ef707cf92a04b5508deda399372c2-15 | Bin 0 -> 32 bytes ...3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 | Bin 0 -> 25 bytes ...3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 | Bin 0 -> 22 bytes ...3e34341fb51769fd9d948bdd20c011e335b145f4-1 | Bin 0 -> 64 bytes ...3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/4.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/40.bz2 | Bin 0 -> 58 bytes ...05726718b3f54a0cfae1666f06d3cc1ee747104-14 | Bin 0 -> 27 bytes ...07188676d45d6f9dd5f3c84e7df0e763c7cca57-22 | Bin 0 -> 82 bytes ...08ac1a4a83e082e848c208eed903930d81e81b6-17 | Bin 0 -> 67 bytes .../github.com/pierrec/lz4/fuzz/corpus/41.bz2 | Bin 0 -> 58 bytes ...413e39442f005279560ddad02bbdd1a05c9f0eaf-4 | 1 + ...41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 | Bin 0 -> 9 bytes .../github.com/pierrec/lz4/fuzz/corpus/42.bz2 | Bin 0 -> 58 bytes ...208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 | Bin 0 -> 35 bytes ...421bd1daa317c5d67fa21879de29d062c342294b-5 | Bin 0 -> 19 bytes ...2b056f9dac9cc658c80092e490b3dbcd436e3f8-15 | Bin 0 -> 32 bytes .../github.com/pierrec/lz4/fuzz/corpus/43.bz2 | Bin 0 -> 58 bytes ...432c09281c46537c98864bc7d601780562b68410-1 | Bin 0 -> 22 bytes .../github.com/pierrec/lz4/fuzz/corpus/44.bz2 | Bin 0 -> 58 bytes ...46dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 | Bin 0 -> 81 bytes .../github.com/pierrec/lz4/fuzz/corpus/45.bz2 | Bin 0 -> 58 bytes ...51831159c1afb87077066147630b4b6caeb54c3-11 | Bin 0 -> 25 bytes .../github.com/pierrec/lz4/fuzz/corpus/46.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/47.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/48.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/49.bz2 | Bin 0 -> 82 bytes ...49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 | Bin 0 -> 35 bytes ...9a3ead0ad96e8da5a4c8f89bd140e1d8af8995a-17 | Bin 0 -> 128 bytes ...a625a4b4f3069707e88f16db88e993dabc41aa2-27 | Bin 0 -> 51 bytes ...a6464c2aba2492f5122856de7ac451994eadda4-10 | Bin 0 -> 20 bytes ...b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 | Bin 0 -> 71 bytes ...4b55f37e6637f4246a41caa490da4bec632379d4-7 | Bin 0 -> 21 bytes ...4bb422b835278e4aca92d076331d9c8cc5752345-1 | Bin 0 -> 47 bytes ...bd00d26b893ce064dad6e771f30541b541d43b9-18 | Bin 0 -> 114 bytes ...cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 | Bin 0 -> 83 bytes ...d1b64babe1f045b8374f4d74949622591546eb5-17 | Bin 0 -> 56 bytes ...d49686993529cfe29473c50b9b0fb2b6ea4f6bf-13 | Bin 0 -> 25 bytes ...4ea726d6736026a733707e695d9c2cdc83efc05b-5 | Bin 0 -> 32 bytes ...ef3e6d20ccec24376a526ab9ec9f6f2cc604129-25 | Bin 0 -> 147 bytes .../github.com/pierrec/lz4/fuzz/corpus/5.bz2 | Bin 0 -> 42 bytes .../github.com/pierrec/lz4/fuzz/corpus/50.bz2 | Bin 0 -> 82 bytes ...0a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 | Bin 0 -> 105 bytes ...0e3ac1126c605158726db6f2cca3120f99b8e73-22 | Bin 0 -> 105 bytes .../github.com/pierrec/lz4/fuzz/corpus/51.bz2 | Bin 0 -> 82 bytes ...12ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 | Bin 0 -> 195 bytes ...514a62216c761adf23d946f11c0d1a0410990641-3 | Bin 0 -> 15 bytes ...16d84c21ac984bd1cae56910d71b62e39610c5d-29 | Bin 0 -> 51 bytes .../github.com/pierrec/lz4/fuzz/corpus/52.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/53.bz2 | Bin 0 -> 82 bytes .../github.com/pierrec/lz4/fuzz/corpus/54.bz2 | Bin 0 -> 82 bytes ...5431cabbc58d8dc143ece079de40300c1ce6e101-1 | Bin 0 -> 144 bytes ...5700385089e16e44968ea410c6b90206b16d72a-14 | Bin 0 -> 20 bytes ...55b9a902445e2bfa2f0f37d630779d329eeda20e-1 | Bin 0 -> 33 bytes ...620a492eaf067734e5b8b64517b28ec3beaa97e-12 | Bin 0 -> 46 bytes ...5699fea659964d8ab94069d08b0b97834c0a42df-2 | 1 + ...765fc21629571e51adf2fc2bc8b64541a1ea08d-18 | Bin 0 -> 81 bytes ...768ea5d1911143f4b1c0585b9b864ebe16aa004-12 | Bin 0 -> 33 bytes ...7b780437f4abf2d5cba0775bf802a4dfdb067d6-25 | Bin 0 -> 195 bytes ...8f53d40265c9a49c0d3b4292cb637464a4e376a-17 | Bin 0 -> 35 bytes ...59b254c3565c9eed2bc93385b821da897afcbb15-1 | Bin 0 -> 44 bytes ...a962e3d6a128983afe9ea78a28cce0f40a790c0-14 | Bin 0 -> 42 bytes ...af52ef91b6f717ffdd805585e24806407e9621b-14 | Bin 0 -> 114 bytes ...5b01aeb030dc1dc9568fd32f1647d92f0692a411-6 | 1 + ...bbd27cea704a4e6ff3f42f4792a91eb7839bc0d-12 | Bin 0 -> 28 bytes ...5bd895c23369df9505dd99ffcd035dc5e897264b-1 | Bin 0 -> 49 bytes ...5bfd84d7b2ba6b6325d5135fb0a9ae1ec5d7d3e1-2 | Bin 0 -> 48 bytes ...5c4f347c3567baf700dfccf49a91192c83b89da2-8 | 1 + ...5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 | Bin 0 -> 38 bytes ...ddf63d61aa38da1d409e37b301e0fe5a207a051-27 | Bin 0 -> 156 bytes ...e54c67050ee8583c7453ff13d6eec15b2255288-20 | Bin 0 -> 83 bytes ...5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 | 1 + .../github.com/pierrec/lz4/fuzz/corpus/6.bz2 | Bin 0 -> 42 bytes ...046b14dd1f6925bcfe470a8484353f525db6a9c-19 | Bin 0 -> 57 bytes ...608a9993a51ec7bf252ac76b163def5f7002d2e4-4 | 1 + ...610d8dc3cf4012e4e2d070988b0720285a4c361e-7 | Bin 0 -> 21 bytes ...1b196987682fb64ef9c4ff37532bf9b2ac201bc-14 | Bin 0 -> 30 bytes ...26f8b6efa3ea0f254789fe6cf52f6e52538f357-25 | Bin 0 -> 219 bytes ...6277f2e0a6df2ac61660ee1965c690b87c26b556-7 | Bin 0 -> 21 bytes ...2c738f00c488f493989b2037d9cf1781f0bbd40-11 | Bin 0 -> 38 bytes ...631ffa88df9713a124b3ba6c704c0c75727af2ff-6 | Bin 0 -> 16 bytes ...35d5de257a1910a7fd0db2e567edfa348e47270-11 | Bin 0 -> 38 bytes ...64c500b5addcbf8c673188a1477e4159851ae04f-1 | Bin 0 -> 124 bytes ...60387064a3cf4cb81046989929abe1b4fbfc815-17 | Bin 0 -> 51 bytes ...66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 | Bin 0 -> 16 bytes ...7ab3037ff49f082a877224d68e35069cc4d45eb-16 | Bin 0 -> 32 bytes ...69dcc80940a26844b0afe7898fea9cf68b698214-4 | Bin 0 -> 12 bytes ...a04b54e1511633ec895326b4e043e186fa5693b-29 | Bin 0 -> 171 bytes ...6a3e8935204dcd3dc48a1ff7415c305f0e5863aa-9 | Bin 0 -> 28 bytes ...b351674a45f2d9be602fe8d3fb84229551b4ce3-16 | Bin 0 -> 69 bytes ...b7f4ac7aa8b357dee3067d7a60143c03b54bb8d-16 | Bin 0 -> 42 bytes ...6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 | Bin 0 -> 46636 bytes ...6e14a407faae939957b80e641a836735bbdcad5a-2 | 1 + ...6f24be0bcac848e4e5b4b85bc60f70f12388a5ed-4 | 1 + .../github.com/pierrec/lz4/fuzz/corpus/7.bz2 | Bin 0 -> 42 bytes ...102c7f297296821114661e00e5bf54d0891d105-21 | Bin 0 -> 76 bytes ...151692dfebfc82876676e65ee9b807d83a3df54-22 | Bin 0 -> 92 bytes ...1a24ce771fb7f1a4163e57a478c3044ad42e62d-24 | Bin 0 -> 51 bytes ...2f032947602f1be74f01c91165c5118121f36c7-24 | Bin 0 -> 51 bytes ...3b6bd1462a0521b4bf76abb1fd80df6e180dc80-17 | Bin 0 -> 62 bytes ...3c81fef0997a4929b303e02a99f3977870f2013-29 | Bin 0 -> 159 bytes ...3efed803abadf6167fc3f04e0674cc39c30f6af-21 | Bin 0 -> 37 bytes ...603f5f266de813608c4cc1ccd1c798ef8065c5c-23 | Bin 0 -> 51 bytes ...67d1943125a0f6e9397779cc757c9cdd1e05631-17 | Bin 0 -> 62 bytes ...6d22068e2ed4a5952d4adc7ea8dada5509a784c-13 | Bin 0 -> 30 bytes ...740102922cb9933980bb800c1115daf38edf654-24 | Bin 0 -> 72 bytes ...83270b1e353ba3895b7d0c4135b8592e22f6508-12 | Bin 0 -> 56 bytes ...7851a406571c6b4c1aeed0af16db8c48444c3f2b-1 | Bin 0 -> 34 bytes ...78981d313038119ac4f7017349e50a1cba56b382-7 | Bin 0 -> 23 bytes ...8c88c4afaf5962056b1aea720509b9f6f286b91-15 | Bin 0 -> 64 bytes ...9c5ac978f5aee35e123f523369aa46b1d0a995d-11 | Bin 0 -> 26 bytes ...adf4aa021efaa953268c817467959fa3c42ca42-13 | Bin 0 -> 25 bytes ...7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 | 1 + ...7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 | 1 + ...cdc0917ad63ce7a7c98301a366c31635f0f099d-14 | Bin 0 -> 32 bytes ...7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 | Bin 0 -> 1452 bytes ...7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 | Bin 0 -> 8 bytes ...e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 | Bin 0 -> 135 bytes ...7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 | Bin 0 -> 26 bytes ...f970f16026c689c096a19fef1a3282a13ee69dc-20 | Bin 0 -> 65 bytes ...7fa96d28faf45062eb803ea84a334b607e966f90-1 | Bin 0 -> 31 bytes .../github.com/pierrec/lz4/fuzz/corpus/8.bz2 | Bin 0 -> 42 bytes ...261f0c1799ca71c411f6d3f34069b25dac8b739-18 | Bin 0 -> 52 bytes ...82afa534de59025bf1e3358919286525ae7d3347-2 | 1 + ...496965f7aa6cea3e080dbfb911a7034e6623cb7-10 | Bin 0 -> 23 bytes ...84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 | Bin 0 -> 10 bytes ...86513e3435adaf7c493dd50eb5de372010185e36-1 | 1 + ...6637b211f4fa0118ccab9ee193c66286126bb5d-20 | Bin 0 -> 35 bytes ...695984335fa005895377a8a60000a921d7efd99-10 | Bin 0 -> 25 bytes ...6baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 | Bin 0 -> 35 bytes ...8e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 | Bin 0 -> 25 bytes ...9216c662a46d50f37cfa08963acad8c6f7aace7-11 | Bin 0 -> 20 bytes ...8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 | 1 + ...f0d2862c49eebbcd473a38c8fa1e76288f47127-26 | Bin 0 -> 51 bytes ...f61ea021e02cc609baafbdf714b9577e4bcb05f-16 | Bin 0 -> 74 bytes ...8f7a47710904981ffaa1fefa21fa95fd2d818487-7 | Bin 0 -> 23 bytes .../github.com/pierrec/lz4/fuzz/corpus/9.bz2 | Bin 0 -> 42 bytes ...0a227d3beab730ed6eecd63657f5406beccabdf-12 | Bin 0 -> 39 bytes ...2197169aded0d5d0407e3925959e922257a101d-28 | Bin 0 -> 195 bytes ...24e17974cd194fa756d23394676d37cc3641f64-17 | Bin 0 -> 25 bytes ...92a785b5ea93d36e27029e281e9a34377d81ce55-5 | 1 + ...92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 | Bin 0 -> 40 bytes ...363b81db6b35e8beebcc32d560f786472829bd8-21 | Bin 0 -> 88 bytes ...48b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 | Bin 0 -> 32 bytes ...505b43fcbc3139441e35bdaaec138e28af076f6-25 | Bin 0 -> 91 bytes ...51bb02c199adb52e9e300e9fc070bf55980b910-14 | Bin 0 -> 25 bytes ...55404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 | Bin 0 -> 23 bytes ...67e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 | Bin 0 -> 28 bytes ...6c9a1fa8b0184ad486f8f68a9ddc88434579080-30 | Bin 0 -> 159 bytes ...6cc45abef3bc9fb6659714b9743cda92ec0abb9-16 | Bin 0 -> 38 bytes ...719ea029fdf8c837f991ac3548145485cc1f06e-13 | Bin 0 -> 73 bytes ...84480af27d1640fd02f40e736ffcde3a91e4abb-22 | Bin 0 -> 88 bytes ...8d40a50ee58c05727777e242ecbc0d4e214f7fe-21 | Bin 0 -> 35 bytes ...915e9bb007bc2c1f3d346123933923279f0dec1-27 | Bin 0 -> 51 bytes ...992413e17d64968cb04af34c7761182f20fc97b6-2 | Bin 0 -> 30 bytes ...9cfa74a1fea5d16168dd9efc720425b85e95eb7-15 | Bin 0 -> 32 bytes ...a552bab72f174ede3b9bdb7a663c963fd1463d3-16 | Bin 0 -> 32 bytes ...9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 | 1 + ...9be44693435bc6c51980f30418bcc690d8c25fe7-6 | 1 + ...c0420bf00f888487d543f42fc48b407c65d4717-17 | Bin 0 -> 95 bytes ...ca2a086f1f08c7dec54d52425bd72f17c11056e-21 | Bin 0 -> 37 bytes ...db70b1edad2317d94dcaafe7f5c5e3145084167-12 | Bin 0 -> 37 bytes .../fuzz/corpus/Mark.Twain-Tom.Sawyer.txt.bz2 | Bin 0 -> 124744 bytes ...01e13c3e401957031defb62b05434c65b01d5c4-10 | Bin 0 -> 31 bytes ...059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 | Bin 0 -> 38 bytes ...06b1a08fcda463f1d51c485b0e7271ff9048b41-16 | Bin 0 -> 35 bytes ...0f3d67e96968a267366be380147cbc7b17e5b2b-16 | Bin 0 -> 68 bytes ...18d849dc2a98c4ebb6000b2cc853f21fb64d9e5-24 | Bin 0 -> 195 bytes ...2e5916be780e35e9ecb7c42be52dd5e134f3363-25 | Bin 0 -> 195 bytes ...33252a74974fc86df30c311d501a1f363d350cd-12 | Bin 0 -> 33 bytes ...462f03ee666a20244d3331e3635b7eb796d906d-15 | Bin 0 -> 60 bytes ...a56e983782e49f8267a61d4375e98b1a862862ac-9 | Bin 0 -> 17 bytes ...58a9f9caca5e73b4296b931201a5ea870974c26-15 | Bin 0 -> 116 bytes ...a628194a08ff63e98625b1786175026c5f02c716-5 | Bin 0 -> 38 bytes ...64f2336fd4a9ec8153b95f40c383e1ecfed9e73-25 | Bin 0 -> 51 bytes ...a6a5682a6663e0c548c9e5acbad4958e2c256b32-7 | Bin 0 -> 60 bytes ...6dbaac639f3b82609ec27c80fbd003684c28867-21 | Bin 0 -> 61 bytes ...8c6a4509b61d8baa71f59f9e1eb95712b10626c-23 | Bin 0 -> 51 bytes ...9e348d9896cc740f7e910d0a70c080adb65cc77-13 | Bin 0 -> 34 bytes ...a04575587509ffc65a6b0224d24ad1125cb0f63-26 | Bin 0 -> 91 bytes ...a290b4dcc8198945311c8149fc1252f14555e70-15 | Bin 0 -> 63 bytes ...abb8fa4913c79f0a42494ad2215a32927adbd45-16 | Bin 0 -> 63 bytes ...c7077c5220abe6cd481318c42dfe6cb2cb2c666-10 | Bin 0 -> 40 bytes ...cbef0322169a93c7421902883cc8057675c953b-26 | Bin 0 -> 195 bytes ...ec95871bc7d87cae16c36a0d30955b43076aec5-17 | Bin 0 -> 35 bytes ...20e3f27f4e8d41f16124881f92546f0fb2edc16-13 | Bin 0 -> 33 bytes ...27fb21ecbe6e77c91341738621ad7092c29bca5-17 | Bin 0 -> 89 bytes ...38ce47b707326024fb24860c4365d58ab9f3528-29 | Bin 0 -> 166 bytes ...b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 | Bin 0 -> 9 bytes ...3fd355dc090a732d5cf3b25151f165ea901a682-24 | Bin 0 -> 51 bytes ...58846d79a8dc960a718ef88dd3a06ad49b1fe72-16 | Bin 0 -> 35 bytes ...b5b5b895b4619fa039ea99520b9947de2996c38f-6 | Bin 0 -> 16 bytes ...b6aca5c55295d93491e47817f46ca372c9078cec-3 | 1 + ...b6ddb90092b3087158dc32669529db2012f14c3c-7 | Bin 0 -> 20 bytes ...b6e7a519d013ddb67313af02a9ce966877949487-4 | Bin 0 -> 24 bytes ...b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 | Bin 0 -> 17 bytes ...7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 | Bin 0 -> 44 bytes ...7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 | Bin 0 -> 143 bytes ...83b3d04ada1403578065d7f10aa7441830dea3c-11 | Bin 0 -> 20 bytes ...94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 | Bin 0 -> 35 bytes ...ba98469ede70309f18893f0ff95380f5a0486fcd-6 | Bin 0 -> 52 bytes ...c0c31f304c1a1f8be0c8a0d9daa3b8aa1f23799-14 | Bin 0 -> 41 bytes ...c650b6a5356c1935f64f6fb755e43bc5f5187c4-26 | Bin 0 -> 195 bytes ...be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 | Bin 0 -> 66 bytes ...e5767f4d79c5a0b2643d8eddb74eca0598674dc-19 | Bin 0 -> 75 bytes ...07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 | Bin 0 -> 19 bytes ...2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 | Bin 0 -> 36 bytes ...2c3d29bce8aae89fed326832b3e1e1077cef1da-18 | Bin 0 -> 61 bytes ...c321670bbcd985327045dd1468bf2ac4ae7333e5-7 | Bin 0 -> 32 bytes ...34998d9a8893eca9cdeafe7b2482469ad98192b-25 | Bin 0 -> 51 bytes ...5522d11f314fc46de58e15116b6910d52acf866-17 | Bin 0 -> 69 bytes ...c652c46aba3567521f912bae6dc263b668c34c9c-7 | Bin 0 -> 17 bytes ...c6610b87900912d462229a5259dab51ea0aeef33-4 | 1 + ...c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 | Bin 0 -> 39 bytes ...c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 | Bin 0 -> 26 bytes ...77304b250e887b39b5447d19b9c106fcebe7e66-20 | Bin 0 -> 71 bytes ...78cd8530e6d8a606a28797552ce3f5494763621-25 | Bin 0 -> 195 bytes ...790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 | Bin 0 -> 88 bytes ...c7fe1fe2e3fc19fab3766f9fdb1d22c848d49aed-2 | Bin 0 -> 53 bytes ...a5d375d8a66727221d3e198d4ad360782944de7-27 | Bin 0 -> 195 bytes ...cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 | 1 + ...d67bf90feaeb1912792508afa01a09fe1f044c6-13 | Bin 0 -> 33 bytes ...cda434677d4bdd969a3bbf84086349f821e39c80-1 | Bin 0 -> 48 bytes ...fe7201e28d42484764264c231663e6372e95ef7-14 | Bin 0 -> 32 bytes ...ff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 | Bin 0 -> 32 bytes ...cffc7573debb5af80aaddfa752538825275fd6a9-7 | 1 + ...0ae058f71e53a7afd648b859cd7485886be550d-22 | Bin 0 -> 127 bytes ...0e6298a63ffc2695cf7d016a124db7375f197cf-21 | Bin 0 -> 88 bytes ...24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 | Bin 0 -> 49 bytes ...d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 | Bin 0 -> 58 bytes ...3ddffcd038a5646a53d48b684eac5b721c7062a-18 | Bin 0 -> 59 bytes ...4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 | Bin 0 -> 72 bytes ...d57eaf0fada8726afac2287cafb7720af7417b16-1 | 1 + ...d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 | Bin 0 -> 30 bytes ...d7855c38db11bfeeb474a4782f1ea293192f786f-1 | Bin 0 -> 42 bytes ...7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 | Bin 0 -> 51 bytes .../da39a3ee5e6b4b0d3255bfef95601890afd80709 | 0 ...da39a3ee5e6b4b0d3255bfef95601890afd80709-1 | 0 ...dba53c14b92561071ccd7762550d53cf43027bdf-1 | Bin 0 -> 32 bytes ...c61bdd2fb983111d1392cd79ba9b39e0a3b869f-20 | Bin 0 -> 71 bytes ...dcb49d3d45d32601fa27208cec33813e03ff6179-1 | Bin 0 -> 47 bytes ...dce9966b94744440d75a845a48c806041f5a6612-3 | Bin 0 -> 31 bytes ...d799919262810add464dbb4ee39a38f1e4ed258-13 | Bin 0 -> 25 bytes .../dd92516fbea2d0f96abc78f325d731053a451e16 | 1 + ...df986569f89016184b5b6e924d5ba827c9980ca-28 | Bin 0 -> 156 bytes ...e0acf1136a1e05cd27345ce135ea26abd32bbfe-18 | Bin 0 -> 36 bytes ...e33e3ef8a5780c7d3458188a423c00f470904d0-15 | Bin 0 -> 32 bytes ...de501127da94246b2d3aa947637b49fbc17d5e47-1 | 1 + ...e702cd20caeb08a843e0c09b0ce87a74e300415-20 | Bin 0 -> 71 bytes ...e8abda1b9bd5628ca99c8f97237fa885a857bb5-19 | Bin 0 -> 35 bytes ...def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 | Bin 0 -> 20 bytes ...f0768cf0c709a1ff1a93cc0dad23979501c54ff-21 | Bin 0 -> 115 bytes ...dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 | 1 + .../pierrec/lz4/fuzz/corpus/e.txt.bz2 | Bin 0 -> 43149 bytes ...1556049ba9794a15ee21aa283876bf63e531a4f-24 | Bin 0 -> 147 bytes ...e17af76e8c119233dbd2888ab519bd76d7aa7fe9-6 | Bin 0 -> 19 bytes ...346c715ac3187598d8c0453d9e741fae1232c99-11 | Bin 0 -> 29 bytes ...3acf6f2b5a1b97f5a82ebf7d1822077561583fe-26 | Bin 0 -> 195 bytes ...e4a2a1469de980756c607cdc2584fc94bc109382-1 | Bin 0 -> 58 bytes ...68b04a675d8d4192565a808955764c77ae510e6-16 | Bin 0 -> 122 bytes ...7ea1bfd65ca7db84f0984474658bfc3b063c63a-13 | Bin 0 -> 32 bytes ...ea212596f8a7aec4eb2e85fd2cdb5c2816b58495-5 | Bin 0 -> 12 bytes ...a9af92f89e6889b523461ae7b2b9fecee5a7280-18 | Bin 0 -> 130 bytes ...bc69b7ca13ae23b075c9b21ebc283278714e3aa-18 | Bin 0 -> 32 bytes ...c8e760e79dc08a79af0d79c510cafb74e504472-18 | Bin 0 -> 28 bytes ...c984b6fb8e41dbcd4299ecd1dd6fd0a77347122-13 | Bin 0 -> 32 bytes ...cbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 | Bin 0 -> 147 bytes ...cdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 | Bin 0 -> 33 bytes ...da1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 | Bin 0 -> 32 bytes ...dbc11de7dd074c367a69532db023cd810bb3978-13 | Bin 0 -> 43 bytes ...ee6afbf375619a2bd6fb0abe0e42e51ab3b0ab13-6 | Bin 0 -> 20 bytes ...ee907d38c1394c4971b389a99a3be0913836212b-9 | Bin 0 -> 72 bytes ...ebbefa1983c9e1aeb5217aabcac7ab24dfe166f-17 | Bin 0 -> 75 bytes ...ee3d4a9a8b297f016c23f50a9792c30a621720e-21 | Bin 0 -> 71 bytes ...ef87432939473264357babc06257b0280ffd15ee-5 | 1 + ...fdd522fe3abb88204f63b1fe7312f62b6ee593d-16 | Bin 0 -> 67 bytes ...35bdf2e8b4af93c6a73e564055aa4eacd9f0d0c-13 | Bin 0 -> 25 bytes ...f3a2381d6f39defe22520aea46201e6ce6d37f80-1 | Bin 0 -> 31 bytes ...f3e916907eab3412b5875e5eca05bf3eac8a8d5e-1 | Bin 0 -> 37 bytes ...f493376c3eda80cbe822ac456486734b72f891fc-2 | Bin 0 -> 44 bytes ...55efbb04cd32f7828e951d067319db00627153f-28 | Bin 0 -> 51 bytes ...71b4776ecbbe47746fb53d7749751c5c5bbff05-22 | Bin 0 -> 61 bytes ...724d4c839c012c7772618e28ef68d478cc00c74-21 | Bin 0 -> 37 bytes ...f86152e5ce510dc674fa73d20b324e2d3c4d145b-1 | 1 + ...f931bee2e7f1fefd8bb2fabf88f8f3d2b3ea78fa-2 | Bin 0 -> 36 bytes ...ac6c4165067ef2d87a23a2530a59eb560d470e0-23 | Bin 0 -> 51 bytes ...fb56a1001599e07354ce3101af111554c6c9bb40-1 | Bin 0 -> 60 bytes ...fb75f3059f8835a7e8781c899af756f22d1c06b4-7 | Bin 0 -> 13 bytes ...bfe35b0485040874ed564b94ba764bdd17e80fc-10 | Bin 0 -> 20 bytes ...cb1c8b1893ca85647581cadec481754d8f35c96-12 | Bin 0 -> 25 bytes ...cb33fb48e48acd9155fd7ed8e82e71c850ffd22-16 | Bin 0 -> 32 bytes ...fcd47a15e10a21e1eb13aeac223becc89aac4c69-2 | Bin 0 -> 38 bytes ...d4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 | Bin 0 -> 51 bytes ...db78af507e72288b059ff902ae5e76538d1e6ea-14 | Bin 0 -> 32 bytes ...fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 | Bin 0 -> 15 bytes ...e78d4faf4ce717d84938010f92ca5e844f9980b-13 | Bin 0 -> 24 bytes ...f3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 | Bin 0 -> 36 bytes ...f47856b8fa7323572c8b4a6d8028dcb2663a37a-11 | Bin 0 -> 84 bytes ...fa97253e1ab365b84eebb9d257f9370b7796fbf-28 | Bin 0 -> 51 bytes .../pierrec/lz4/fuzz/corpus/pss-vect.txt.bz2 | Bin 0 -> 28526 bytes .../0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 | Bin 0 -> 27 bytes ...fcd1f53d5bd839e5728ba92db050f5e0968.output | 51 + ...fcd1f53d5bd839e5728ba92db050f5e0968.quoted | 2 + .../169b44c5a64fec4d8e969d25d3e4764c9c3b604b | Bin 0 -> 66 bytes ...4c5a64fec4d8e969d25d3e4764c9c3b604b.output | 54 + ...4c5a64fec4d8e969d25d3e4764c9c3b604b.quoted | 4 + .../ea0a00651ba4143c05fe7b5c85f69fe16a29a458 | Bin 0 -> 19 bytes ...0651ba4143c05fe7b5c85f69fe16a29a458.output | 23 + ...0651ba4143c05fe7b5c85f69fe16a29a458.quoted | 1 + .../github.com/pierrec/lz4/fuzz/lz4-fuzz.zip | Bin 0 -> 2361685 bytes vendor/github.com/pierrec/lz4/fuzz/lz4.go | 45 + .../a596442269a13f32d85889a173f2d36187a768c6 | 1 + .../d159e91cdd6fcbee9e37460f96c597b70c590886 | 10 + vendor/github.com/pierrec/lz4/lz4.go | 104 + vendor/github.com/pierrec/lz4/lz4c/main.go | 105 + vendor/github.com/pierrec/lz4/reader.go | 364 + vendor/github.com/pierrec/lz4/writer.go | 370 + vendor/github.com/pierrec/xxHash/LICENSE | 28 + .../pierrec/xxHash/xxHash32/xxHash32.go | 205 + vendor/github.com/pkg/sftp/.gitignore | 8 + vendor/github.com/pkg/sftp/.travis.yml | 21 + vendor/github.com/pkg/sftp/CONTRIBUTORS | 2 + vendor/github.com/pkg/sftp/LICENSE | 9 + vendor/github.com/pkg/sftp/README.md | 29 + vendor/github.com/pkg/sftp/attrs.go | 237 + vendor/github.com/pkg/sftp/attrs_stubs.go | 11 + vendor/github.com/pkg/sftp/attrs_unix.go | 17 + vendor/github.com/pkg/sftp/client.go | 1211 + vendor/github.com/pkg/sftp/debug.go | 9 + .../examples/buffered-read-benchmark/main.go | 77 + .../examples/buffered-write-benchmark/main.go | 83 + .../pkg/sftp/examples/sftp-server/README.md | 12 + .../pkg/sftp/examples/sftp-server/main.go | 134 + .../examples/streaming-read-benchmark/main.go | 84 + .../streaming-write-benchmark/main.go | 84 + vendor/github.com/pkg/sftp/packet.go | 840 + vendor/github.com/pkg/sftp/release.go | 5 + vendor/github.com/pkg/sftp/server.go | 648 + .../pkg/sftp/server_standalone/main.go | 40 + vendor/github.com/pkg/sftp/server_stubs.go | 12 + vendor/github.com/pkg/sftp/server_unix.go | 143 + vendor/github.com/pkg/sftp/sftp.go | 215 + .../rackspace/gophercloud/.travis.yml | 16 + .../rackspace/gophercloud/CONTRIBUTING.md | 274 + .../rackspace/gophercloud/CONTRIBUTORS.md | 13 + .../github.com/rackspace/gophercloud/LICENSE | 191 + .../rackspace/gophercloud/README.md | 160 + .../rackspace/gophercloud/UPGRADING.md | 338 + .../gophercloud/acceptance/README.md | 57 + .../acceptance/openstack/compute/v2/pkg.go | 3 + .../acceptance/openstack/db/v1/common.go | 70 + .../acceptance/openstack/db/v1/pkg.go | 1 + .../acceptance/openstack/identity/v2/pkg.go | 1 + .../acceptance/openstack/identity/v3/pkg.go | 1 + .../openstack/networking/v2/common.go | 39 + .../networking/v2/extensions/fwaas/pkg.go | 1 + .../networking/v2/extensions/lbaas/common.go | 78 + .../networking/v2/extensions/lbaas/pkg.go | 1 + .../openstack/networking/v2/extensions/pkg.go | 1 + .../acceptance/openstack/networking/v2/pkg.go | 1 + .../openstack/objectstorage/v1/common.go | 28 + .../openstack/orchestration/v1/common.go | 44 + .../orchestration/v1/hello-compute.json | 13 + .../gophercloud/acceptance/openstack/pkg.go | 4 + .../rackspace/blockstorage/v1/common.go | 38 + .../acceptance/rackspace/cdn/v1/common.go | 23 + .../acceptance/rackspace/compute/v2/pkg.go | 1 + .../acceptance/rackspace/db/v1/common.go | 73 + .../acceptance/rackspace/db/v1/pkg.go | 1 + .../acceptance/rackspace/identity/v2/pkg.go | 1 + .../acceptance/rackspace/lb/v1/common.go | 62 + .../rackspace/networking/v2/common.go | 39 + .../rackspace/objectstorage/v1/common.go | 54 + .../rackspace/orchestration/v1/common.go | 45 + .../gophercloud/acceptance/rackspace/pkg.go | 1 + .../rackspace/rackconnect/v3/common.go | 26 + .../gophercloud/acceptance/tools/pkg.go | 1 + .../gophercloud/acceptance/tools/tools.go | 89 + .../rackspace/gophercloud/auth_options.go | 50 + .../rackspace/gophercloud/auth_results.go | 14 + .../github.com/rackspace/gophercloud/doc.go | 67 + .../rackspace/gophercloud/endpoint_search.go | 92 + .../gophercloud/openstack/auth_env.go | 58 + .../blockstorage/v1/apiversions/doc.go | 3 + .../blockstorage/v1/apiversions/requests.go | 21 + .../blockstorage/v1/apiversions/results.go | 58 + .../blockstorage/v1/apiversions/urls.go | 15 + .../blockstorage/v1/snapshots/doc.go | 5 + .../blockstorage/v1/snapshots/fixtures.go | 114 + .../blockstorage/v1/snapshots/requests.go | 206 + .../blockstorage/v1/snapshots/results.go | 123 + .../blockstorage/v1/snapshots/urls.go | 27 + .../blockstorage/v1/snapshots/util.go | 22 + .../openstack/blockstorage/v1/volumes/doc.go | 5 + .../blockstorage/v1/volumes/requests.go | 236 + .../blockstorage/v1/volumes/results.go | 113 + .../blockstorage/v1/volumes/testing/doc.go | 7 + .../v1/volumes/testing/fixtures.go | 113 + .../openstack/blockstorage/v1/volumes/urls.go | 23 + .../openstack/blockstorage/v1/volumes/util.go | 22 + .../blockstorage/v1/volumetypes/doc.go | 9 + .../blockstorage/v1/volumetypes/fixtures.go | 60 + .../blockstorage/v1/volumetypes/requests.go | 76 + .../blockstorage/v1/volumetypes/results.go | 72 + .../blockstorage/v1/volumetypes/urls.go | 19 + .../gophercloud/openstack/cdn/v1/base/doc.go | 4 + .../openstack/cdn/v1/base/fixtures.go | 53 + .../openstack/cdn/v1/base/requests.go | 21 + .../openstack/cdn/v1/base/results.go | 35 + .../gophercloud/openstack/cdn/v1/base/urls.go | 11 + .../openstack/cdn/v1/flavors/doc.go | 6 + .../openstack/cdn/v1/flavors/fixtures.go | 82 + .../openstack/cdn/v1/flavors/requests.go | 22 + .../openstack/cdn/v1/flavors/results.go | 71 + .../openstack/cdn/v1/flavors/urls.go | 11 + .../openstack/cdn/v1/serviceassets/doc.go | 7 + .../cdn/v1/serviceassets/fixtures.go | 19 + .../cdn/v1/serviceassets/requests.go | 48 + .../openstack/cdn/v1/serviceassets/results.go | 8 + .../openstack/cdn/v1/serviceassets/urls.go | 7 + .../openstack/cdn/v1/services/doc.go | 7 + .../openstack/cdn/v1/services/errors.go | 7 + .../openstack/cdn/v1/services/fixtures.go | 372 + .../openstack/cdn/v1/services/requests.go | 378 + .../openstack/cdn/v1/services/results.go | 316 + .../openstack/cdn/v1/services/urls.go | 23 + .../rackspace/gophercloud/openstack/client.go | 274 + .../gophercloud/openstack/common/README.md | 3 + .../openstack/common/extensions/doc.go | 15 + .../openstack/common/extensions/errors.go | 1 + .../openstack/common/extensions/fixtures.go | 91 + .../openstack/common/extensions/requests.go | 21 + .../openstack/common/extensions/results.go | 65 + .../openstack/common/extensions/urls.go | 13 + .../v2/extensions/bootfromvolume/requests.go | 111 + .../v2/extensions/bootfromvolume/results.go | 10 + .../v2/extensions/bootfromvolume/urls.go | 7 + .../compute/v2/extensions/defsecrules/doc.go | 1 + .../v2/extensions/defsecrules/fixtures.go | 108 + .../v2/extensions/defsecrules/requests.go | 95 + .../v2/extensions/defsecrules/results.go | 69 + .../compute/v2/extensions/defsecrules/urls.go | 13 + .../compute/v2/extensions/delegate.go | 23 + .../compute/v2/extensions/diskconfig/doc.go | 3 + .../v2/extensions/diskconfig/requests.go | 114 + .../v2/extensions/diskconfig/results.go | 60 + .../openstack/compute/v2/extensions/doc.go | 3 + .../compute/v2/extensions/floatingip/doc.go | 3 + .../v2/extensions/floatingip/fixtures.go | 193 + .../v2/extensions/floatingip/requests.go | 171 + .../v2/extensions/floatingip/results.go | 99 + .../compute/v2/extensions/floatingip/urls.go | 37 + .../compute/v2/extensions/keypairs/doc.go | 3 + .../v2/extensions/keypairs/fixtures.go | 171 + .../v2/extensions/keypairs/requests.go | 102 + .../compute/v2/extensions/keypairs/results.go | 94 + .../compute/v2/extensions/keypairs/urls.go | 25 + .../compute/v2/extensions/networks/doc.go | 2 + .../v2/extensions/networks/fixtures.go | 209 + .../v2/extensions/networks/requests.go | 22 + .../compute/v2/extensions/networks/results.go | 222 + .../compute/v2/extensions/networks/urls.go | 17 + .../v2/extensions/schedulerhints/doc.go | 3 + .../v2/extensions/schedulerhints/requests.go | 134 + .../compute/v2/extensions/secgroups/doc.go | 1 + .../v2/extensions/secgroups/fixtures.go | 267 + .../v2/extensions/secgroups/requests.go | 257 + .../v2/extensions/secgroups/results.go | 147 + .../compute/v2/extensions/secgroups/urls.go | 32 + .../compute/v2/extensions/servergroups/doc.go | 2 + .../v2/extensions/servergroups/fixtures.go | 161 + .../v2/extensions/servergroups/requests.go | 77 + .../v2/extensions/servergroups/results.go | 87 + .../v2/extensions/servergroups/urls.go | 25 + .../compute/v2/extensions/startstop/doc.go | 5 + .../v2/extensions/startstop/fixtures.go | 27 + .../v2/extensions/startstop/requests.go | 23 + .../v2/extensions/tenantnetworks/doc.go | 2 + .../v2/extensions/tenantnetworks/fixtures.go | 84 + .../v2/extensions/tenantnetworks/requests.go | 22 + .../v2/extensions/tenantnetworks/results.go | 68 + .../v2/extensions/tenantnetworks/urls.go | 17 + .../compute/v2/extensions/volumeattach/doc.go | 3 + .../v2/extensions/volumeattach/requests.go | 75 + .../v2/extensions/volumeattach/results.go | 84 + .../v2/extensions/volumeattach/testing/doc.go | 7 + .../volumeattach/testing/fixtures.go | 110 + .../v2/extensions/volumeattach/urls.go | 25 + .../openstack/compute/v2/flavors/doc.go | 7 + .../openstack/compute/v2/flavors/requests.go | 103 + .../openstack/compute/v2/flavors/results.go | 122 + .../openstack/compute/v2/flavors/urls.go | 13 + .../openstack/compute/v2/images/doc.go | 7 + .../openstack/compute/v2/images/requests.go | 109 + .../openstack/compute/v2/images/results.go | 95 + .../openstack/compute/v2/images/urls.go | 15 + .../openstack/compute/v2/servers/doc.go | 6 + .../openstack/compute/v2/servers/fixtures.go | 664 + .../openstack/compute/v2/servers/requests.go | 852 + .../openstack/compute/v2/servers/results.go | 372 + .../openstack/compute/v2/servers/urls.go | 47 + .../openstack/compute/v2/servers/util.go | 20 + .../openstack/db/v1/configurations/doc.go | 11 + .../db/v1/configurations/fixtures.go | 157 + .../db/v1/configurations/requests.go | 287 + .../openstack/db/v1/configurations/results.go | 197 + .../openstack/db/v1/configurations/urls.go | 31 + .../openstack/db/v1/databases/doc.go | 6 + .../openstack/db/v1/databases/fixtures.go | 61 + .../openstack/db/v1/databases/requests.go | 115 + .../openstack/db/v1/databases/results.go | 72 + .../openstack/db/v1/databases/urls.go | 11 + .../openstack/db/v1/datastores/doc.go | 3 + .../openstack/db/v1/datastores/fixtures.go | 100 + .../openstack/db/v1/datastores/requests.go | 47 + .../openstack/db/v1/datastores/results.go | 123 + .../openstack/db/v1/datastores/urls.go | 19 + .../openstack/db/v1/flavors/doc.go | 7 + .../openstack/db/v1/flavors/fixtures.go | 50 + .../openstack/db/v1/flavors/requests.go | 29 + .../openstack/db/v1/flavors/results.go | 92 + .../openstack/db/v1/flavors/urls.go | 11 + .../openstack/db/v1/instances/doc.go | 7 + .../openstack/db/v1/instances/fixtures.go | 169 + .../openstack/db/v1/instances/requests.go | 238 + .../openstack/db/v1/instances/results.go | 213 + .../openstack/db/v1/instances/urls.go | 19 + .../gophercloud/openstack/db/v1/users/doc.go | 3 + .../openstack/db/v1/users/fixtures.go | 37 + .../openstack/db/v1/users/requests.go | 132 + .../openstack/db/v1/users/results.go | 73 + .../gophercloud/openstack/db/v1/users/urls.go | 11 + .../openstack/endpoint_location.go | 91 + .../v2/extensions/admin/roles/docs.go | 16 + .../v2/extensions/admin/roles/fixtures.go | 48 + .../v2/extensions/admin/roles/requests.go | 33 + .../v2/extensions/admin/roles/results.go | 53 + .../v2/extensions/admin/roles/urls.go | 21 + .../identity/v2/extensions/delegate.go | 52 + .../openstack/identity/v2/extensions/doc.go | 3 + .../identity/v2/extensions/fixtures.go | 60 + .../openstack/identity/v2/tenants/doc.go | 7 + .../openstack/identity/v2/tenants/fixtures.go | 65 + .../openstack/identity/v2/tenants/requests.go | 33 + .../openstack/identity/v2/tenants/results.go | 62 + .../openstack/identity/v2/tenants/urls.go | 7 + .../openstack/identity/v2/tokens/doc.go | 5 + .../openstack/identity/v2/tokens/errors.go | 30 + .../openstack/identity/v2/tokens/fixtures.go | 195 + .../openstack/identity/v2/tokens/requests.go | 99 + .../openstack/identity/v2/tokens/results.go | 170 + .../openstack/identity/v2/tokens/urls.go | 13 + .../openstack/identity/v2/users/doc.go | 1 + .../openstack/identity/v2/users/fixtures.go | 163 + .../openstack/identity/v2/users/requests.go | 161 + .../openstack/identity/v2/users/results.go | 128 + .../openstack/identity/v2/users/urls.go | 21 + .../openstack/identity/v3/endpoints/doc.go | 6 + .../openstack/identity/v3/endpoints/errors.go | 21 + .../identity/v3/endpoints/requests.go | 123 + .../identity/v3/endpoints/results.go | 82 + .../openstack/identity/v3/endpoints/urls.go | 11 + .../openstack/identity/v3/roles/doc.go | 3 + .../openstack/identity/v3/roles/requests.go | 50 + .../openstack/identity/v3/roles/results.go | 81 + .../openstack/identity/v3/roles/urls.go | 7 + .../openstack/identity/v3/services/doc.go | 3 + .../identity/v3/services/requests.go | 77 + .../openstack/identity/v3/services/results.go | 80 + .../openstack/identity/v3/services/urls.go | 11 + .../openstack/identity/v3/tokens/doc.go | 6 + .../openstack/identity/v3/tokens/errors.go | 72 + .../openstack/identity/v3/tokens/requests.go | 281 + .../openstack/identity/v3/tokens/results.go | 139 + .../openstack/identity/v3/tokens/urls.go | 7 + .../networking/v2/apiversions/doc.go | 4 + .../networking/v2/apiversions/errors.go | 1 + .../networking/v2/apiversions/requests.go | 21 + .../networking/v2/apiversions/results.go | 77 + .../networking/v2/apiversions/urls.go | 15 + .../networking/v2/common/common_tests.go | 14 + .../networking/v2/extensions/delegate.go | 41 + .../networking/v2/extensions/external/doc.go | 3 + .../v2/extensions/external/requests.go | 69 + .../v2/extensions/external/results.go | 81 + .../networking/v2/extensions/fwaas/doc.go | 3 + .../v2/extensions/fwaas/firewalls/errors.go | 11 + .../v2/extensions/fwaas/firewalls/requests.go | 216 + .../v2/extensions/fwaas/firewalls/results.go | 101 + .../v2/extensions/fwaas/firewalls/urls.go | 16 + .../v2/extensions/fwaas/policies/requests.go | 243 + .../v2/extensions/fwaas/policies/results.go | 101 + .../v2/extensions/fwaas/policies/urls.go | 26 + .../v2/extensions/fwaas/rules/errors.go | 12 + .../v2/extensions/fwaas/rules/requests.go | 285 + .../v2/extensions/fwaas/rules/results.go | 110 + .../v2/extensions/fwaas/rules/urls.go | 16 + .../networking/v2/extensions/layer3/doc.go | 5 + .../extensions/layer3/floatingips/requests.go | 168 + .../extensions/layer3/floatingips/results.go | 127 + .../v2/extensions/layer3/floatingips/urls.go | 13 + .../v2/extensions/layer3/routers/requests.go | 230 + .../v2/extensions/layer3/routers/results.go | 168 + .../v2/extensions/layer3/routers/urls.go | 21 + .../networking/v2/extensions/lbaas/doc.go | 3 + .../v2/extensions/lbaas/members/requests.go | 123 + .../v2/extensions/lbaas/members/results.go | 122 + .../v2/extensions/lbaas/members/urls.go | 16 + .../v2/extensions/lbaas/monitors/requests.go | 265 + .../v2/extensions/lbaas/monitors/results.go | 147 + .../v2/extensions/lbaas/monitors/urls.go | 16 + .../v2/extensions/lbaas/pools/requests.go | 181 + .../v2/extensions/lbaas/pools/results.go | 146 + .../v2/extensions/lbaas/pools/urls.go | 25 + .../v2/extensions/lbaas/vips/requests.go | 256 + .../v2/extensions/lbaas/vips/results.go | 166 + .../v2/extensions/lbaas/vips/urls.go | 16 + .../networking/v2/extensions/provider/doc.go | 21 + .../v2/extensions/provider/results.go | 124 + .../networking/v2/extensions/security/doc.go | 32 + .../v2/extensions/security/groups/requests.go | 131 + .../v2/extensions/security/groups/results.go | 108 + .../v2/extensions/security/groups/urls.go | 13 + .../v2/extensions/security/rules/requests.go | 174 + .../v2/extensions/security/rules/results.go | 133 + .../v2/extensions/security/rules/urls.go | 13 + .../openstack/networking/v2/networks/doc.go | 9 + .../networking/v2/networks/errors.go | 1 + .../networking/v2/networks/requests.go | 226 + .../networking/v2/networks/results.go | 116 + .../openstack/networking/v2/networks/urls.go | 31 + .../openstack/networking/v2/ports/doc.go | 8 + .../openstack/networking/v2/ports/errors.go | 11 + .../openstack/networking/v2/ports/requests.go | 260 + .../openstack/networking/v2/ports/results.go | 126 + .../openstack/networking/v2/ports/urls.go | 31 + .../openstack/networking/v2/subnets/doc.go | 10 + .../openstack/networking/v2/subnets/errors.go | 13 + .../networking/v2/subnets/requests.go | 271 + .../networking/v2/subnets/results.go | 132 + .../openstack/networking/v2/subnets/urls.go | 31 + .../objectstorage/v1/accounts/doc.go | 8 + .../objectstorage/v1/accounts/fixtures.go | 38 + .../objectstorage/v1/accounts/requests.go | 107 + .../objectstorage/v1/accounts/results.go | 102 + .../objectstorage/v1/accounts/urls.go | 11 + .../objectstorage/v1/containers/doc.go | 8 + .../objectstorage/v1/containers/fixtures.go | 143 + .../objectstorage/v1/containers/requests.go | 205 + .../objectstorage/v1/containers/results.go | 270 + .../objectstorage/v1/containers/urls.go | 23 + .../openstack/objectstorage/v1/objects/doc.go | 5 + .../objectstorage/v1/objects/fixtures.go | 195 + .../objectstorage/v1/objects/requests.go | 501 + .../objectstorage/v1/objects/results.go | 438 + .../objectstorage/v1/objects/urls.go | 33 + .../orchestration/v1/apiversions/doc.go | 4 + .../orchestration/v1/apiversions/requests.go | 13 + .../orchestration/v1/apiversions/results.go | 42 + .../orchestration/v1/apiversions/urls.go | 7 + .../orchestration/v1/buildinfo/doc.go | 2 + .../orchestration/v1/buildinfo/fixtures.go | 45 + .../orchestration/v1/buildinfo/requests.go | 10 + .../orchestration/v1/buildinfo/results.go | 37 + .../orchestration/v1/buildinfo/urls.go | 7 + .../orchestration/v1/stackevents/doc.go | 4 + .../orchestration/v1/stackevents/fixtures.go | 446 + .../orchestration/v1/stackevents/requests.go | 203 + .../orchestration/v1/stackevents/results.go | 172 + .../orchestration/v1/stackevents/urls.go | 19 + .../orchestration/v1/stackresources/doc.go | 5 + .../v1/stackresources/fixtures.go | 439 + .../v1/stackresources/requests.go | 113 + .../v1/stackresources/results.go | 284 + .../orchestration/v1/stackresources/urls.go | 31 + .../openstack/orchestration/v1/stacks/doc.go | 8 + .../orchestration/v1/stacks/environment.go | 137 + .../orchestration/v1/stacks/fixtures.go | 604 + .../orchestration/v1/stacks/requests.go | 682 + .../orchestration/v1/stacks/results.go | 313 + .../orchestration/v1/stacks/template.go | 139 + .../openstack/orchestration/v1/stacks/urls.go | 35 + .../orchestration/v1/stacks/utils.go | 161 + .../orchestration/v1/stacktemplates/doc.go | 8 + .../v1/stacktemplates/fixtures.go | 95 + .../v1/stacktemplates/requests.go | 58 + .../v1/stacktemplates/results.go | 51 + .../orchestration/v1/stacktemplates/urls.go | 11 + .../openstack/utils/choose_version.go | 114 + .../rackspace/gophercloud/pagination/http.go | 60 + .../gophercloud/pagination/linked.go | 67 + .../gophercloud/pagination/marker.go | 40 + .../rackspace/gophercloud/pagination/null.go | 20 + .../rackspace/gophercloud/pagination/pager.go | 226 + .../rackspace/gophercloud/pagination/pkg.go | 4 + .../gophercloud/pagination/single.go | 15 + .../rackspace/gophercloud/params.go | 271 + .../rackspace/gophercloud/provider_client.go | 308 + .../gophercloud/rackspace/auth_env.go | 57 + .../blockstorage/v1/snapshots/delegate.go | 131 + .../blockstorage/v1/snapshots/doc.go | 3 + .../blockstorage/v1/snapshots/results.go | 147 + .../blockstorage/v1/volumes/delegate.go | 75 + .../rackspace/blockstorage/v1/volumes/doc.go | 3 + .../blockstorage/v1/volumes/results.go | 66 + .../blockstorage/v1/volumetypes/delegate.go | 18 + .../blockstorage/v1/volumetypes/doc.go | 3 + .../blockstorage/v1/volumetypes/results.go | 37 + .../rackspace/cdn/v1/base/delegate.go | 18 + .../gophercloud/rackspace/cdn/v1/base/doc.go | 4 + .../rackspace/cdn/v1/flavors/delegate.go | 18 + .../rackspace/cdn/v1/flavors/doc.go | 6 + .../cdn/v1/serviceassets/delegate.go | 13 + .../rackspace/cdn/v1/serviceassets/doc.go | 7 + .../rackspace/cdn/v1/services/delegate.go | 37 + .../rackspace/cdn/v1/services/doc.go | 7 + .../rackspace/gophercloud/rackspace/client.go | 224 + .../compute/v2/bootfromvolume/delegate.go | 12 + .../rackspace/compute/v2/flavors/delegate.go | 43 + .../rackspace/compute/v2/flavors/doc.go | 3 + .../rackspace/compute/v2/flavors/fixtures.go | 137 + .../rackspace/compute/v2/flavors/results.go | 104 + .../rackspace/compute/v2/flavors/urls.go | 9 + .../rackspace/compute/v2/images/delegate.go | 22 + .../rackspace/compute/v2/images/doc.go | 3 + .../rackspace/compute/v2/images/fixtures.go | 200 + .../rackspace/compute/v2/keypairs/delegate.go | 33 + .../rackspace/compute/v2/keypairs/doc.go | 3 + .../rackspace/compute/v2/networks/doc.go | 3 + .../rackspace/compute/v2/networks/requests.go | 89 + .../rackspace/compute/v2/networks/results.go | 81 + .../rackspace/compute/v2/networks/urls.go | 27 + .../rackspace/compute/v2/servers/delegate.go | 116 + .../rackspace/compute/v2/servers/doc.go | 3 + .../rackspace/compute/v2/servers/fixtures.go | 574 + .../rackspace/compute/v2/servers/requests.go | 178 + .../compute/v2/virtualinterfaces/requests.go | 45 + .../compute/v2/virtualinterfaces/results.go | 81 + .../compute/v2/virtualinterfaces/urls.go | 15 + .../compute/v2/volumeattach/delegate.go | 27 + .../rackspace/compute/v2/volumeattach/doc.go | 3 + .../rackspace/db/v1/backups/doc.go | 6 + .../rackspace/db/v1/backups/fixtures.go | 66 + .../rackspace/db/v1/backups/requests.go | 138 + .../rackspace/db/v1/backups/results.go | 149 + .../rackspace/db/v1/backups/urls.go | 11 + .../db/v1/configurations/delegate.go | 79 + .../rackspace/db/v1/configurations/doc.go | 1 + .../db/v1/configurations/fixtures.go | 159 + .../rackspace/db/v1/databases/delegate.go | 19 + .../rackspace/db/v1/databases/doc.go | 3 + .../rackspace/db/v1/databases/urls.go | 1 + .../rackspace/db/v1/datastores/delegate.go | 28 + .../rackspace/db/v1/datastores/doc.go | 1 + .../rackspace/db/v1/flavors/delegate.go | 17 + .../rackspace/db/v1/flavors/doc.go | 3 + .../rackspace/db/v1/instances/delegate.go | 49 + .../rackspace/db/v1/instances/doc.go | 3 + .../rackspace/db/v1/instances/fixtures.go | 340 + .../rackspace/db/v1/instances/requests.go | 199 + .../rackspace/db/v1/instances/results.go | 191 + .../rackspace/db/v1/instances/urls.go | 23 + .../rackspace/db/v1/users/delegate.go | 16 + .../gophercloud/rackspace/db/v1/users/doc.go | 3 + .../rackspace/db/v1/users/fixtures.go | 77 + .../rackspace/db/v1/users/requests.go | 176 + .../rackspace/db/v1/users/results.go | 149 + .../gophercloud/rackspace/db/v1/users/urls.go | 19 + .../identity/v2/extensions/delegate.go | 24 + .../rackspace/identity/v2/extensions/doc.go | 3 + .../rackspace/identity/v2/roles/delegate.go | 50 + .../rackspace/identity/v2/roles/fixtures.go | 49 + .../rackspace/identity/v2/tenants/delegate.go | 17 + .../rackspace/identity/v2/tenants/doc.go | 3 + .../rackspace/identity/v2/tokens/delegate.go | 60 + .../rackspace/identity/v2/tokens/doc.go | 3 + .../rackspace/identity/v2/users/delegate.go | 142 + .../rackspace/identity/v2/users/fixtures.go | 154 + .../rackspace/identity/v2/users/results.go | 129 + .../rackspace/identity/v2/users/urls.go | 7 + .../gophercloud/rackspace/lb/v1/acl/doc.go | 12 + .../rackspace/lb/v1/acl/fixtures.go | 109 + .../rackspace/lb/v1/acl/requests.go | 111 + .../rackspace/lb/v1/acl/results.go | 72 + .../gophercloud/rackspace/lb/v1/acl/urls.go | 20 + .../gophercloud/rackspace/lb/v1/lbs/doc.go | 44 + .../rackspace/lb/v1/lbs/fixtures.go | 584 + .../rackspace/lb/v1/lbs/requests.go | 497 + .../rackspace/lb/v1/lbs/results.go | 420 + .../gophercloud/rackspace/lb/v1/lbs/urls.go | 49 + .../rackspace/lb/v1/monitors/doc.go | 21 + .../rackspace/lb/v1/monitors/fixtures.go | 87 + .../rackspace/lb/v1/monitors/requests.go | 160 + .../rackspace/lb/v1/monitors/results.go | 90 + .../rackspace/lb/v1/monitors/urls.go | 16 + .../gophercloud/rackspace/lb/v1/nodes/doc.go | 35 + .../rackspace/lb/v1/nodes/fixtures.go | 243 + .../rackspace/lb/v1/nodes/requests.go | 251 + .../rackspace/lb/v1/nodes/results.go | 213 + .../gophercloud/rackspace/lb/v1/nodes/urls.go | 25 + .../rackspace/lb/v1/sessions/doc.go | 30 + .../rackspace/lb/v1/sessions/fixtures.go | 59 + .../rackspace/lb/v1/sessions/requests.go | 63 + .../rackspace/lb/v1/sessions/results.go | 58 + .../rackspace/lb/v1/sessions/urls.go | 16 + .../gophercloud/rackspace/lb/v1/ssl/doc.go | 22 + .../rackspace/lb/v1/ssl/fixtures.go | 196 + .../rackspace/lb/v1/ssl/requests.go | 247 + .../rackspace/lb/v1/ssl/results.go | 148 + .../gophercloud/rackspace/lb/v1/ssl/urls.go | 25 + .../rackspace/lb/v1/throttle/doc.go | 5 + .../rackspace/lb/v1/throttle/fixtures.go | 62 + .../rackspace/lb/v1/throttle/requests.go | 76 + .../rackspace/lb/v1/throttle/results.go | 43 + .../rackspace/lb/v1/throttle/urls.go | 16 + .../gophercloud/rackspace/lb/v1/vips/doc.go | 13 + .../rackspace/lb/v1/vips/fixtures.go | 88 + .../rackspace/lb/v1/vips/requests.go | 97 + .../rackspace/lb/v1/vips/results.go | 89 + .../gophercloud/rackspace/lb/v1/vips/urls.go | 20 + .../networking/v2/common/common_tests.go | 12 + .../networking/v2/networks/delegate.go | 41 + .../rackspace/networking/v2/ports/delegate.go | 43 + .../rackspace/networking/v2/security/doc.go | 32 + .../networking/v2/security/groups/delegate.go | 30 + .../networking/v2/security/rules/delegate.go | 30 + .../networking/v2/subnets/delegate.go | 40 + .../objectstorage/v1/accounts/delegate.go | 39 + .../objectstorage/v1/accounts/doc.go | 3 + .../rackspace/objectstorage/v1/bulk/doc.go | 3 + .../objectstorage/v1/bulk/requests.go | 51 + .../objectstorage/v1/bulk/results.go | 28 + .../rackspace/objectstorage/v1/bulk/urls.go | 11 + .../v1/cdncontainers/delegate.go | 38 + .../objectstorage/v1/cdncontainers/doc.go | 3 + .../v1/cdncontainers/requests.go | 161 + .../objectstorage/v1/cdncontainers/results.go | 149 + .../objectstorage/v1/cdncontainers/urls.go | 15 + .../objectstorage/v1/cdnobjects/delegate.go | 11 + .../objectstorage/v1/cdnobjects/doc.go | 3 + .../objectstorage/v1/cdnobjects/request.go | 15 + .../objectstorage/v1/containers/delegate.go | 93 + .../objectstorage/v1/containers/doc.go | 3 + .../objectstorage/v1/objects/delegate.go | 94 + .../rackspace/objectstorage/v1/objects/doc.go | 3 + .../orchestration/v1/buildinfo/delegate.go | 11 + .../orchestration/v1/buildinfo/doc.go | 2 + .../orchestration/v1/stackevents/delegate.go | 27 + .../orchestration/v1/stackevents/doc.go | 3 + .../v1/stackresources/delegate.go | 42 + .../orchestration/v1/stackresources/doc.go | 5 + .../orchestration/v1/stacks/delegate.go | 49 + .../rackspace/orchestration/v1/stacks/doc.go | 8 + .../orchestration/v1/stacks/fixtures.go | 32 + .../v1/stacktemplates/delegate.go | 16 + .../orchestration/v1/stacktemplates/doc.go | 8 + .../rackconnect/v3/cloudnetworks/requests.go | 24 + .../rackconnect/v3/cloudnetworks/results.go | 113 + .../rackconnect/v3/cloudnetworks/urls.go | 11 + .../rackspace/rackconnect/v3/doc.go | 4 + .../rackspace/rackconnect/v3/lbpools/doc.go | 14 + .../rackconnect/v3/lbpools/requests.go | 146 + .../rackconnect/v3/lbpools/results.go | 505 + .../rackspace/rackconnect/v3/lbpools/urls.go | 49 + .../rackconnect/v3/publicips/requests.go | 50 + .../rackconnect/v3/publicips/results.go | 221 + .../rackconnect/v3/publicips/urls.go | 25 + .../rackspace/gophercloud/results.go | 153 + .../gophercloud/script/acceptancetest | 5 + .../rackspace/gophercloud/script/bootstrap | 26 + .../rackspace/gophercloud/script/cibuild | 5 + .../rackspace/gophercloud/script/test | 5 + .../rackspace/gophercloud/script/unittest | 5 + .../rackspace/gophercloud/service_client.go | 32 + .../gophercloud/testhelper/client/fake.go | 17 + .../gophercloud/testhelper/convenience.go | 329 + .../rackspace/gophercloud/testhelper/doc.go | 4 + .../gophercloud/testhelper/fixture/helper.go | 31 + .../gophercloud/testhelper/http_responses.go | 91 + .../github.com/rackspace/gophercloud/util.go | 82 + vendor/github.com/satori/go.uuid/.travis.yml | 11 + vendor/github.com/satori/go.uuid/LICENSE | 20 + vendor/github.com/satori/go.uuid/README.md | 66 + vendor/github.com/satori/go.uuid/uuid.go | 435 + .../github.com/tent/http-link-go/.gitignore | 1 + .../github.com/tent/http-link-go/.travis.yml | 6 + vendor/github.com/tent/http-link-go/LICENSE | 27 + vendor/github.com/tent/http-link-go/README.md | 12 + vendor/github.com/tent/http-link-go/link.go | 185 + vendor/github.com/ugorji/go/LICENSE | 22 + vendor/github.com/ugorji/go/codec/0doc.go | 199 + vendor/github.com/ugorji/go/codec/README.md | 148 + vendor/github.com/ugorji/go/codec/binc.go | 922 + vendor/github.com/ugorji/go/codec/cbor.go | 585 + .../ugorji/go/codec/codecgen/README.md | 36 + .../ugorji/go/codec/codecgen/gen.go | 273 + .../github.com/ugorji/go/codec/codecgen/z.go | 3 + vendor/github.com/ugorji/go/codec/decode.go | 2019 + vendor/github.com/ugorji/go/codec/encode.go | 1419 + .../ugorji/go/codec/fast-path.generated.go | 39365 +++++++++++++++ .../ugorji/go/codec/fast-path.go.tmpl | 540 + .../ugorji/go/codec/fast-path.not.go | 32 + .../ugorji/go/codec/gen-dec-array.go.tmpl | 104 + .../ugorji/go/codec/gen-dec-map.go.tmpl | 58 + .../ugorji/go/codec/gen-helper.generated.go | 233 + .../ugorji/go/codec/gen-helper.go.tmpl | 364 + .../ugorji/go/codec/gen.generated.go | 175 + vendor/github.com/ugorji/go/codec/gen.go | 1989 + vendor/github.com/ugorji/go/codec/helper.go | 1271 + .../ugorji/go/codec/helper_internal.go | 242 + .../ugorji/go/codec/helper_not_unsafe.go | 20 + .../ugorji/go/codec/helper_unsafe.go | 45 + vendor/github.com/ugorji/go/codec/json.go | 1213 + vendor/github.com/ugorji/go/codec/msgpack.go | 845 + vendor/github.com/ugorji/go/codec/noop.go | 213 + vendor/github.com/ugorji/go/codec/prebuild.go | 3 + vendor/github.com/ugorji/go/codec/prebuild.sh | 199 + vendor/github.com/ugorji/go/codec/rpc.go | 180 + vendor/github.com/ugorji/go/codec/simple.go | 519 + .../ugorji/go/codec/test-cbor-goldens.json | 639 + vendor/github.com/ugorji/go/codec/test.py | 126 + vendor/github.com/ugorji/go/codec/tests.sh | 80 + vendor/github.com/ugorji/go/codec/time.go | 233 + vendor/golang.org/x/crypto/LICENSE | 27 + vendor/golang.org/x/crypto/PATENTS | 22 + .../x/crypto/curve25519/const_amd64.s | 20 + .../x/crypto/curve25519/cswap_amd64.s | 88 + .../x/crypto/curve25519/curve25519.go | 841 + vendor/golang.org/x/crypto/curve25519/doc.go | 23 + .../x/crypto/curve25519/freeze_amd64.s | 94 + .../x/crypto/curve25519/ladderstep_amd64.s | 1398 + .../x/crypto/curve25519/mont25519_amd64.go | 240 + .../x/crypto/curve25519/mul_amd64.s | 191 + .../x/crypto/curve25519/square_amd64.s | 153 + .../golang.org/x/crypto/ssh/agent/client.go | 615 + .../golang.org/x/crypto/ssh/agent/forward.go | 103 + .../golang.org/x/crypto/ssh/agent/keyring.go | 184 + .../golang.org/x/crypto/ssh/agent/server.go | 209 + vendor/golang.org/x/crypto/ssh/buffer.go | 98 + vendor/golang.org/x/crypto/ssh/certs.go | 501 + vendor/golang.org/x/crypto/ssh/channel.go | 631 + vendor/golang.org/x/crypto/ssh/cipher.go | 552 + vendor/golang.org/x/crypto/ssh/client.go | 213 + vendor/golang.org/x/crypto/ssh/client_auth.go | 441 + vendor/golang.org/x/crypto/ssh/common.go | 354 + vendor/golang.org/x/crypto/ssh/connection.go | 144 + vendor/golang.org/x/crypto/ssh/doc.go | 18 + vendor/golang.org/x/crypto/ssh/handshake.go | 412 + vendor/golang.org/x/crypto/ssh/kex.go | 526 + vendor/golang.org/x/crypto/ssh/keys.go | 720 + vendor/golang.org/x/crypto/ssh/mac.go | 57 + vendor/golang.org/x/crypto/ssh/messages.go | 725 + vendor/golang.org/x/crypto/ssh/mux.go | 356 + vendor/golang.org/x/crypto/ssh/server.go | 495 + vendor/golang.org/x/crypto/ssh/session.go | 605 + vendor/golang.org/x/crypto/ssh/tcpip.go | 407 + .../x/crypto/ssh/terminal/terminal.go | 892 + .../golang.org/x/crypto/ssh/terminal/util.go | 128 + .../x/crypto/ssh/terminal/util_bsd.go | 12 + .../x/crypto/ssh/terminal/util_linux.go | 11 + .../x/crypto/ssh/terminal/util_windows.go | 174 + vendor/golang.org/x/crypto/ssh/test/doc.go | 7 + vendor/golang.org/x/crypto/ssh/transport.go | 332 + vendor/golang.org/x/net/LICENSE | 27 + vendor/golang.org/x/net/PATENTS | 22 + vendor/golang.org/x/net/context/context.go | 447 + .../x/net/context/ctxhttp/cancelreq.go | 19 + .../x/net/context/ctxhttp/cancelreq_go14.go | 23 + .../x/net/context/ctxhttp/ctxhttp.go | 140 + vendor/golang.org/x/net/html/atom/atom.go | 78 + vendor/golang.org/x/net/html/atom/gen.go | 648 + vendor/golang.org/x/net/html/atom/table.go | 713 + .../golang.org/x/net/html/charset/charset.go | 257 + vendor/golang.org/x/net/html/const.go | 102 + vendor/golang.org/x/net/html/doc.go | 106 + vendor/golang.org/x/net/html/doctype.go | 156 + vendor/golang.org/x/net/html/entity.go | 2253 + vendor/golang.org/x/net/html/escape.go | 258 + vendor/golang.org/x/net/html/foreign.go | 226 + vendor/golang.org/x/net/html/node.go | 193 + vendor/golang.org/x/net/html/parse.go | 2094 + vendor/golang.org/x/net/html/render.go | 271 + vendor/golang.org/x/net/html/token.go | 1219 + vendor/golang.org/x/oauth2/.travis.yml | 14 + vendor/golang.org/x/oauth2/AUTHORS | 3 + vendor/golang.org/x/oauth2/CONTRIBUTING.md | 31 + vendor/golang.org/x/oauth2/CONTRIBUTORS | 3 + vendor/golang.org/x/oauth2/LICENSE | 27 + vendor/golang.org/x/oauth2/README.md | 64 + .../x/oauth2/bitbucket/bitbucket.go | 16 + .../golang.org/x/oauth2/client_appengine.go | 25 + .../clientcredentials/clientcredentials.go | 112 + .../golang.org/x/oauth2/facebook/facebook.go | 16 + vendor/golang.org/x/oauth2/github/github.go | 16 + .../golang.org/x/oauth2/google/appengine.go | 86 + .../x/oauth2/google/appengine_hook.go | 13 + .../x/oauth2/google/appenginevm_hook.go | 14 + vendor/golang.org/x/oauth2/google/default.go | 155 + vendor/golang.org/x/oauth2/google/google.go | 145 + vendor/golang.org/x/oauth2/google/jwt.go | 71 + vendor/golang.org/x/oauth2/google/sdk.go | 168 + vendor/golang.org/x/oauth2/internal/oauth2.go | 76 + vendor/golang.org/x/oauth2/internal/token.go | 221 + .../golang.org/x/oauth2/internal/transport.go | 69 + vendor/golang.org/x/oauth2/jws/jws.go | 172 + vendor/golang.org/x/oauth2/jwt/jwt.go | 153 + .../golang.org/x/oauth2/linkedin/linkedin.go | 16 + .../x/oauth2/microsoft/microsoft.go | 16 + vendor/golang.org/x/oauth2/oauth2.go | 337 + .../x/oauth2/odnoklassniki/odnoklassniki.go | 16 + vendor/golang.org/x/oauth2/paypal/paypal.go | 22 + vendor/golang.org/x/oauth2/token.go | 158 + vendor/golang.org/x/oauth2/transport.go | 132 + vendor/golang.org/x/oauth2/vk/vk.go | 16 + vendor/golang.org/x/sys/LICENSE | 27 + vendor/golang.org/x/sys/PATENTS | 22 + vendor/golang.org/x/sys/unix/.gitignore | 1 + vendor/golang.org/x/sys/unix/asm.s | 10 + vendor/golang.org/x/sys/unix/asm_darwin_386.s | 29 + .../golang.org/x/sys/unix/asm_darwin_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 + .../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 + .../golang.org/x/sys/unix/asm_dragonfly_386.s | 29 + .../x/sys/unix/asm_dragonfly_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_386.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_arm.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_386.s | 35 + .../golang.org/x/sys/unix/asm_linux_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_arm.s | 29 + .../golang.org/x/sys/unix/asm_linux_arm64.s | 24 + .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 28 + vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_solaris_amd64.s | 17 + vendor/golang.org/x/sys/unix/constants.go | 13 + vendor/golang.org/x/sys/unix/env_unix.go | 27 + vendor/golang.org/x/sys/unix/env_unset.go | 14 + vendor/golang.org/x/sys/unix/flock.go | 24 + .../x/sys/unix/flock_linux_32bit.go | 13 + vendor/golang.org/x/sys/unix/gccgo.go | 46 + vendor/golang.org/x/sys/unix/gccgo_c.c | 41 + .../x/sys/unix/gccgo_linux_amd64.go | 20 + vendor/golang.org/x/sys/unix/mkall.sh | 274 + vendor/golang.org/x/sys/unix/mkerrors.sh | 476 + vendor/golang.org/x/sys/unix/mksyscall.pl | 323 + .../x/sys/unix/mksyscall_solaris.pl | 294 + .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 264 + .../golang.org/x/sys/unix/mksysnum_darwin.pl | 39 + .../x/sys/unix/mksysnum_dragonfly.pl | 50 + .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 63 + .../golang.org/x/sys/unix/mksysnum_linux.pl | 58 + .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 58 + .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 50 + vendor/golang.org/x/sys/unix/race.go | 30 + vendor/golang.org/x/sys/unix/race0.go | 25 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 36 + vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 103 + vendor/golang.org/x/sys/unix/str.go | 26 + vendor/golang.org/x/sys/unix/syscall.go | 74 + vendor/golang.org/x/sys/unix/syscall_bsd.go | 628 + .../golang.org/x/sys/unix/syscall_darwin.go | 509 + .../x/sys/unix/syscall_darwin_386.go | 79 + .../x/sys/unix/syscall_darwin_amd64.go | 81 + .../x/sys/unix/syscall_darwin_arm.go | 73 + .../x/sys/unix/syscall_darwin_arm64.go | 79 + .../x/sys/unix/syscall_dragonfly.go | 411 + .../x/sys/unix/syscall_dragonfly_386.go | 63 + .../x/sys/unix/syscall_dragonfly_amd64.go | 63 + .../golang.org/x/sys/unix/syscall_freebsd.go | 682 + .../x/sys/unix/syscall_freebsd_386.go | 63 + .../x/sys/unix/syscall_freebsd_amd64.go | 63 + .../x/sys/unix/syscall_freebsd_arm.go | 63 + vendor/golang.org/x/sys/unix/syscall_linux.go | 1086 + .../x/sys/unix/syscall_linux_386.go | 388 + .../x/sys/unix/syscall_linux_amd64.go | 146 + .../x/sys/unix/syscall_linux_arm.go | 233 + .../x/sys/unix/syscall_linux_arm64.go | 150 + .../x/sys/unix/syscall_linux_ppc64x.go | 96 + .../golang.org/x/sys/unix/syscall_netbsd.go | 492 + .../x/sys/unix/syscall_netbsd_386.go | 44 + .../x/sys/unix/syscall_netbsd_amd64.go | 44 + .../x/sys/unix/syscall_netbsd_arm.go | 44 + .../golang.org/x/sys/unix/syscall_no_getwd.go | 11 + .../golang.org/x/sys/unix/syscall_openbsd.go | 303 + .../x/sys/unix/syscall_openbsd_386.go | 44 + .../x/sys/unix/syscall_openbsd_amd64.go | 44 + .../golang.org/x/sys/unix/syscall_solaris.go | 713 + .../x/sys/unix/syscall_solaris_amd64.go | 37 + vendor/golang.org/x/sys/unix/syscall_unix.go | 297 + vendor/golang.org/x/sys/unix/types_darwin.go | 250 + .../golang.org/x/sys/unix/types_dragonfly.go | 242 + vendor/golang.org/x/sys/unix/types_freebsd.go | 353 + vendor/golang.org/x/sys/unix/types_linux.go | 406 + vendor/golang.org/x/sys/unix/types_netbsd.go | 232 + vendor/golang.org/x/sys/unix/types_openbsd.go | 244 + vendor/golang.org/x/sys/unix/types_solaris.go | 260 + .../x/sys/unix/zerrors_darwin_386.go | 1576 + .../x/sys/unix/zerrors_darwin_amd64.go | 1576 + .../x/sys/unix/zerrors_darwin_arm.go | 1293 + .../x/sys/unix/zerrors_darwin_arm64.go | 1576 + .../x/sys/unix/zerrors_dragonfly_386.go | 1530 + .../x/sys/unix/zerrors_dragonfly_amd64.go | 1530 + .../x/sys/unix/zerrors_freebsd_386.go | 1743 + .../x/sys/unix/zerrors_freebsd_amd64.go | 1748 + .../x/sys/unix/zerrors_freebsd_arm.go | 1729 + .../x/sys/unix/zerrors_linux_386.go | 1817 + .../x/sys/unix/zerrors_linux_amd64.go | 1818 + .../x/sys/unix/zerrors_linux_arm.go | 1742 + .../x/sys/unix/zerrors_linux_arm64.go | 1896 + .../x/sys/unix/zerrors_linux_ppc64.go | 1969 + .../x/sys/unix/zerrors_linux_ppc64le.go | 1968 + .../x/sys/unix/zerrors_netbsd_386.go | 1712 + .../x/sys/unix/zerrors_netbsd_amd64.go | 1702 + .../x/sys/unix/zerrors_netbsd_arm.go | 1688 + .../x/sys/unix/zerrors_openbsd_386.go | 1584 + .../x/sys/unix/zerrors_openbsd_amd64.go | 1583 + .../x/sys/unix/zerrors_solaris_amd64.go | 1436 + .../x/sys/unix/zsyscall_darwin_386.go | 1426 + .../x/sys/unix/zsyscall_darwin_amd64.go | 1442 + .../x/sys/unix/zsyscall_darwin_arm.go | 1426 + .../x/sys/unix/zsyscall_darwin_arm64.go | 1426 + .../x/sys/unix/zsyscall_dragonfly_386.go | 1412 + .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1412 + .../x/sys/unix/zsyscall_freebsd_386.go | 1664 + .../x/sys/unix/zsyscall_freebsd_amd64.go | 1664 + .../x/sys/unix/zsyscall_freebsd_arm.go | 1664 + .../x/sys/unix/zsyscall_linux_386.go | 1628 + .../x/sys/unix/zsyscall_linux_amd64.go | 1822 + .../x/sys/unix/zsyscall_linux_arm.go | 1756 + .../x/sys/unix/zsyscall_linux_arm64.go | 1750 + .../x/sys/unix/zsyscall_linux_ppc64.go | 1792 + .../x/sys/unix/zsyscall_linux_ppc64le.go | 1792 + .../x/sys/unix/zsyscall_netbsd_386.go | 1326 + .../x/sys/unix/zsyscall_netbsd_amd64.go | 1326 + .../x/sys/unix/zsyscall_netbsd_arm.go | 1326 + .../x/sys/unix/zsyscall_openbsd_386.go | 1386 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 1386 + .../x/sys/unix/zsyscall_solaris_amd64.go | 1559 + .../golang.org/x/sys/unix/zsysctl_openbsd.go | 270 + .../x/sys/unix/zsysnum_darwin_386.go | 398 + .../x/sys/unix/zsysnum_darwin_amd64.go | 398 + .../x/sys/unix/zsysnum_darwin_arm.go | 358 + .../x/sys/unix/zsysnum_darwin_arm64.go | 398 + .../x/sys/unix/zsysnum_dragonfly_386.go | 304 + .../x/sys/unix/zsysnum_dragonfly_amd64.go | 304 + .../x/sys/unix/zsysnum_freebsd_386.go | 351 + .../x/sys/unix/zsysnum_freebsd_amd64.go | 351 + .../x/sys/unix/zsysnum_freebsd_arm.go | 351 + .../x/sys/unix/zsysnum_linux_386.go | 355 + .../x/sys/unix/zsysnum_linux_amd64.go | 321 + .../x/sys/unix/zsysnum_linux_arm.go | 356 + .../x/sys/unix/zsysnum_linux_arm64.go | 272 + .../x/sys/unix/zsysnum_linux_ppc64.go | 360 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 353 + .../x/sys/unix/zsysnum_netbsd_386.go | 273 + .../x/sys/unix/zsysnum_netbsd_amd64.go | 273 + .../x/sys/unix/zsysnum_netbsd_arm.go | 273 + .../x/sys/unix/zsysnum_openbsd_386.go | 207 + .../x/sys/unix/zsysnum_openbsd_amd64.go | 207 + .../x/sys/unix/zsysnum_solaris_amd64.go | 13 + .../x/sys/unix/ztypes_darwin_386.go | 447 + .../x/sys/unix/ztypes_darwin_amd64.go | 462 + .../x/sys/unix/ztypes_darwin_arm.go | 449 + .../x/sys/unix/ztypes_darwin_arm64.go | 457 + .../x/sys/unix/ztypes_dragonfly_386.go | 437 + .../x/sys/unix/ztypes_dragonfly_amd64.go | 443 + .../x/sys/unix/ztypes_freebsd_386.go | 502 + .../x/sys/unix/ztypes_freebsd_amd64.go | 505 + .../x/sys/unix/ztypes_freebsd_arm.go | 497 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 590 + .../x/sys/unix/ztypes_linux_amd64.go | 608 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 579 + .../x/sys/unix/ztypes_linux_arm64.go | 595 + .../x/sys/unix/ztypes_linux_ppc64.go | 605 + .../x/sys/unix/ztypes_linux_ppc64le.go | 605 + .../x/sys/unix/ztypes_netbsd_386.go | 396 + .../x/sys/unix/ztypes_netbsd_amd64.go | 403 + .../x/sys/unix/ztypes_netbsd_arm.go | 401 + .../x/sys/unix/ztypes_openbsd_386.go | 441 + .../x/sys/unix/ztypes_openbsd_amd64.go | 448 + .../x/sys/unix/ztypes_solaris_amd64.go | 422 + vendor/google.golang.org/api/LICENSE | 27 + .../api/compute/v1/compute-api.json | 14458 ++++++ .../api/compute/v1/compute-gen.go | 39937 ++++++++++++++++ .../api/gensupport/backoff.go | 34 + .../api/gensupport/buffer.go | 77 + .../google.golang.org/api/gensupport/doc.go | 10 + .../google.golang.org/api/gensupport/json.go | 172 + .../google.golang.org/api/gensupport/media.go | 198 + .../api/gensupport/params.go | 50 + .../api/gensupport/resumable.go | 177 + .../api/googleapi/googleapi.go | 418 + .../googleapi/internal/uritemplates/LICENSE | 18 + .../internal/uritemplates/uritemplates.go | 359 + .../googleapi/internal/uritemplates/utils.go | 13 + .../api/googleapi/transport/apikey.go | 38 + .../google.golang.org/api/googleapi/types.go | 182 + .../google.golang.org/appengine/.travis.yml | 18 + vendor/google.golang.org/appengine/LICENSE | 202 + vendor/google.golang.org/appengine/README.md | 75 + .../google.golang.org/appengine/aetest/doc.go | 42 + .../appengine/aetest/instance.go | 51 + .../appengine/aetest/instance_classic.go | 21 + .../appengine/aetest/instance_vm.go | 276 + .../appengine/aetest/user.go | 36 + .../google.golang.org/appengine/appengine.go | 76 + .../appengine/appengine_vm.go | 56 + .../appengine/blobstore/blobstore.go | 276 + .../appengine/blobstore/read.go | 160 + .../appengine/capability/capability.go | 52 + .../appengine/channel/channel.go | 83 + .../appengine/cloudsql/cloudsql.go | 62 + .../appengine/cloudsql/cloudsql_classic.go | 17 + .../appengine/cloudsql/cloudsql_vm.go | 16 + .../appengine/cmd/aebundler/aebundler.go | 342 + .../appengine/cmd/aedeploy/aedeploy.go | 264 + .../appengine/datastore/datastore.go | 406 + .../appengine/datastore/doc.go | 351 + .../appengine/datastore/key.go | 309 + .../appengine/datastore/load.go | 334 + .../appengine/datastore/metadata.go | 79 + .../appengine/datastore/prop.go | 294 + .../appengine/datastore/query.go | 713 + .../appengine/datastore/save.go | 300 + .../appengine/datastore/transaction.go | 87 + .../appengine/delay/delay.go | 275 + .../appengine/demos/guestbook/app.yaml | 17 + .../appengine/demos/guestbook/favicon.ico | Bin 0 -> 1150 bytes .../appengine/demos/guestbook/guestbook.go | 109 + .../appengine/demos/guestbook/index.yaml | 7 + .../demos/guestbook/templates/guestbook.html | 26 + .../appengine/demos/helloworld/app.yaml | 13 + .../appengine/demos/helloworld/favicon.ico | Bin 0 -> 1150 bytes .../appengine/demos/helloworld/helloworld.go | 50 + vendor/google.golang.org/appengine/errors.go | 46 + .../google.golang.org/appengine/file/file.go | 28 + .../google.golang.org/appengine/identity.go | 142 + .../appengine/image/image.go | 67 + .../appengine/internal/aetesting/fake.go | 80 + .../appengine/internal/api.go | 640 + .../appengine/internal/api_classic.go | 133 + .../appengine/internal/api_common.go | 101 + .../appengine/internal/app_id.go | 28 + .../app_identity/app_identity_service.pb.go | 296 + .../app_identity/app_identity_service.proto | 64 + .../appengine/internal/base/api_base.pb.go | 133 + .../appengine/internal/base/api_base.proto | 33 + .../blobstore/blobstore_service.pb.go | 347 + .../blobstore/blobstore_service.proto | 71 + .../capability/capability_service.pb.go | 125 + .../capability/capability_service.proto | 28 + .../internal/channel/channel_service.pb.go | 154 + .../internal/channel/channel_service.proto | 30 + .../internal/datastore/datastore_v3.pb.go | 2778 ++ .../internal/datastore/datastore_v3.proto | 541 + .../appengine/internal/identity.go | 14 + .../appengine/internal/identity_classic.go | 27 + .../appengine/internal/identity_vm.go | 97 + .../internal/image/images_service.pb.go | 845 + .../internal/image/images_service.proto | 162 + .../appengine/internal/internal.go | 144 + .../appengine/internal/log/log_service.pb.go | 899 + .../appengine/internal/log/log_service.proto | 150 + .../internal/mail/mail_service.pb.go | 229 + .../internal/mail/mail_service.proto | 45 + .../internal/memcache/memcache_service.pb.go | 938 + .../internal/memcache/memcache_service.proto | 165 + .../appengine/internal/metadata.go | 61 + .../internal/modules/modules_service.pb.go | 375 + .../internal/modules/modules_service.proto | 80 + .../appengine/internal/net.go | 56 + .../appengine/internal/regen.sh | 40 + .../internal/remote_api/remote_api.pb.go | 231 + .../internal/remote_api/remote_api.proto | 44 + .../appengine/internal/search/search.pb.go | 2127 + .../appengine/internal/search/search.proto | 388 + .../internal/socket/socket_service.pb.go | 1858 + .../internal/socket/socket_service.proto | 460 + .../internal/system/system_service.pb.go | 198 + .../internal/system/system_service.proto | 49 + .../taskqueue/taskqueue_service.pb.go | 1888 + .../taskqueue/taskqueue_service.proto | 342 + .../appengine/internal/transaction.go | 107 + .../internal/urlfetch/urlfetch_service.pb.go | 355 + .../internal/urlfetch/urlfetch_service.proto | 64 + .../internal/user/user_service.pb.go | 289 + .../internal/user/user_service.proto | 58 + .../internal/xmpp/xmpp_service.pb.go | 427 + .../internal/xmpp/xmpp_service.proto | 83 + vendor/google.golang.org/appengine/log/api.go | 40 + vendor/google.golang.org/appengine/log/log.go | 323 + .../google.golang.org/appengine/mail/mail.go | 123 + .../appengine/memcache/memcache.go | 526 + .../appengine/module/module.go | 113 + .../google.golang.org/appengine/namespace.go | 25 + .../appengine/remote_api/client.go | 174 + .../appengine/remote_api/remote_api.go | 152 + .../appengine/runtime/runtime.go | 148 + .../google.golang.org/appengine/search/doc.go | 205 + .../appengine/search/field.go | 82 + .../appengine/search/search.go | 1109 + .../appengine/search/struct.go | 245 + .../google.golang.org/appengine/socket/doc.go | 10 + .../appengine/socket/socket_classic.go | 290 + .../appengine/socket/socket_vm.go | 64 + .../appengine/taskqueue/taskqueue.go | 496 + vendor/google.golang.org/appengine/timeout.go | 20 + .../appengine/urlfetch/urlfetch.go | 210 + .../google.golang.org/appengine/user/oauth.go | 52 + .../google.golang.org/appengine/user/user.go | 84 + .../appengine/user/user_classic.go | 35 + .../appengine/user/user_vm.go | 38 + .../google.golang.org/appengine/xmpp/xmpp.go | 253 + vendor/google.golang.org/cloud/LICENSE | 202 + .../cloud/compute/metadata/metadata.go | 332 + .../google.golang.org/cloud/internal/cloud.go | 128 + .../internal/datastore/datastore_v1.pb.go | 1633 + .../internal/datastore/datastore_v1.proto | 606 + .../cloud/internal/opts/option.go | 25 + .../cloud/internal/testutil/context.go | 71 + .../cloud/internal/transport/cancelreq.go | 29 + .../internal/transport/cancelreq_legacy.go | 31 + .../cloud/internal/transport/dial.go | 135 + .../cloud/internal/transport/proto.go | 80 + vendor/gopkg.in/fsnotify.v1/.gitignore | 6 + vendor/gopkg.in/fsnotify.v1/.travis.yml | 23 + vendor/gopkg.in/fsnotify.v1/AUTHORS | 40 + vendor/gopkg.in/fsnotify.v1/CHANGELOG.md | 283 + vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md | 77 + vendor/gopkg.in/fsnotify.v1/LICENSE | 28 + vendor/gopkg.in/fsnotify.v1/README.md | 64 + vendor/gopkg.in/fsnotify.v1/fsnotify.go | 62 + vendor/gopkg.in/fsnotify.v1/inotify.go | 324 + vendor/gopkg.in/fsnotify.v1/inotify_poller.go | 186 + vendor/gopkg.in/fsnotify.v1/kqueue.go | 502 + vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go | 11 + .../gopkg.in/fsnotify.v1/open_mode_darwin.go | 12 + vendor/gopkg.in/fsnotify.v1/windows.go | 561 + vendor/gopkg.in/tomb.v1/LICENSE | 29 + vendor/gopkg.in/tomb.v1/README.md | 4 + vendor/gopkg.in/tomb.v1/tomb.go | 176 + vendor/gopkg.in/xmlpath.v2/LICENSE | 187 + vendor/gopkg.in/xmlpath.v2/README.md | 4 + .../gopkg.in/xmlpath.v2/cmd/webpath/main.go | 88 + vendor/gopkg.in/xmlpath.v2/doc.go | 75 + vendor/gopkg.in/xmlpath.v2/parser.go | 396 + vendor/gopkg.in/xmlpath.v2/path.go | 790 + 2560 files changed, 408767 insertions(+) create mode 100644 vendor/github.com/ActiveState/tail/.gitignore create mode 100644 vendor/github.com/ActiveState/tail/.travis.yml create mode 100644 vendor/github.com/ActiveState/tail/CHANGES.md create mode 100644 vendor/github.com/ActiveState/tail/Dockerfile create mode 100644 vendor/github.com/ActiveState/tail/LICENSE.txt create mode 100644 vendor/github.com/ActiveState/tail/Makefile create mode 100644 vendor/github.com/ActiveState/tail/README.md create mode 100644 vendor/github.com/ActiveState/tail/cmd/gotail/.gitignore create mode 100644 vendor/github.com/ActiveState/tail/cmd/gotail/Makefile create mode 100644 vendor/github.com/ActiveState/tail/cmd/gotail/gotail.go create mode 100644 vendor/github.com/ActiveState/tail/deps.json create mode 100644 vendor/github.com/ActiveState/tail/ratelimiter/Licence create mode 100644 vendor/github.com/ActiveState/tail/ratelimiter/leakybucket.go create mode 100644 vendor/github.com/ActiveState/tail/ratelimiter/memory.go create mode 100644 vendor/github.com/ActiveState/tail/ratelimiter/storage.go create mode 100644 vendor/github.com/ActiveState/tail/tail.go create mode 100644 vendor/github.com/ActiveState/tail/tail_posix.go create mode 100644 vendor/github.com/ActiveState/tail/tail_windows.go create mode 100644 vendor/github.com/ActiveState/tail/util/util.go create mode 100644 vendor/github.com/ActiveState/tail/watch/filechanges.go create mode 100644 vendor/github.com/ActiveState/tail/watch/inotify.go create mode 100644 vendor/github.com/ActiveState/tail/watch/inotify_tracker.go create mode 100644 vendor/github.com/ActiveState/tail/watch/polling.go create mode 100644 vendor/github.com/ActiveState/tail/watch/watch.go create mode 100644 vendor/github.com/ActiveState/tail/winfile/winfile.go create mode 100644 vendor/github.com/armon/go-radix/.gitignore create mode 100644 vendor/github.com/armon/go-radix/.travis.yml create mode 100644 vendor/github.com/armon/go-radix/LICENSE create mode 100644 vendor/github.com/armon/go-radix/README.md create mode 100644 vendor/github.com/armon/go-radix/radix.go create mode 100644 vendor/github.com/aws/aws-sdk-go/LICENSE.txt create mode 100644 vendor/github.com/aws/aws-sdk-go/NOTICE.txt create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/client.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/convert_types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/errors.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/logger.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/session.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/version.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json create mode 100644 vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/restjson.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/restxml/restxml.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/signer/v4/header_rules.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/signer/v4/v4.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/waiter/waiter.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/ec2/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/ec2/service.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/ec2/waiters.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/service.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go create mode 100644 vendor/github.com/bgentry/speakeasy/.gitignore create mode 100644 vendor/github.com/bgentry/speakeasy/LICENSE_WINDOWS create mode 100644 vendor/github.com/bgentry/speakeasy/Readme.md create mode 100644 vendor/github.com/bgentry/speakeasy/example/main.go create mode 100644 vendor/github.com/bgentry/speakeasy/speakeasy.go create mode 100644 vendor/github.com/bgentry/speakeasy/speakeasy_unix.go create mode 100644 vendor/github.com/bgentry/speakeasy/speakeasy_windows.go create mode 100644 vendor/github.com/digitalocean/godo/.travis.yml create mode 100644 vendor/github.com/digitalocean/godo/CONTRIBUTING.md create mode 100644 vendor/github.com/digitalocean/godo/LICENSE.txt create mode 100644 vendor/github.com/digitalocean/godo/README.md create mode 100644 vendor/github.com/digitalocean/godo/account.go create mode 100644 vendor/github.com/digitalocean/godo/action.go create mode 100644 vendor/github.com/digitalocean/godo/doc.go create mode 100644 vendor/github.com/digitalocean/godo/domains.go create mode 100644 vendor/github.com/digitalocean/godo/droplet_actions.go create mode 100644 vendor/github.com/digitalocean/godo/droplets.go create mode 100644 vendor/github.com/digitalocean/godo/errors.go create mode 100644 vendor/github.com/digitalocean/godo/floating_ips.go create mode 100644 vendor/github.com/digitalocean/godo/floating_ips_actions.go create mode 100644 vendor/github.com/digitalocean/godo/godo.go create mode 100644 vendor/github.com/digitalocean/godo/image_actions.go create mode 100644 vendor/github.com/digitalocean/godo/images.go create mode 100644 vendor/github.com/digitalocean/godo/keys.go create mode 100644 vendor/github.com/digitalocean/godo/links.go create mode 100644 vendor/github.com/digitalocean/godo/regions.go create mode 100644 vendor/github.com/digitalocean/godo/sizes.go create mode 100644 vendor/github.com/digitalocean/godo/strings.go create mode 100644 vendor/github.com/digitalocean/godo/timestamp.go create mode 100644 vendor/github.com/digitalocean/godo/util/droplet.go create mode 100644 vendor/github.com/dylanmei/iso8601/LICENSE create mode 100644 vendor/github.com/dylanmei/iso8601/README.md create mode 100644 vendor/github.com/dylanmei/iso8601/duration.go create mode 100644 vendor/github.com/dylanmei/winrmtest/LICENSE create mode 100644 vendor/github.com/dylanmei/winrmtest/README.md create mode 100644 vendor/github.com/dylanmei/winrmtest/remote.go create mode 100644 vendor/github.com/dylanmei/winrmtest/wsman.go create mode 100644 vendor/github.com/go-ini/ini/.gitignore create mode 100644 vendor/github.com/go-ini/ini/LICENSE create mode 100644 vendor/github.com/go-ini/ini/README.md create mode 100644 vendor/github.com/go-ini/ini/README_ZH.md create mode 100644 vendor/github.com/go-ini/ini/ini.go create mode 100644 vendor/github.com/go-ini/ini/parser.go create mode 100644 vendor/github.com/go-ini/ini/struct.go create mode 100644 vendor/github.com/golang/protobuf/LICENSE create mode 100644 vendor/github.com/golang/protobuf/proto/Makefile create mode 100644 vendor/github.com/golang/protobuf/proto/clone.go create mode 100644 vendor/github.com/golang/protobuf/proto/decode.go create mode 100644 vendor/github.com/golang/protobuf/proto/encode.go create mode 100644 vendor/github.com/golang/protobuf/proto/equal.go create mode 100644 vendor/github.com/golang/protobuf/proto/extensions.go create mode 100644 vendor/github.com/golang/protobuf/proto/lib.go create mode 100644 vendor/github.com/golang/protobuf/proto/message_set.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_reflect.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_unsafe.go create mode 100644 vendor/github.com/golang/protobuf/proto/properties.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto create mode 100644 vendor/github.com/golang/protobuf/proto/text.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_parser.go create mode 100644 vendor/github.com/google/go-querystring/LICENSE create mode 100644 vendor/github.com/google/go-querystring/query/encode.go create mode 100644 vendor/github.com/hashicorp/atlas-go/LICENSE create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/archive.go create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-dir-mode/file.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file-compressed/file.tar.gz create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/baz.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/COMMIT_EDITMSG create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/HEAD create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/config create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/description create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/applypatch-msg.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/commit-msg.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/post-update.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-applypatch.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-commit.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-push.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-rebase.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/prepare-commit-msg.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/update.sample create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/index create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/info/exclude create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/logs/HEAD create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/logs/refs/heads/master create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/75/25d17cbbb56f3253a20903ffddc07c6c935c76 create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/7e/49ea5550b356e32b63c044201f5f7da1e0925f create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/7f/7402c7d2a6e71ca3db3e236099771b160b8ad1 create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/refs/heads/master create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/bar.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/subdir/hello.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/untracked.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-hg/bar.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-hg/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-hg/subdir/hello.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir-splat/bar.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir-splat/build/darwin-amd64/build.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir-splat/build/linux-amd64/build.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir/bar.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-subdir/subdir/hello.txt create mode 120000 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-symlink/link/link create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-symlink/real/foo.txt create mode 100644 vendor/github.com/hashicorp/atlas-go/archive/vcs.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/application.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/artifact.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/authentication.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/build_config.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/client.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/terraform.go create mode 100644 vendor/github.com/hashicorp/atlas-go/v1/util.go create mode 100644 vendor/github.com/hashicorp/errwrap/LICENSE create mode 100644 vendor/github.com/hashicorp/errwrap/README.md create mode 100644 vendor/github.com/hashicorp/errwrap/errwrap.go create mode 100644 vendor/github.com/hashicorp/go-checkpoint/LICENSE create mode 100644 vendor/github.com/hashicorp/go-checkpoint/README.md create mode 100644 vendor/github.com/hashicorp/go-checkpoint/checkpoint.go create mode 100644 vendor/github.com/hashicorp/go-cleanhttp/LICENSE create mode 100644 vendor/github.com/hashicorp/go-cleanhttp/README.md create mode 100644 vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go create mode 100644 vendor/github.com/hashicorp/go-multierror/LICENSE create mode 100644 vendor/github.com/hashicorp/go-multierror/README.md create mode 100644 vendor/github.com/hashicorp/go-multierror/append.go create mode 100644 vendor/github.com/hashicorp/go-multierror/flatten.go create mode 100644 vendor/github.com/hashicorp/go-multierror/format.go create mode 100644 vendor/github.com/hashicorp/go-multierror/multierror.go create mode 100644 vendor/github.com/hashicorp/go-multierror/prefix.go create mode 100644 vendor/github.com/hashicorp/go-version/.travis.yml create mode 100644 vendor/github.com/hashicorp/go-version/LICENSE create mode 100644 vendor/github.com/hashicorp/go-version/README.md create mode 100644 vendor/github.com/hashicorp/go-version/constraint.go create mode 100644 vendor/github.com/hashicorp/go-version/version.go create mode 100644 vendor/github.com/hashicorp/go-version/version_collection.go create mode 100644 vendor/github.com/hashicorp/yamux/.gitignore create mode 100644 vendor/github.com/hashicorp/yamux/LICENSE create mode 100644 vendor/github.com/hashicorp/yamux/README.md create mode 100644 vendor/github.com/hashicorp/yamux/addr.go create mode 100644 vendor/github.com/hashicorp/yamux/const.go create mode 100644 vendor/github.com/hashicorp/yamux/mux.go create mode 100644 vendor/github.com/hashicorp/yamux/session.go create mode 100644 vendor/github.com/hashicorp/yamux/spec.md create mode 100644 vendor/github.com/hashicorp/yamux/stream.go create mode 100644 vendor/github.com/hashicorp/yamux/util.go create mode 100644 vendor/github.com/hpcloud/tail/LICENSE.txt create mode 100644 vendor/github.com/hpcloud/tail/ratelimiter/Licence create mode 100644 vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go create mode 100644 vendor/github.com/hpcloud/tail/ratelimiter/memory.go create mode 100644 vendor/github.com/hpcloud/tail/ratelimiter/storage.go create mode 100644 vendor/github.com/hpcloud/tail/util/util.go create mode 100644 vendor/github.com/hpcloud/tail/watch/filechanges.go create mode 100644 vendor/github.com/hpcloud/tail/watch/inotify.go create mode 100644 vendor/github.com/hpcloud/tail/watch/inotify_tracker.go create mode 100644 vendor/github.com/hpcloud/tail/watch/polling.go create mode 100644 vendor/github.com/hpcloud/tail/watch/watch.go create mode 100644 vendor/github.com/hpcloud/tail/winfile/winfile.go create mode 100644 vendor/github.com/jmespath/go-jmespath/.gitignore create mode 100644 vendor/github.com/jmespath/go-jmespath/.travis.yml create mode 100644 vendor/github.com/jmespath/go-jmespath/LICENSE create mode 100644 vendor/github.com/jmespath/go-jmespath/Makefile create mode 100644 vendor/github.com/jmespath/go-jmespath/README.md create mode 100644 vendor/github.com/jmespath/go-jmespath/api.go create mode 100644 vendor/github.com/jmespath/go-jmespath/astnodetype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/basic.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/boolean.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/current.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/escape.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/filters.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/functions.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/indices.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/literal.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/pipe.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/slice.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/syntax.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/unicode.json create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json create mode 100644 vendor/github.com/jmespath/go-jmespath/functions.go create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-159 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-16 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-160 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-161 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-162 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-163 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-164 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-165 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-166 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-167 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-168 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-169 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-17 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-170 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-171 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-172 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-173 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-174 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-175 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-178 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-179 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-18 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-180 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-181 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-182 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-183 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-184 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-185 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-186 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-187 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-188 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-189 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-19 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-190 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-191 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-192 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-193 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-194 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-195 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-196 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-198 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-199 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-2 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-20 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-200 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-201 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-202 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-203 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-204 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-205 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-206 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-207 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-208 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-209 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-21 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-210 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-211 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-212 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-213 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-214 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-215 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-216 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-217 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-218 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-219 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-22 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-220 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-221 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-222 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-223 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-224 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-225 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-226 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-227 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-228 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-229 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-23 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-230 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-231 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-232 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-233 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-234 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-235 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-236 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-237 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-238 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-239 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-24 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-240 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-241 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-242 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-243 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-244 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-245 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-246 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-247 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-248 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-249 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-25 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-250 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-251 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-252 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-253 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-254 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-255 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-256 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-257 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-258 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-259 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-26 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-260 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-261 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-262 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-263 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-264 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-265 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-266 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-267 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-268 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-269 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-27 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-270 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-271 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-272 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-273 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-274 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-275 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-276 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-277 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-278 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-279 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-28 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-280 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-281 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-282 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-283 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-284 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-285 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-286 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-287 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-288 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-289 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-29 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-290 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-291 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-292 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-293 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-294 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-295 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-296 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-297 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-298 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-299 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-3 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-30 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-300 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-301 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-302 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-303 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-304 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-305 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-306 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-307 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-308 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-309 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-31 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-310 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-311 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-312 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-313 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-314 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-315 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-316 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-317 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-318 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-319 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-32 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-320 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-321 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-322 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-323 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-324 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-325 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-326 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-327 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-328 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-329 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-33 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-330 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-331 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-332 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-333 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-334 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-335 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-336 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-337 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-338 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-339 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-34 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-340 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-341 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-342 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-343 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-344 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-345 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-346 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-347 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-348 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-349 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-35 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-350 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-351 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-352 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-353 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-354 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-355 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-356 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-357 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-358 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-359 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-36 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-360 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-361 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-362 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-363 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-364 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-365 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-366 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-367 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-368 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-369 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-37 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-370 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-371 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-372 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-373 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-374 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-375 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-376 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-377 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-378 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-379 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-38 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-380 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-381 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-382 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-383 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-384 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-385 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-386 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-387 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-388 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-389 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-39 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-390 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-391 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-392 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-393 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-394 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-395 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-396 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-397 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-398 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-399 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-4 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-40 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-400 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-401 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-402 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-403 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-404 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-405 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-406 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-407 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-408 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-409 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-41 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-410 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-411 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-412 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-413 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-414 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-415 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-416 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-417 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-418 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-419 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-42 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-420 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-421 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-422 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-423 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-424 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-425 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-426 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-427 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-428 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-429 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-43 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-430 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-431 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-432 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-433 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-434 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-435 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-436 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-437 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-438 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-439 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-44 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-440 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-441 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-442 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-443 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-444 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-445 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-446 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-447 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-448 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-449 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-45 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-450 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-451 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-452 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-453 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-454 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-455 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-456 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-457 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-458 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-459 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-46 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-460 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-461 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-462 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-463 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-464 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-465 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-466 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-467 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-468 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-469 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-47 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-470 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-471 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-472 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-473 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-474 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-475 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-476 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-477 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-478 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-479 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-48 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-480 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-481 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-482 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-483 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-484 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-485 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-486 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-487 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-488 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-489 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-49 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-490 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-491 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-492 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-493 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-494 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-495 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-496 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-497 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-498 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-499 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-5 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-50 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-500 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-501 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-502 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-503 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-504 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-505 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-506 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-507 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-508 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-509 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-51 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-510 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-511 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-512 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-513 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-514 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-515 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-516 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-517 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-518 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-519 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-52 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-520 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-521 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-522 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-523 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-524 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-525 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-526 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-527 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-528 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-529 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-53 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-530 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-531 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-532 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-533 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-534 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-535 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-536 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-537 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-538 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-539 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-54 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-540 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-541 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-542 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-543 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-544 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-545 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-546 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-547 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-548 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-549 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-55 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-550 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-551 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-552 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-553 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-554 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-555 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-556 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-557 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-558 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-559 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-56 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-560 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-561 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-562 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-563 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-564 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-565 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-566 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-567 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-568 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-569 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-57 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-570 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-571 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-572 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-573 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-574 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-575 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-576 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-577 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-578 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-579 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-58 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-580 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-581 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-582 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-583 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-584 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-585 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-586 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-587 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-588 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-589 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-59 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-590 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-591 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-592 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-593 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-594 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-595 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-596 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-597 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-598 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-599 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-6 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-60 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-600 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-601 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-602 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-603 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-604 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-605 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-606 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-607 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-608 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-609 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-61 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-610 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-611 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-612 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-613 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-614 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-615 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-616 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-617 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-618 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-619 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-62 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-620 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-621 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-622 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-623 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-624 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-625 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-626 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-627 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-628 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-629 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-63 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-630 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-631 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-632 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-633 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-634 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-635 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-636 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-637 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-638 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-639 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-64 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-640 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-641 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-642 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-643 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-644 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-645 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-646 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-647 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-648 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-649 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-65 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-650 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-651 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-652 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-653 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-654 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-655 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-656 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-66 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-67 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-68 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-69 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-7 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-70 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-71 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-72 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-73 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-74 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-75 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-76 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-77 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-78 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-79 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-8 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-80 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-81 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-82 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-83 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-84 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-85 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-86 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-87 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-88 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-89 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-9 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-90 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-91 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-92 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-93 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-94 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-95 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-96 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-97 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-98 create mode 100644 vendor/github.com/jmespath/go-jmespath/fuzz/jmespath.go create mode 100644 vendor/github.com/jmespath/go-jmespath/interpreter.go create mode 100644 vendor/github.com/jmespath/go-jmespath/lexer.go create mode 100644 vendor/github.com/jmespath/go-jmespath/parser.go create mode 100644 vendor/github.com/jmespath/go-jmespath/toktype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/util.go create mode 100644 vendor/github.com/kardianos/osext/LICENSE create mode 100644 vendor/github.com/kardianos/osext/README.md create mode 100644 vendor/github.com/kardianos/osext/osext.go create mode 100644 vendor/github.com/kardianos/osext/osext_plan9.go create mode 100644 vendor/github.com/kardianos/osext/osext_procfs.go create mode 100644 vendor/github.com/kardianos/osext/osext_sysctl.go create mode 100644 vendor/github.com/kardianos/osext/osext_windows.go create mode 100644 vendor/github.com/klauspost/compress/LICENSE create mode 100644 vendor/github.com/klauspost/compress/flate/copy.go create mode 100644 vendor/github.com/klauspost/compress/flate/crc32_amd64.go create mode 100644 vendor/github.com/klauspost/compress/flate/crc32_amd64.s create mode 100644 vendor/github.com/klauspost/compress/flate/crc32_noasm.go create mode 100644 vendor/github.com/klauspost/compress/flate/deflate.go create mode 100644 vendor/github.com/klauspost/compress/flate/fixedhuff.go create mode 100644 vendor/github.com/klauspost/compress/flate/gen.go create mode 100644 vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go create mode 100644 vendor/github.com/klauspost/compress/flate/huffman_code.go create mode 100644 vendor/github.com/klauspost/compress/flate/inflate.go create mode 100644 vendor/github.com/klauspost/compress/flate/reverse_bits.go create mode 100644 vendor/github.com/klauspost/compress/flate/snappy.go create mode 100644 vendor/github.com/klauspost/compress/flate/token.go create mode 100644 vendor/github.com/klauspost/cpuid/.gitignore create mode 100644 vendor/github.com/klauspost/cpuid/.travis.yml create mode 100644 vendor/github.com/klauspost/cpuid/LICENSE create mode 100644 vendor/github.com/klauspost/cpuid/README.md create mode 100644 vendor/github.com/klauspost/cpuid/cpuid.go create mode 100644 vendor/github.com/klauspost/cpuid/cpuid_386.s create mode 100644 vendor/github.com/klauspost/cpuid/cpuid_amd64.s create mode 100644 vendor/github.com/klauspost/cpuid/detect_intel.go create mode 100644 vendor/github.com/klauspost/cpuid/detect_ref.go create mode 100644 vendor/github.com/klauspost/cpuid/generate.go create mode 100644 vendor/github.com/klauspost/cpuid/private-gen.go create mode 100644 vendor/github.com/klauspost/cpuid/private/README.md create mode 100644 vendor/github.com/klauspost/cpuid/private/cpuid.go create mode 100644 vendor/github.com/klauspost/cpuid/private/cpuid_386.s create mode 100644 vendor/github.com/klauspost/cpuid/private/cpuid_amd64.s create mode 100644 vendor/github.com/klauspost/cpuid/private/cpuid_detect_intel.go create mode 100644 vendor/github.com/klauspost/cpuid/private/cpuid_detect_ref.go create mode 100644 vendor/github.com/klauspost/crc32/.gitignore create mode 100644 vendor/github.com/klauspost/crc32/.travis.yml create mode 100644 vendor/github.com/klauspost/crc32/LICENSE create mode 100644 vendor/github.com/klauspost/crc32/README.md create mode 100644 vendor/github.com/klauspost/crc32/crc32.go create mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64.go create mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64.s create mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64p32.go create mode 100644 vendor/github.com/klauspost/crc32/crc32_amd64p32.s create mode 100644 vendor/github.com/klauspost/crc32/crc32_generic.go create mode 100644 vendor/github.com/klauspost/pgzip/.gitignore create mode 100644 vendor/github.com/klauspost/pgzip/.travis.yml create mode 100644 vendor/github.com/klauspost/pgzip/GO_LICENSE create mode 100644 vendor/github.com/klauspost/pgzip/LICENSE create mode 100644 vendor/github.com/klauspost/pgzip/README.md create mode 100644 vendor/github.com/klauspost/pgzip/circle.yml create mode 100644 vendor/github.com/klauspost/pgzip/gunzip.go create mode 100644 vendor/github.com/klauspost/pgzip/gzip.go create mode 100644 vendor/github.com/kr/fs/LICENSE create mode 100644 vendor/github.com/kr/fs/Readme create mode 100644 vendor/github.com/kr/fs/filesystem.go create mode 100644 vendor/github.com/kr/fs/walk.go create mode 100644 vendor/github.com/masterzen/simplexml/LICENSE create mode 100644 vendor/github.com/masterzen/simplexml/dom/document.go create mode 100644 vendor/github.com/masterzen/simplexml/dom/element.go create mode 100644 vendor/github.com/masterzen/simplexml/dom/namespace.go create mode 100644 vendor/github.com/masterzen/winrm/LICENSE create mode 100644 vendor/github.com/masterzen/winrm/soap/header.go create mode 100644 vendor/github.com/masterzen/winrm/soap/message.go create mode 100644 vendor/github.com/masterzen/winrm/soap/namespaces.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/client.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/command.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/endpoint.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/http.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/parameters.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/powershell.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/request.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/response.go create mode 100644 vendor/github.com/masterzen/winrm/winrm/shell.go create mode 100644 vendor/github.com/masterzen/xmlpath/LICENSE create mode 100644 vendor/github.com/masterzen/xmlpath/doc.go create mode 100644 vendor/github.com/masterzen/xmlpath/parser.go create mode 100644 vendor/github.com/masterzen/xmlpath/path.go create mode 100644 vendor/github.com/mattn/go-isatty/LICENSE create mode 100644 vendor/github.com/mattn/go-isatty/README.md create mode 100644 vendor/github.com/mattn/go-isatty/doc.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_appengine.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_bsd.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_linux.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_solaris.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_windows.go create mode 100644 vendor/github.com/mitchellh/cli/.travis.yml create mode 100644 vendor/github.com/mitchellh/cli/LICENSE create mode 100644 vendor/github.com/mitchellh/cli/README.md create mode 100644 vendor/github.com/mitchellh/cli/cli.go create mode 100644 vendor/github.com/mitchellh/cli/command.go create mode 100644 vendor/github.com/mitchellh/cli/command_mock.go create mode 100644 vendor/github.com/mitchellh/cli/help.go create mode 100644 vendor/github.com/mitchellh/cli/ui.go create mode 100644 vendor/github.com/mitchellh/cli/ui_colored.go create mode 100644 vendor/github.com/mitchellh/cli/ui_concurrent.go create mode 100644 vendor/github.com/mitchellh/cli/ui_mock.go create mode 100644 vendor/github.com/mitchellh/cli/ui_writer.go create mode 100644 vendor/github.com/mitchellh/go-fs/LICENSE create mode 100644 vendor/github.com/mitchellh/go-fs/README.md create mode 100644 vendor/github.com/mitchellh/go-fs/block_device.go create mode 100644 vendor/github.com/mitchellh/go-fs/directory.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/boot_sector.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/cluster_chain.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/directory.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/fat.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/file.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/filesystem.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/short_name.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/super_floppy.go create mode 100644 vendor/github.com/mitchellh/go-fs/fat/type.go create mode 100644 vendor/github.com/mitchellh/go-fs/file.go create mode 100644 vendor/github.com/mitchellh/go-fs/file_disk.go create mode 100644 vendor/github.com/mitchellh/go-fs/filesystem.go create mode 100644 vendor/github.com/mitchellh/go-homedir/LICENSE create mode 100644 vendor/github.com/mitchellh/go-homedir/README.md create mode 100644 vendor/github.com/mitchellh/go-homedir/homedir.go create mode 100644 vendor/github.com/mitchellh/go-vnc/LICENSE create mode 100644 vendor/github.com/mitchellh/go-vnc/README.md create mode 100644 vendor/github.com/mitchellh/go-vnc/client.go create mode 100644 vendor/github.com/mitchellh/go-vnc/client_auth.go create mode 100644 vendor/github.com/mitchellh/go-vnc/color.go create mode 100644 vendor/github.com/mitchellh/go-vnc/encoding.go create mode 100644 vendor/github.com/mitchellh/go-vnc/pixel_format.go create mode 100644 vendor/github.com/mitchellh/go-vnc/pointer.go create mode 100644 vendor/github.com/mitchellh/go-vnc/server_messages.go create mode 100644 vendor/github.com/mitchellh/iochan/LICENSE.md create mode 100644 vendor/github.com/mitchellh/iochan/README.md create mode 100644 vendor/github.com/mitchellh/iochan/iochan.go create mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 vendor/github.com/mitchellh/multistep/LICENSE.md create mode 100644 vendor/github.com/mitchellh/multistep/README.md create mode 100644 vendor/github.com/mitchellh/multistep/basic_runner.go create mode 100644 vendor/github.com/mitchellh/multistep/debug_runner.go create mode 100644 vendor/github.com/mitchellh/multistep/multistep.go create mode 100644 vendor/github.com/mitchellh/multistep/statebag.go create mode 100644 vendor/github.com/mitchellh/panicwrap/LICENSE create mode 100644 vendor/github.com/mitchellh/panicwrap/README.md create mode 100644 vendor/github.com/mitchellh/panicwrap/panicwrap.go create mode 100644 vendor/github.com/mitchellh/prefixedio/LICENSE create mode 100644 vendor/github.com/mitchellh/prefixedio/README.md create mode 100644 vendor/github.com/mitchellh/prefixedio/reader.go create mode 100644 vendor/github.com/mitchellh/reflectwalk/LICENSE create mode 100644 vendor/github.com/mitchellh/reflectwalk/README.md create mode 100644 vendor/github.com/mitchellh/reflectwalk/location.go create mode 100644 vendor/github.com/mitchellh/reflectwalk/location_string.go create mode 100644 vendor/github.com/mitchellh/reflectwalk/reflectwalk.go create mode 100644 vendor/github.com/nu7hatch/gouuid/.gitignore create mode 100644 vendor/github.com/nu7hatch/gouuid/COPYING create mode 100644 vendor/github.com/nu7hatch/gouuid/README.md create mode 100644 vendor/github.com/nu7hatch/gouuid/uuid.go create mode 100644 vendor/github.com/packer-community/winrmcp/LICENSE create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/cp.go create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/endpoint.go create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/ls.go create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/path.go create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go create mode 100644 vendor/github.com/packer-community/winrmcp/winrmcp/winrmcp.go create mode 100644 vendor/github.com/pierrec/lz4/.travis.yml create mode 100644 vendor/github.com/pierrec/lz4/LICENSE create mode 100644 vendor/github.com/pierrec/lz4/README.md create mode 100644 vendor/github.com/pierrec/lz4/block.go create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0547c73efb9b6a345fd9a52aa0798b48dd9aca62-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/05aae2cf8756f66066cf623618042ebaa92ec745-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/07fe3e792f0d2862dccc04db22c0e4aef4d41b49-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0a4ff2ab3a01888686c5bc358b72be108bbb4721-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0a7fddf3c8aa1c781223748129c9dc0807de3a6b-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0b5bec228930b2cfcda3be9a39107a6bc8044f1e-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0ca5fd3841a6777873c7ef26f65a384e7b15d065-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0ce9c3bac93df0ea1f6343d223d5220f9eb2383a-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/10.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/106b9d718c97bb7c872847d3070a570e99d9fa3e-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/11.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/113a12cbb28b83fcee714d58c35bbf52c0740e90-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/12.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1288161f8ce422490f63f257ce7338ef90fb8827-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/13.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/136f7224ae337a61df2e72b80af8b1aaa5933af3-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/13c3c26f7a34d01fc89c92ca8ba2ba5ae430c225-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/13db64707d1ea3070b4a37b6c1291d6125acbbd3-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/14.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/14193748a7b6cda204b11d042a35635151e90dbb-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/15.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/15663b854e9a4f193502ea6463dae38b4d8fca90-19 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/15e223354eb5378a7ee74a41dfab28ffc895ca33-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/16.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/17.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/177c1c68fead4507aa47dd2455fd17a10ceda5ea-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/18.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/180a2772b126d31abcb3ef692a14b13cf47f103e-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/19.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/20.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/21.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/22.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/23.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/24.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/25.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/26.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/27.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/28.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/29.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2a08d7c56ff9959698688f19ddd2e1e4d4651270-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2a33d8514fb512aa20b0a56800cd3e12f3952b6b-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2a52400dd3aa2d2a40657d1e51c47c1929912927-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2ab005ac79cd4dada693dd2a747c001898d45e1e-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2cdafdadb156e2759c389b6b8edf6a402034886c-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2d7f0171116eec9984eaa9138e1312e90a7d67ee-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/2fad20024167a500cdb8df5334a614f113efae00-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/30.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/300579a548d96d64c9da8470efa15e787f1a36f1-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/31.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/32.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/33.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/34.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/35.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/36.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/363d4559cac10516289fe1b6029590c4c7a6d8eb-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/37.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/38.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/39.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/397127b75cb59b253ed49206082b0428b6b23d02-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/40.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/41.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/42.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/43.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/44.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/45.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/46.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/47.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/48.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/49.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/49a3ead0ad96e8da5a4c8f89bd140e1d8af8995a-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4a625a4b4f3069707e88f16db88e993dabc41aa2-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4a6464c2aba2492f5122856de7ac451994eadda4-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4b55f37e6637f4246a41caa490da4bec632379d4-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4bb422b835278e4aca92d076331d9c8cc5752345-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4d49686993529cfe29473c50b9b0fb2b6ea4f6bf-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4ea726d6736026a733707e695d9c2cdc83efc05b-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/4ef3e6d20ccec24376a526ab9ec9f6f2cc604129-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/50.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/51.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/514a62216c761adf23d946f11c0d1a0410990641-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/516d84c21ac984bd1cae56910d71b62e39610c5d-29 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/52.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/53.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/54.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/55700385089e16e44968ea410c6b90206b16d72a-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/55b9a902445e2bfa2f0f37d630779d329eeda20e-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5620a492eaf067734e5b8b64517b28ec3beaa97e-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5699fea659964d8ab94069d08b0b97834c0a42df-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5765fc21629571e51adf2fc2bc8b64541a1ea08d-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5768ea5d1911143f4b1c0585b9b864ebe16aa004-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/57b780437f4abf2d5cba0775bf802a4dfdb067d6-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/58f53d40265c9a49c0d3b4292cb637464a4e376a-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5b01aeb030dc1dc9568fd32f1647d92f0692a411-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5bbd27cea704a4e6ff3f42f4792a91eb7839bc0d-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5bfd84d7b2ba6b6325d5135fb0a9ae1ec5d7d3e1-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/67ab3037ff49f082a877224d68e35069cc4d45eb-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/69dcc80940a26844b0afe7898fea9cf68b698214-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6a04b54e1511633ec895326b4e043e186fa5693b-29 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6a3e8935204dcd3dc48a1ff7415c305f0e5863aa-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6b351674a45f2d9be602fe8d3fb84229551b4ce3-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6b7f4ac7aa8b357dee3067d7a60143c03b54bb8d-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6e14a407faae939957b80e641a836735bbdcad5a-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/6f24be0bcac848e4e5b4b85bc60f70f12388a5ed-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7151692dfebfc82876676e65ee9b807d83a3df54-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/73b6bd1462a0521b4bf76abb1fd80df6e180dc80-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/73c81fef0997a4929b303e02a99f3977870f2013-29 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/73efed803abadf6167fc3f04e0674cc39c30f6af-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7603f5f266de813608c4cc1ccd1c798ef8065c5c-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/767d1943125a0f6e9397779cc757c9cdd1e05631-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/76d22068e2ed4a5952d4adc7ea8dada5509a784c-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7740102922cb9933980bb800c1115daf38edf654-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/783270b1e353ba3895b7d0c4135b8592e22f6508-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7851a406571c6b4c1aeed0af16db8c48444c3f2b-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/96c9a1fa8b0184ad486f8f68a9ddc88434579080-30 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/96cc45abef3bc9fb6659714b9743cda92ec0abb9-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9719ea029fdf8c837f991ac3548145485cc1f06e-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/984480af27d1640fd02f40e736ffcde3a91e4abb-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/992413e17d64968cb04af34c7761182f20fc97b6-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/9db70b1edad2317d94dcaafe7f5c5e3145084167-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/Mark.Twain-Tom.Sawyer.txt.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a0f3d67e96968a267366be380147cbc7b17e5b2b-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a18d849dc2a98c4ebb6000b2cc853f21fb64d9e5-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a462f03ee666a20244d3331e3635b7eb796d906d-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a56e983782e49f8267a61d4375e98b1a862862ac-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a58a9f9caca5e73b4296b931201a5ea870974c26-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a628194a08ff63e98625b1786175026c5f02c716-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a64f2336fd4a9ec8153b95f40c383e1ecfed9e73-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a6a5682a6663e0c548c9e5acbad4958e2c256b32-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a8c6a4509b61d8baa71f59f9e1eb95712b10626c-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/a9e348d9896cc740f7e910d0a70c080adb65cc77-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b20e3f27f4e8d41f16124881f92546f0fb2edc16-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b58846d79a8dc960a718ef88dd3a06ad49b1fe72-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b5b5b895b4619fa039ea99520b9947de2996c38f-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b6aca5c55295d93491e47817f46ca372c9078cec-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b6ddb90092b3087158dc32669529db2012f14c3c-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b6e7a519d013ddb67313af02a9ce966877949487-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ba98469ede70309f18893f0ff95380f5a0486fcd-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/bc0c31f304c1a1f8be0c8a0d9daa3b8aa1f23799-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/bc650b6a5356c1935f64f6fb755e43bc5f5187c4-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/be5767f4d79c5a0b2643d8eddb74eca0598674dc-19 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c34998d9a8893eca9cdeafe7b2482469ad98192b-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c5522d11f314fc46de58e15116b6910d52acf866-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/c7fe1fe2e3fc19fab3766f9fdb1d22c848d49aed-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d0e6298a63ffc2695cf7d016a124db7375f197cf-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dba53c14b92561071ccd7762550d53cf43027bdf-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dc61bdd2fb983111d1392cd79ba9b39e0a3b869f-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dd799919262810add464dbb4ee39a38f1e4ed258-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e17af76e8c119233dbd2888ab519bd76d7aa7fe9-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e346c715ac3187598d8c0453d9e741fae1232c99-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e3acf6f2b5a1b97f5a82ebf7d1822077561583fe-26 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e4a2a1469de980756c607cdc2584fc94bc109382-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/e7ea1bfd65ca7db84f0984474658bfc3b063c63a-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ea212596f8a7aec4eb2e85fd2cdb5c2816b58495-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ea9af92f89e6889b523461ae7b2b9fecee5a7280-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ebc69b7ca13ae23b075c9b21ebc283278714e3aa-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ec8e760e79dc08a79af0d79c510cafb74e504472-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ec984b6fb8e41dbcd4299ecd1dd6fd0a77347122-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/edbc11de7dd074c367a69532db023cd810bb3978-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ee6afbf375619a2bd6fb0abe0e42e51ab3b0ab13-6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ee907d38c1394c4971b389a99a3be0913836212b-9 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/eebbefa1983c9e1aeb5217aabcac7ab24dfe166f-17 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/eee3d4a9a8b297f016c23f50a9792c30a621720e-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ef87432939473264357babc06257b0280ffd15ee-5 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/efdd522fe3abb88204f63b1fe7312f62b6ee593d-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f35bdf2e8b4af93c6a73e564055aa4eacd9f0d0c-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f3a2381d6f39defe22520aea46201e6ce6d37f80-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f3e916907eab3412b5875e5eca05bf3eac8a8d5e-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f86152e5ce510dc674fa73d20b324e2d3c4d145b-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/f931bee2e7f1fefd8bb2fabf88f8f3d2b3ea78fa-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fb56a1001599e07354ce3101af111554c6c9bb40-1 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fb75f3059f8835a7e8781c899af756f22d1c06b4-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fbfe35b0485040874ed564b94ba764bdd17e80fc-10 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fcb1c8b1893ca85647581cadec481754d8f35c96-12 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fcb33fb48e48acd9155fd7ed8e82e71c850ffd22-16 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fcd47a15e10a21e1eb13aeac223becc89aac4c69-2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fdb78af507e72288b059ff902ae5e76538d1e6ea-14 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/ffa97253e1ab365b84eebb9d257f9370b7796fbf-28 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/corpus/pss-vect.txt.bz2 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b.output create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b.quoted create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458.output create mode 100644 vendor/github.com/pierrec/lz4/fuzz/crashers/ea0a00651ba4143c05fe7b5c85f69fe16a29a458.quoted create mode 100644 vendor/github.com/pierrec/lz4/fuzz/lz4-fuzz.zip create mode 100644 vendor/github.com/pierrec/lz4/fuzz/lz4.go create mode 100644 vendor/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 create mode 100644 vendor/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 create mode 100644 vendor/github.com/pierrec/lz4/lz4.go create mode 100644 vendor/github.com/pierrec/lz4/lz4c/main.go create mode 100644 vendor/github.com/pierrec/lz4/reader.go create mode 100644 vendor/github.com/pierrec/lz4/writer.go create mode 100644 vendor/github.com/pierrec/xxHash/LICENSE create mode 100644 vendor/github.com/pierrec/xxHash/xxHash32/xxHash32.go create mode 100644 vendor/github.com/pkg/sftp/.gitignore create mode 100644 vendor/github.com/pkg/sftp/.travis.yml create mode 100644 vendor/github.com/pkg/sftp/CONTRIBUTORS create mode 100644 vendor/github.com/pkg/sftp/LICENSE create mode 100644 vendor/github.com/pkg/sftp/README.md create mode 100644 vendor/github.com/pkg/sftp/attrs.go create mode 100644 vendor/github.com/pkg/sftp/attrs_stubs.go create mode 100644 vendor/github.com/pkg/sftp/attrs_unix.go create mode 100644 vendor/github.com/pkg/sftp/client.go create mode 100644 vendor/github.com/pkg/sftp/debug.go create mode 100644 vendor/github.com/pkg/sftp/examples/buffered-read-benchmark/main.go create mode 100644 vendor/github.com/pkg/sftp/examples/buffered-write-benchmark/main.go create mode 100644 vendor/github.com/pkg/sftp/examples/sftp-server/README.md create mode 100644 vendor/github.com/pkg/sftp/examples/sftp-server/main.go create mode 100644 vendor/github.com/pkg/sftp/examples/streaming-read-benchmark/main.go create mode 100644 vendor/github.com/pkg/sftp/examples/streaming-write-benchmark/main.go create mode 100644 vendor/github.com/pkg/sftp/packet.go create mode 100644 vendor/github.com/pkg/sftp/release.go create mode 100644 vendor/github.com/pkg/sftp/server.go create mode 100644 vendor/github.com/pkg/sftp/server_standalone/main.go create mode 100644 vendor/github.com/pkg/sftp/server_stubs.go create mode 100644 vendor/github.com/pkg/sftp/server_unix.go create mode 100644 vendor/github.com/pkg/sftp/sftp.go create mode 100644 vendor/github.com/rackspace/gophercloud/.travis.yml create mode 100644 vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md create mode 100644 vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md create mode 100644 vendor/github.com/rackspace/gophercloud/LICENSE create mode 100644 vendor/github.com/rackspace/gophercloud/README.md create mode 100644 vendor/github.com/rackspace/gophercloud/UPGRADING.md create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/README.md create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go create mode 100644 vendor/github.com/rackspace/gophercloud/auth_options.go create mode 100644 vendor/github.com/rackspace/gophercloud/auth_results.go create mode 100644 vendor/github.com/rackspace/gophercloud/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/endpoint_search.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/auth_env.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/client.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/README.md create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/endpoint_location.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/docs.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/common/common_tests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/errors.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/environment.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/template.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/utils.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/utils/choose_version.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/http.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/linked.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/marker.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/null.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/pager.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/pkg.go create mode 100644 vendor/github.com/rackspace/gophercloud/pagination/single.go create mode 100644 vendor/github.com/rackspace/gophercloud/params.go create mode 100644 vendor/github.com/rackspace/gophercloud/provider_client.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/auth_env.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/client.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/common/common_tests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/networks/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/ports/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/groups/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/rules/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/subnets/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/request.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/fixtures.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/delegate.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/requests.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/urls.go create mode 100644 vendor/github.com/rackspace/gophercloud/results.go create mode 100644 vendor/github.com/rackspace/gophercloud/script/acceptancetest create mode 100644 vendor/github.com/rackspace/gophercloud/script/bootstrap create mode 100644 vendor/github.com/rackspace/gophercloud/script/cibuild create mode 100644 vendor/github.com/rackspace/gophercloud/script/test create mode 100644 vendor/github.com/rackspace/gophercloud/script/unittest create mode 100644 vendor/github.com/rackspace/gophercloud/service_client.go create mode 100644 vendor/github.com/rackspace/gophercloud/testhelper/client/fake.go create mode 100644 vendor/github.com/rackspace/gophercloud/testhelper/convenience.go create mode 100644 vendor/github.com/rackspace/gophercloud/testhelper/doc.go create mode 100644 vendor/github.com/rackspace/gophercloud/testhelper/fixture/helper.go create mode 100644 vendor/github.com/rackspace/gophercloud/testhelper/http_responses.go create mode 100644 vendor/github.com/rackspace/gophercloud/util.go create mode 100644 vendor/github.com/satori/go.uuid/.travis.yml create mode 100644 vendor/github.com/satori/go.uuid/LICENSE create mode 100644 vendor/github.com/satori/go.uuid/README.md create mode 100644 vendor/github.com/satori/go.uuid/uuid.go create mode 100644 vendor/github.com/tent/http-link-go/.gitignore create mode 100644 vendor/github.com/tent/http-link-go/.travis.yml create mode 100644 vendor/github.com/tent/http-link-go/LICENSE create mode 100644 vendor/github.com/tent/http-link-go/README.md create mode 100644 vendor/github.com/tent/http-link-go/link.go create mode 100644 vendor/github.com/ugorji/go/LICENSE create mode 100644 vendor/github.com/ugorji/go/codec/0doc.go create mode 100644 vendor/github.com/ugorji/go/codec/README.md create mode 100644 vendor/github.com/ugorji/go/codec/binc.go create mode 100644 vendor/github.com/ugorji/go/codec/cbor.go create mode 100644 vendor/github.com/ugorji/go/codec/codecgen/README.md create mode 100644 vendor/github.com/ugorji/go/codec/codecgen/gen.go create mode 100644 vendor/github.com/ugorji/go/codec/codecgen/z.go create mode 100644 vendor/github.com/ugorji/go/codec/decode.go create mode 100644 vendor/github.com/ugorji/go/codec/encode.go create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.not.go create mode 100644 vendor/github.com/ugorji/go/codec/gen-dec-array.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen-dec-map.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen-helper.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/gen-helper.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/gen.go create mode 100644 vendor/github.com/ugorji/go/codec/helper.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_internal.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_not_unsafe.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_unsafe.go create mode 100644 vendor/github.com/ugorji/go/codec/json.go create mode 100644 vendor/github.com/ugorji/go/codec/msgpack.go create mode 100644 vendor/github.com/ugorji/go/codec/noop.go create mode 100644 vendor/github.com/ugorji/go/codec/prebuild.go create mode 100644 vendor/github.com/ugorji/go/codec/prebuild.sh create mode 100644 vendor/github.com/ugorji/go/codec/rpc.go create mode 100644 vendor/github.com/ugorji/go/codec/simple.go create mode 100644 vendor/github.com/ugorji/go/codec/test-cbor-goldens.json create mode 100644 vendor/github.com/ugorji/go/codec/test.py create mode 100644 vendor/github.com/ugorji/go/codec/tests.sh create mode 100644 vendor/github.com/ugorji/go/codec/time.go create mode 100644 vendor/golang.org/x/crypto/LICENSE create mode 100644 vendor/golang.org/x/crypto/PATENTS create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go create mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go create mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go create mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/forward.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server.go create mode 100644 vendor/golang.org/x/crypto/ssh/buffer.go create mode 100644 vendor/golang.org/x/crypto/ssh/certs.go create mode 100644 vendor/golang.org/x/crypto/ssh/channel.go create mode 100644 vendor/golang.org/x/crypto/ssh/cipher.go create mode 100644 vendor/golang.org/x/crypto/ssh/client.go create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth.go create mode 100644 vendor/golang.org/x/crypto/ssh/common.go create mode 100644 vendor/golang.org/x/crypto/ssh/connection.go create mode 100644 vendor/golang.org/x/crypto/ssh/doc.go create mode 100644 vendor/golang.org/x/crypto/ssh/handshake.go create mode 100644 vendor/golang.org/x/crypto/ssh/kex.go create mode 100644 vendor/golang.org/x/crypto/ssh/keys.go create mode 100644 vendor/golang.org/x/crypto/ssh/mac.go create mode 100644 vendor/golang.org/x/crypto/ssh/messages.go create mode 100644 vendor/golang.org/x/crypto/ssh/mux.go create mode 100644 vendor/golang.org/x/crypto/ssh/server.go create mode 100644 vendor/golang.org/x/crypto/ssh/session.go create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_linux.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_windows.go create mode 100644 vendor/golang.org/x/crypto/ssh/test/doc.go create mode 100644 vendor/golang.org/x/crypto/ssh/transport.go create mode 100644 vendor/golang.org/x/net/LICENSE create mode 100644 vendor/golang.org/x/net/PATENTS create mode 100644 vendor/golang.org/x/net/context/context.go create mode 100644 vendor/golang.org/x/net/context/ctxhttp/cancelreq.go create mode 100644 vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go create mode 100644 vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go create mode 100644 vendor/golang.org/x/net/html/atom/atom.go create mode 100644 vendor/golang.org/x/net/html/atom/gen.go create mode 100644 vendor/golang.org/x/net/html/atom/table.go create mode 100644 vendor/golang.org/x/net/html/charset/charset.go create mode 100644 vendor/golang.org/x/net/html/const.go create mode 100644 vendor/golang.org/x/net/html/doc.go create mode 100644 vendor/golang.org/x/net/html/doctype.go create mode 100644 vendor/golang.org/x/net/html/entity.go create mode 100644 vendor/golang.org/x/net/html/escape.go create mode 100644 vendor/golang.org/x/net/html/foreign.go create mode 100644 vendor/golang.org/x/net/html/node.go create mode 100644 vendor/golang.org/x/net/html/parse.go create mode 100644 vendor/golang.org/x/net/html/render.go create mode 100644 vendor/golang.org/x/net/html/token.go create mode 100644 vendor/golang.org/x/oauth2/.travis.yml create mode 100644 vendor/golang.org/x/oauth2/AUTHORS create mode 100644 vendor/golang.org/x/oauth2/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/oauth2/CONTRIBUTORS create mode 100644 vendor/golang.org/x/oauth2/LICENSE create mode 100644 vendor/golang.org/x/oauth2/README.md create mode 100644 vendor/golang.org/x/oauth2/bitbucket/bitbucket.go create mode 100644 vendor/golang.org/x/oauth2/client_appengine.go create mode 100644 vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go create mode 100644 vendor/golang.org/x/oauth2/facebook/facebook.go create mode 100644 vendor/golang.org/x/oauth2/github/github.go create mode 100644 vendor/golang.org/x/oauth2/google/appengine.go create mode 100644 vendor/golang.org/x/oauth2/google/appengine_hook.go create mode 100644 vendor/golang.org/x/oauth2/google/appenginevm_hook.go create mode 100644 vendor/golang.org/x/oauth2/google/default.go create mode 100644 vendor/golang.org/x/oauth2/google/google.go create mode 100644 vendor/golang.org/x/oauth2/google/jwt.go create mode 100644 vendor/golang.org/x/oauth2/google/sdk.go create mode 100644 vendor/golang.org/x/oauth2/internal/oauth2.go create mode 100644 vendor/golang.org/x/oauth2/internal/token.go create mode 100644 vendor/golang.org/x/oauth2/internal/transport.go create mode 100644 vendor/golang.org/x/oauth2/jws/jws.go create mode 100644 vendor/golang.org/x/oauth2/jwt/jwt.go create mode 100644 vendor/golang.org/x/oauth2/linkedin/linkedin.go create mode 100644 vendor/golang.org/x/oauth2/microsoft/microsoft.go create mode 100644 vendor/golang.org/x/oauth2/oauth2.go create mode 100644 vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go create mode 100644 vendor/golang.org/x/oauth2/paypal/paypal.go create mode 100644 vendor/golang.org/x/oauth2/token.go create mode 100644 vendor/golang.org/x/oauth2/transport.go create mode 100644 vendor/golang.org/x/oauth2/vk/vk.go create mode 100644 vendor/golang.org/x/sys/LICENSE create mode 100644 vendor/golang.org/x/sys/PATENTS create mode 100644 vendor/golang.org/x/sys/unix/.gitignore create mode 100644 vendor/golang.org/x/sys/unix/asm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_solaris_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/constants.go create mode 100644 vendor/golang.org/x/sys/unix/env_unix.go create mode 100644 vendor/golang.org/x/sys/unix/env_unset.go create mode 100644 vendor/golang.org/x/sys/unix/flock.go create mode 100644 vendor/golang.org/x/sys/unix/flock_linux_32bit.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo_c.c create mode 100644 vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/mkall.sh create mode 100644 vendor/golang.org/x/sys/unix/mkerrors.sh create mode 100644 vendor/golang.org/x/sys/unix/mksyscall.pl create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_linux.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl create mode 100644 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl create mode 100644 vendor/golang.org/x/sys/unix/race.go create mode 100644 vendor/golang.org/x/sys/unix/race0.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_linux.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix.go create mode 100644 vendor/golang.org/x/sys/unix/str.go create mode 100644 vendor/golang.org/x/sys/unix/syscall.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_no_getwd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix.go create mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_linux.go create mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go create mode 100644 vendor/google.golang.org/api/LICENSE create mode 100644 vendor/google.golang.org/api/compute/v1/compute-api.json create mode 100644 vendor/google.golang.org/api/compute/v1/compute-gen.go create mode 100644 vendor/google.golang.org/api/gensupport/backoff.go create mode 100644 vendor/google.golang.org/api/gensupport/buffer.go create mode 100644 vendor/google.golang.org/api/gensupport/doc.go create mode 100644 vendor/google.golang.org/api/gensupport/json.go create mode 100644 vendor/google.golang.org/api/gensupport/media.go create mode 100644 vendor/google.golang.org/api/gensupport/params.go create mode 100644 vendor/google.golang.org/api/gensupport/resumable.go create mode 100644 vendor/google.golang.org/api/googleapi/googleapi.go create mode 100644 vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE create mode 100644 vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go create mode 100644 vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go create mode 100644 vendor/google.golang.org/api/googleapi/transport/apikey.go create mode 100644 vendor/google.golang.org/api/googleapi/types.go create mode 100644 vendor/google.golang.org/appengine/.travis.yml create mode 100644 vendor/google.golang.org/appengine/LICENSE create mode 100644 vendor/google.golang.org/appengine/README.md create mode 100644 vendor/google.golang.org/appengine/aetest/doc.go create mode 100644 vendor/google.golang.org/appengine/aetest/instance.go create mode 100644 vendor/google.golang.org/appengine/aetest/instance_classic.go create mode 100644 vendor/google.golang.org/appengine/aetest/instance_vm.go create mode 100644 vendor/google.golang.org/appengine/aetest/user.go create mode 100644 vendor/google.golang.org/appengine/appengine.go create mode 100644 vendor/google.golang.org/appengine/appengine_vm.go create mode 100644 vendor/google.golang.org/appengine/blobstore/blobstore.go create mode 100644 vendor/google.golang.org/appengine/blobstore/read.go create mode 100644 vendor/google.golang.org/appengine/capability/capability.go create mode 100644 vendor/google.golang.org/appengine/channel/channel.go create mode 100644 vendor/google.golang.org/appengine/cloudsql/cloudsql.go create mode 100644 vendor/google.golang.org/appengine/cloudsql/cloudsql_classic.go create mode 100644 vendor/google.golang.org/appengine/cloudsql/cloudsql_vm.go create mode 100644 vendor/google.golang.org/appengine/cmd/aebundler/aebundler.go create mode 100644 vendor/google.golang.org/appengine/cmd/aedeploy/aedeploy.go create mode 100644 vendor/google.golang.org/appengine/datastore/datastore.go create mode 100644 vendor/google.golang.org/appengine/datastore/doc.go create mode 100644 vendor/google.golang.org/appengine/datastore/key.go create mode 100644 vendor/google.golang.org/appengine/datastore/load.go create mode 100644 vendor/google.golang.org/appengine/datastore/metadata.go create mode 100644 vendor/google.golang.org/appengine/datastore/prop.go create mode 100644 vendor/google.golang.org/appengine/datastore/query.go create mode 100644 vendor/google.golang.org/appengine/datastore/save.go create mode 100644 vendor/google.golang.org/appengine/datastore/transaction.go create mode 100644 vendor/google.golang.org/appengine/delay/delay.go create mode 100644 vendor/google.golang.org/appengine/demos/guestbook/app.yaml create mode 100644 vendor/google.golang.org/appengine/demos/guestbook/favicon.ico create mode 100644 vendor/google.golang.org/appengine/demos/guestbook/guestbook.go create mode 100644 vendor/google.golang.org/appengine/demos/guestbook/index.yaml create mode 100644 vendor/google.golang.org/appengine/demos/guestbook/templates/guestbook.html create mode 100644 vendor/google.golang.org/appengine/demos/helloworld/app.yaml create mode 100644 vendor/google.golang.org/appengine/demos/helloworld/favicon.ico create mode 100644 vendor/google.golang.org/appengine/demos/helloworld/helloworld.go create mode 100644 vendor/google.golang.org/appengine/errors.go create mode 100644 vendor/google.golang.org/appengine/file/file.go create mode 100644 vendor/google.golang.org/appengine/identity.go create mode 100644 vendor/google.golang.org/appengine/image/image.go create mode 100644 vendor/google.golang.org/appengine/internal/aetesting/fake.go create mode 100644 vendor/google.golang.org/appengine/internal/api.go create mode 100644 vendor/google.golang.org/appengine/internal/api_classic.go create mode 100644 vendor/google.golang.org/appengine/internal/api_common.go create mode 100644 vendor/google.golang.org/appengine/internal/app_id.go create mode 100644 vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/base/api_base.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/base/api_base.proto create mode 100644 vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/capability/capability_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/capability/capability_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/channel/channel_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/channel/channel_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto create mode 100644 vendor/google.golang.org/appengine/internal/identity.go create mode 100644 vendor/google.golang.org/appengine/internal/identity_classic.go create mode 100644 vendor/google.golang.org/appengine/internal/identity_vm.go create mode 100644 vendor/google.golang.org/appengine/internal/image/images_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/image/images_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/internal.go create mode 100644 vendor/google.golang.org/appengine/internal/log/log_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/log/log_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/mail/mail_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/mail/mail_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/metadata.go create mode 100644 vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/modules/modules_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/net.go create mode 100644 vendor/google.golang.org/appengine/internal/regen.sh create mode 100644 vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto create mode 100644 vendor/google.golang.org/appengine/internal/search/search.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/search/search.proto create mode 100644 vendor/google.golang.org/appengine/internal/socket/socket_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/socket/socket_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/system/system_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/system/system_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/transaction.go create mode 100644 vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/user/user_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/user/user_service.proto create mode 100644 vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.pb.go create mode 100644 vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.proto create mode 100644 vendor/google.golang.org/appengine/log/api.go create mode 100644 vendor/google.golang.org/appengine/log/log.go create mode 100644 vendor/google.golang.org/appengine/mail/mail.go create mode 100644 vendor/google.golang.org/appengine/memcache/memcache.go create mode 100644 vendor/google.golang.org/appengine/module/module.go create mode 100644 vendor/google.golang.org/appengine/namespace.go create mode 100644 vendor/google.golang.org/appengine/remote_api/client.go create mode 100644 vendor/google.golang.org/appengine/remote_api/remote_api.go create mode 100644 vendor/google.golang.org/appengine/runtime/runtime.go create mode 100644 vendor/google.golang.org/appengine/search/doc.go create mode 100644 vendor/google.golang.org/appengine/search/field.go create mode 100644 vendor/google.golang.org/appengine/search/search.go create mode 100644 vendor/google.golang.org/appengine/search/struct.go create mode 100644 vendor/google.golang.org/appengine/socket/doc.go create mode 100644 vendor/google.golang.org/appengine/socket/socket_classic.go create mode 100644 vendor/google.golang.org/appengine/socket/socket_vm.go create mode 100644 vendor/google.golang.org/appengine/taskqueue/taskqueue.go create mode 100644 vendor/google.golang.org/appengine/timeout.go create mode 100644 vendor/google.golang.org/appengine/urlfetch/urlfetch.go create mode 100644 vendor/google.golang.org/appengine/user/oauth.go create mode 100644 vendor/google.golang.org/appengine/user/user.go create mode 100644 vendor/google.golang.org/appengine/user/user_classic.go create mode 100644 vendor/google.golang.org/appengine/user/user_vm.go create mode 100644 vendor/google.golang.org/appengine/xmpp/xmpp.go create mode 100644 vendor/google.golang.org/cloud/LICENSE create mode 100644 vendor/google.golang.org/cloud/compute/metadata/metadata.go create mode 100644 vendor/google.golang.org/cloud/internal/cloud.go create mode 100644 vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go create mode 100644 vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto create mode 100644 vendor/google.golang.org/cloud/internal/opts/option.go create mode 100644 vendor/google.golang.org/cloud/internal/testutil/context.go create mode 100644 vendor/google.golang.org/cloud/internal/transport/cancelreq.go create mode 100644 vendor/google.golang.org/cloud/internal/transport/cancelreq_legacy.go create mode 100644 vendor/google.golang.org/cloud/internal/transport/dial.go create mode 100644 vendor/google.golang.org/cloud/internal/transport/proto.go create mode 100644 vendor/gopkg.in/fsnotify.v1/.gitignore create mode 100644 vendor/gopkg.in/fsnotify.v1/.travis.yml create mode 100644 vendor/gopkg.in/fsnotify.v1/AUTHORS create mode 100644 vendor/gopkg.in/fsnotify.v1/CHANGELOG.md create mode 100644 vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md create mode 100644 vendor/gopkg.in/fsnotify.v1/LICENSE create mode 100644 vendor/gopkg.in/fsnotify.v1/README.md create mode 100644 vendor/gopkg.in/fsnotify.v1/fsnotify.go create mode 100644 vendor/gopkg.in/fsnotify.v1/inotify.go create mode 100644 vendor/gopkg.in/fsnotify.v1/inotify_poller.go create mode 100644 vendor/gopkg.in/fsnotify.v1/kqueue.go create mode 100644 vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go create mode 100644 vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go create mode 100644 vendor/gopkg.in/fsnotify.v1/windows.go create mode 100644 vendor/gopkg.in/tomb.v1/LICENSE create mode 100644 vendor/gopkg.in/tomb.v1/README.md create mode 100644 vendor/gopkg.in/tomb.v1/tomb.go create mode 100644 vendor/gopkg.in/xmlpath.v2/LICENSE create mode 100644 vendor/gopkg.in/xmlpath.v2/README.md create mode 100644 vendor/gopkg.in/xmlpath.v2/cmd/webpath/main.go create mode 100644 vendor/gopkg.in/xmlpath.v2/doc.go create mode 100644 vendor/gopkg.in/xmlpath.v2/parser.go create mode 100644 vendor/gopkg.in/xmlpath.v2/path.go diff --git a/vendor/github.com/ActiveState/tail/.gitignore b/vendor/github.com/ActiveState/tail/.gitignore new file mode 100644 index 000000000..6d9953c3c --- /dev/null +++ b/vendor/github.com/ActiveState/tail/.gitignore @@ -0,0 +1,3 @@ +.test +.go + diff --git a/vendor/github.com/ActiveState/tail/.travis.yml b/vendor/github.com/ActiveState/tail/.travis.yml new file mode 100644 index 000000000..15fbdbcff --- /dev/null +++ b/vendor/github.com/ActiveState/tail/.travis.yml @@ -0,0 +1,13 @@ +language: go + +script: + - go test -race -v ./... + +go: + - 1.3.3 + - 1.4.3 + - 1.5.2 + +install: + - go get gopkg.in/fsnotify.v1 + - go get gopkg.in/tomb.v1 diff --git a/vendor/github.com/ActiveState/tail/CHANGES.md b/vendor/github.com/ActiveState/tail/CHANGES.md new file mode 100644 index 000000000..3725d1e24 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/CHANGES.md @@ -0,0 +1,57 @@ +# API current (gopkg.in/ActiveState/tail) + +## July, 2015 + +* Fix inotify watcher leak; remove `Cleanup` (#51) + +# API v0 (gopkg.in/ActiveState/tail.v0) + +## June, 2015 + +* Don't return partial lines (PR #40) +* Use stable version of fsnotify (#46) + +## July, 2014 + +* Fix tail for Windows (PR #36) + +## May, 2014 + +* Improved rate limiting using leaky bucket (PR #29) +* Fix odd line splitting (PR #30) + +## Apr, 2014 + +* LimitRate now discards read buffer (PR #28) +* allow reading of longer lines if MaxLineSize is unset (PR #24) +* updated deps.json to latest fsnotify (441bbc86b1) + +## Feb, 2014 + +* added `Config.Logger` to suppress library logging + +## Nov, 2013 + +* add Cleanup to remove leaky inotify watches (PR #20) + +## Aug, 2013 + +* redesigned Location field (PR #12) +* add tail.Tell (PR #14) + +## July, 2013 + +* Rate limiting (PR #10) + +## May, 2013 + +* Detect file deletions/renames in polling file watcher (PR #1) +* Detect file truncation +* Fix potential race condition when reopening the file (issue 5) +* Fix potential blocking of `tail.Stop` (issue 4) +* Fix uncleaned up ChangeEvents goroutines after calling tail.Stop +* Support Follow=false + +## Feb, 2013 + +* Initial open source release diff --git a/vendor/github.com/ActiveState/tail/Dockerfile b/vendor/github.com/ActiveState/tail/Dockerfile new file mode 100644 index 000000000..cd297b940 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/Dockerfile @@ -0,0 +1,19 @@ +FROM golang + +RUN mkdir -p $GOPATH/src/github.com/hpcloud/tail/ +ADD . $GOPATH/src/github.com/hpcloud/tail/ + +# expecting to fetch dependencies successfully. +RUN go get -v github.com/hpcloud/tail + +# expecting to run the test successfully. +RUN go test -v github.com/hpcloud/tail + +# expecting to install successfully +RUN go install -v github.com/hpcloud/tail +RUN go install -v github.com/hpcloud/tail/cmd/gotail + +RUN $GOPATH/bin/gotail -h || true + +ENV PATH $GOPATH/bin:$PATH +CMD ["gotail"] diff --git a/vendor/github.com/ActiveState/tail/LICENSE.txt b/vendor/github.com/ActiveState/tail/LICENSE.txt new file mode 100644 index 000000000..ea07fde89 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/LICENSE.txt @@ -0,0 +1,23 @@ +# This is the MIT license + +# Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/ActiveState/tail/Makefile b/vendor/github.com/ActiveState/tail/Makefile new file mode 100644 index 000000000..9ac927db1 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/Makefile @@ -0,0 +1,11 @@ +default: test + +test: *.go + go test -v ./... + +fmt: + gofmt -w . + +# Run the test in an isolated environment. +fulltest: + docker build -t hpcloud/tail . diff --git a/vendor/github.com/ActiveState/tail/README.md b/vendor/github.com/ActiveState/tail/README.md new file mode 100644 index 000000000..e494ab5ff --- /dev/null +++ b/vendor/github.com/ActiveState/tail/README.md @@ -0,0 +1,27 @@ +[![Build Status](https://travis-ci.org/hpcloud/tail.svg)](https://travis-ci.org/hpcloud/tail) + +# Go package for tail-ing files + +A Go package striving to emulate the features of the BSD `tail` program. + +```Go +t, err := tail.TailFile("/var/log/nginx.log", tail.Config{Follow: true}) +for line := range t.Lines { + fmt.Println(line.Text) +} +``` + +See [API documentation](http://godoc.org/github.com/hpcloud/tail). + +## Log rotation + +Tail comes with full support for truncation/move detection as it is +designed to work with log rotation tools. + +## Installing + + go get github.com/hpcloud/tail/... + +## Windows support + +This package [needs assistance](https://github.com/hpcloud/tail/labels/Windows) for full Windows support. diff --git a/vendor/github.com/ActiveState/tail/cmd/gotail/.gitignore b/vendor/github.com/ActiveState/tail/cmd/gotail/.gitignore new file mode 100644 index 000000000..6249af5fb --- /dev/null +++ b/vendor/github.com/ActiveState/tail/cmd/gotail/.gitignore @@ -0,0 +1 @@ +gotail diff --git a/vendor/github.com/ActiveState/tail/cmd/gotail/Makefile b/vendor/github.com/ActiveState/tail/cmd/gotail/Makefile new file mode 100644 index 000000000..6b5a2d957 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/cmd/gotail/Makefile @@ -0,0 +1,4 @@ +default: gotail + +gotail: *.go ../../*.go + go build diff --git a/vendor/github.com/ActiveState/tail/cmd/gotail/gotail.go b/vendor/github.com/ActiveState/tail/cmd/gotail/gotail.go new file mode 100644 index 000000000..c63b58286 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/cmd/gotail/gotail.go @@ -0,0 +1,64 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package main + +import ( + "flag" + "fmt" + "github.com/hpcloud/tail" + "os" +) + +func args2config() (tail.Config, int64) { + config := tail.Config{Follow: true} + n := int64(0) + maxlinesize := int(0) + flag.Int64Var(&n, "n", 0, "tail from the last Nth location") + flag.IntVar(&maxlinesize, "max", 0, "max line size") + flag.BoolVar(&config.Follow, "f", false, "wait for additional data to be appended to the file") + flag.BoolVar(&config.ReOpen, "F", false, "follow, and track file rename/rotation") + flag.BoolVar(&config.Poll, "p", false, "use polling, instead of inotify") + flag.Parse() + if config.ReOpen { + config.Follow = true + } + config.MaxLineSize = maxlinesize + return config, n +} + +func main() { + config, n := args2config() + if flag.NFlag() < 1 { + fmt.Println("need one or more files as arguments") + os.Exit(1) + } + + if n != 0 { + config.Location = &tail.SeekInfo{-n, os.SEEK_END} + } + + done := make(chan bool) + for _, filename := range flag.Args() { + go tailFile(filename, config, done) + } + + for _, _ = range flag.Args() { + <-done + } +} + +func tailFile(filename string, config tail.Config, done chan bool) { + defer func() { done <- true }() + t, err := tail.TailFile(filename, config) + if err != nil { + fmt.Println(err) + return + } + for line := range t.Lines { + fmt.Println(line.Text) + } + err = t.Wait() + if err != nil { + fmt.Println(err) + } +} diff --git a/vendor/github.com/ActiveState/tail/deps.json b/vendor/github.com/ActiveState/tail/deps.json new file mode 100644 index 000000000..87e78bdde --- /dev/null +++ b/vendor/github.com/ActiveState/tail/deps.json @@ -0,0 +1,14 @@ +{ + "github.com/howeyc/fsnotify": { + "repo": "http://github.com/howeyc/fsnotify.git", + "version": "441bbc86b167", + "type": "git-clone", + "alias": "github.com/howeyc/fsnotify" + }, + "gopkg.in/tomb.v1": { + "repo": "https://github.com/go-tomb/tomb.git", + "version": "c131134a1947e9afd9cecfe11f4c6dff0732ae58", + "type": "git-clone", + "alias": "gopkg.in/tomb.v1" + } +} diff --git a/vendor/github.com/ActiveState/tail/ratelimiter/Licence b/vendor/github.com/ActiveState/tail/ratelimiter/Licence new file mode 100644 index 000000000..434aab19f --- /dev/null +++ b/vendor/github.com/ActiveState/tail/ratelimiter/Licence @@ -0,0 +1,7 @@ +Copyright (C) 2013 99designs + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/ActiveState/tail/ratelimiter/leakybucket.go b/vendor/github.com/ActiveState/tail/ratelimiter/leakybucket.go new file mode 100644 index 000000000..358b69e7f --- /dev/null +++ b/vendor/github.com/ActiveState/tail/ratelimiter/leakybucket.go @@ -0,0 +1,97 @@ +// Package ratelimiter implements the Leaky Bucket ratelimiting algorithm with memcached and in-memory backends. +package ratelimiter + +import ( + "time" +) + +type LeakyBucket struct { + Size uint16 + Fill float64 + LeakInterval time.Duration // time.Duration for 1 unit of size to leak + Lastupdate time.Time + Now func() time.Time +} + +func NewLeakyBucket(size uint16, leakInterval time.Duration) *LeakyBucket { + bucket := LeakyBucket{ + Size: size, + Fill: 0, + LeakInterval: leakInterval, + Now: time.Now, + Lastupdate: time.Now(), + } + + return &bucket +} + +func (b *LeakyBucket) updateFill() { + now := b.Now() + if b.Fill > 0 { + elapsed := now.Sub(b.Lastupdate) + + b.Fill -= float64(elapsed) / float64(b.LeakInterval) + if b.Fill < 0 { + b.Fill = 0 + } + } + b.Lastupdate = now +} + +func (b *LeakyBucket) Pour(amount uint16) bool { + b.updateFill() + + var newfill float64 = b.Fill + float64(amount) + + if newfill > float64(b.Size) { + return false + } + + b.Fill = newfill + + return true +} + +// The time at which this bucket will be completely drained +func (b *LeakyBucket) DrainedAt() time.Time { + return b.Lastupdate.Add(time.Duration(b.Fill * float64(b.LeakInterval))) +} + +// The duration until this bucket is completely drained +func (b *LeakyBucket) TimeToDrain() time.Duration { + return b.DrainedAt().Sub(b.Now()) +} + +func (b *LeakyBucket) TimeSinceLastUpdate() time.Duration { + return b.Now().Sub(b.Lastupdate) +} + +type LeakyBucketSer struct { + Size uint16 + Fill float64 + LeakInterval time.Duration // time.Duration for 1 unit of size to leak + Lastupdate time.Time +} + +func (b *LeakyBucket) Serialise() *LeakyBucketSer { + bucket := LeakyBucketSer{ + Size: b.Size, + Fill: b.Fill, + LeakInterval: b.LeakInterval, + Lastupdate: b.Lastupdate, + } + + return &bucket +} + +func (b *LeakyBucketSer) DeSerialise() *LeakyBucket { + bucket := LeakyBucket{ + Size: b.Size, + Fill: b.Fill, + LeakInterval: b.LeakInterval, + Lastupdate: b.Lastupdate, + Now: time.Now, + } + + return &bucket +} diff --git a/vendor/github.com/ActiveState/tail/ratelimiter/memory.go b/vendor/github.com/ActiveState/tail/ratelimiter/memory.go new file mode 100644 index 000000000..8f6a5784a --- /dev/null +++ b/vendor/github.com/ActiveState/tail/ratelimiter/memory.go @@ -0,0 +1,58 @@ +package ratelimiter + +import ( + "errors" + "time" +) + +const GC_SIZE int = 100 + +type Memory struct { + store map[string]LeakyBucket + lastGCCollected time.Time +} + +func NewMemory() *Memory { + m := new(Memory) + m.store = make(map[string]LeakyBucket) + m.lastGCCollected = time.Now() + return m +} + +func (m *Memory) GetBucketFor(key string) (*LeakyBucket, error) { + + bucket, ok := m.store[key] + if !ok { + return nil, errors.New("miss") + } + + return &bucket, nil +} + +func (m *Memory) SetBucketFor(key string, bucket LeakyBucket) error { + + if len(m.store) > GC_SIZE { + m.GarbageCollect() + } + + m.store[key] = bucket + + return nil +} + +func (m *Memory) GarbageCollect() { + now := time.Now() + + // rate limit GC to once per minute + if now.Add(60*time.Second).Unix() > m.lastGCCollected.Unix() { + + for key, bucket := range m.store { + // if the bucket is drained, then GC + if bucket.DrainedAt().Unix() > now.Unix() { + delete(m.store, key) + } + } + + m.lastGCCollected = now + } +} diff --git a/vendor/github.com/ActiveState/tail/ratelimiter/storage.go b/vendor/github.com/ActiveState/tail/ratelimiter/storage.go new file mode 100644 index 000000000..89b2fe882 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/ratelimiter/storage.go @@ -0,0 +1,6 @@ +package ratelimiter + +type Storage interface { + GetBucketFor(string) (*LeakyBucket, error) + SetBucketFor(string, LeakyBucket) error +} diff --git a/vendor/github.com/ActiveState/tail/tail.go b/vendor/github.com/ActiveState/tail/tail.go new file mode 100644 index 000000000..1bae11c32 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/tail.go @@ -0,0 +1,419 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package tail + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "strings" + "sync" + "time" + + "github.com/hpcloud/tail/ratelimiter" + "github.com/hpcloud/tail/util" + "github.com/hpcloud/tail/watch" + "gopkg.in/tomb.v1" +) + +var ( + ErrStop = fmt.Errorf("tail should now stop") +) + +type Line struct { + Text string + Time time.Time + Err error // Error from tail +} + +// NewLine returns a Line with present time. +func NewLine(text string) *Line { + return &Line{text, time.Now(), nil} +} + +// SeekInfo represents arguments to `os.Seek` +type SeekInfo struct { + Offset int64 + Whence int // os.SEEK_* +} + +type logger interface { + Fatal(v ...interface{}) + Fatalf(format string, v ...interface{}) + Fatalln(v ...interface{}) + Panic(v ...interface{}) + Panicf(format string, v ...interface{}) + Panicln(v ...interface{}) + Print(v ...interface{}) + Printf(format string, v ...interface{}) + Println(v ...interface{}) +} + +// Config is used to specify how a file must be tailed. +type Config struct { + // File-specifc + Location *SeekInfo // Seek to this location before tailing + ReOpen bool // Reopen recreated files (tail -F) + MustExist bool // Fail early if the file does not exist + Poll bool // Poll for file changes instead of using inotify + Pipe bool // Is a named pipe (mkfifo) + RateLimiter *ratelimiter.LeakyBucket + + // Generic IO + Follow bool // Continue looking for new lines (tail -f) + MaxLineSize int // If non-zero, split longer lines into multiple lines + + // Logger, when nil, is set to tail.DefaultLogger + // To disable logging: set field to tail.DiscardingLogger + Logger logger +} + +type Tail struct { + Filename string + Lines chan *Line + Config + + file *os.File + reader *bufio.Reader + + watcher watch.FileWatcher + changes *watch.FileChanges + + tomb.Tomb // provides: Done, Kill, Dying + + lk sync.Mutex +} + +var ( + // DefaultLogger is used when Config.Logger == nil + DefaultLogger = log.New(os.Stderr, "", log.LstdFlags) + // DiscardingLogger can be used to disable logging output + DiscardingLogger = log.New(ioutil.Discard, "", 0) +) + +// TailFile begins tailing the file. Output stream is made available +// via the `Tail.Lines` channel. To handle errors during tailing, +// invoke the `Wait` or `Err` method after finishing reading from the +// `Lines` channel. +func TailFile(filename string, config Config) (*Tail, error) { + if config.ReOpen && !config.Follow { + util.Fatal("cannot set ReOpen without Follow.") + } + + t := &Tail{ + Filename: filename, + Lines: make(chan *Line), + Config: config, + } + + // when Logger was not specified in config, use default logger + if t.Logger == nil { + t.Logger = log.New(os.Stderr, "", log.LstdFlags) + } + + if t.Poll { + t.watcher = watch.NewPollingFileWatcher(filename) + } else { + t.watcher = watch.NewInotifyFileWatcher(filename) + } + + if t.MustExist { + var err error + t.file, err = OpenFile(t.Filename) + if err != nil { + return nil, err + } + } + + go t.tailFileSync() + + return t, nil +} + +// Return the file's current position, like stdio's ftell(). +// But this value is not very accurate. +// it may readed one line in the chan(tail.Lines), +// so it may lost one line. +func (tail *Tail) Tell() (offset int64, err error) { + if tail.file == nil { + return + } + offset, err = tail.file.Seek(0, os.SEEK_CUR) + if err == nil { + tail.lk.Lock() + offset -= int64(tail.reader.Buffered()) + tail.lk.Unlock() + } + return +} + +// Stop stops the tailing activity. +func (tail *Tail) Stop() error { + tail.Kill(nil) + return tail.Wait() +} + +func (tail *Tail) close() { + close(tail.Lines) + tail.colseFile() +} + +func (tail *Tail) colseFile() { + if tail.file != nil { + tail.file.Close() + tail.file = nil + } +} + +func (tail *Tail) reopen() error { + tail.colseFile() + for { + var err error + tail.file, err = OpenFile(tail.Filename) + if err != nil { + if os.IsNotExist(err) { + tail.Logger.Printf("Waiting for %s to appear...", tail.Filename) + if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil { + if err == tomb.ErrDying { + return err + } + return fmt.Errorf("Failed to detect creation of %s: %s", tail.Filename, err) + } + continue + } + return fmt.Errorf("Unable to open file %s: %s", tail.Filename, err) + } + break + } + return nil +} + +func (tail *Tail) readLine() (string, error) { + tail.lk.Lock() + line, err := tail.reader.ReadString('\n') + tail.lk.Unlock() + if err != nil { + // Note ReadString "returns the data read before the error" in + // case of an error, including EOF, so we return it as is. The + // caller is expected to process it if err is EOF. + return line, err + } + + line = strings.TrimRight(line, "\n") + + return line, err +} + +func (tail *Tail) tailFileSync() { + defer tail.Done() + defer tail.close() + + if !tail.MustExist { + // deferred first open. + err := tail.reopen() + if err != nil { + if err != tomb.ErrDying { + tail.Kill(err) + } + return + } + } + + // Seek to requested location on first open of the file. + if tail.Location != nil { + _, err := tail.file.Seek(tail.Location.Offset, tail.Location.Whence) + tail.Logger.Printf("Seeked %s - %+v\n", tail.Filename, tail.Location) + if err != nil { + tail.Killf("Seek error on %s: %s", tail.Filename, err) + return + } + } + + tail.openReader() + + var offset int64 = 0 + var err error + // Read line by line. + for { + // do not seek in named pipes + if !tail.Pipe { + // grab the position in case we need to back up in the event of a half-line + offset, err = tail.Tell() + if err != nil { + tail.Kill(err) + return + } + } + + line, err := tail.readLine() + + // Process `line` even if err is EOF. + if err == nil { + cooloff := !tail.sendLine(line) + if cooloff { + // Wait a second before seeking till the end of + // file when rate limit is reached. + msg := fmt.Sprintf( + "Too much log activity; waiting a second " + + "before resuming tailing") + tail.Lines <- &Line{msg, time.Now(), fmt.Errorf(msg)} + select { + case <-time.After(time.Second): + case <-tail.Dying(): + return + } + err = tail.seekEnd() + if err != nil { + tail.Kill(err) + return + } + } + } else if err == io.EOF { + if !tail.Follow { + if line != "" { + tail.sendLine(line) + } + return + } + + if tail.Follow && line != "" { + // this has the potential to never return the last line if + // it's not followed by a newline; seems a fair trade here + err := tail.seekTo(SeekInfo{Offset: offset, Whence: 0}) + if err != nil { + tail.Kill(err) + return + } + } + + // When EOF is reached, wait for more data to become + // available. Wait strategy is based on the `tail.watcher` + // implementation (inotify or polling). + err := tail.waitForChanges() + if err != nil { + if err != ErrStop { + tail.Kill(err) + } + return + } + } else { + // non-EOF error + tail.Killf("Error reading %s: %s", tail.Filename, err) + return + } + + select { + case <-tail.Dying(): + return + default: + } + } +} + +// waitForChanges waits until the file has been appended, deleted, +// moved or truncated. When moved or deleted - the file will be +// reopened if ReOpen is true. Truncated files are always reopened. +func (tail *Tail) waitForChanges() error { + if tail.changes == nil { + pos, err := tail.file.Seek(0, os.SEEK_CUR) + if err != nil { + return err + } + tail.changes, err = tail.watcher.ChangeEvents(&tail.Tomb, pos) + if err != nil { + return err + } + } + + select { + case <-tail.changes.Modified: + return nil + case <-tail.changes.Deleted: + tail.changes = nil + if tail.ReOpen { + // XXX: we must not log from a library. + tail.Logger.Printf("Re-opening moved/deleted file %s ...", tail.Filename) + if err := tail.reopen(); err != nil { + return err + } + tail.Logger.Printf("Successfully reopened %s", tail.Filename) + tail.openReader() + return nil + } else { + tail.Logger.Printf("Stopping tail as file no longer exists: %s", tail.Filename) + return ErrStop + } + case <-tail.changes.Truncated: + // Always reopen truncated files (Follow is true) + tail.Logger.Printf("Re-opening truncated file %s ...", tail.Filename) + if err := tail.reopen(); err != nil { + return err + } + tail.Logger.Printf("Successfully reopened truncated %s", tail.Filename) + tail.openReader() + return nil + case <-tail.Dying(): + return ErrStop + } + panic("unreachable") +} + +func (tail *Tail) openReader() { + if tail.MaxLineSize > 0 { + // add 2 to account for newline characters + tail.reader = bufio.NewReaderSize(tail.file, tail.MaxLineSize+2) + } else { + tail.reader = bufio.NewReader(tail.file) + } +} + +func (tail *Tail) seekEnd() error { + return tail.seekTo(SeekInfo{Offset: 0, Whence: os.SEEK_END}) +} + +func (tail *Tail) seekTo(pos SeekInfo) error { + _, err := tail.file.Seek(pos.Offset, pos.Whence) + if err != nil { + return fmt.Errorf("Seek error on %s: %s", tail.Filename, err) + } + // Reset the read buffer whenever the file is re-seek'ed + tail.reader.Reset(tail.file) + return nil +} + +// sendLine sends the line(s) to Lines channel, splitting longer lines +// if necessary. Return false if rate limit is reached. +func (tail *Tail) sendLine(line string) bool { + now := time.Now() + lines := []string{line} + + // Split longer lines + if tail.MaxLineSize > 0 && len(line) > tail.MaxLineSize { + lines = util.PartitionString(line, tail.MaxLineSize) + } + + for _, line := range lines { + tail.Lines <- &Line{line, now, nil} + } + + if tail.Config.RateLimiter != nil { + ok := tail.Config.RateLimiter.Pour(uint16(len(lines))) + if !ok { + tail.Logger.Printf("Leaky bucket full (%v); entering 1s cooloff period.\n", + tail.Filename) + return false + } + } + + return true +} + +// Cleanup removes inotify watches added by the tail package. This function is +// meant to be invoked from a process's exit handler. Linux kernel may not +// automatically remove inotify watches after the process exits. +func (tail *Tail) Cleanup() { + watch.Cleanup(tail.Filename) +} diff --git a/vendor/github.com/ActiveState/tail/tail_posix.go b/vendor/github.com/ActiveState/tail/tail_posix.go new file mode 100644 index 000000000..bc4dc3357 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/tail_posix.go @@ -0,0 +1,11 @@ +// +build linux darwin freebsd netbsd openbsd + +package tail + +import ( + "os" +) + +func OpenFile(name string) (file *os.File, err error) { + return os.Open(name) +} diff --git a/vendor/github.com/ActiveState/tail/tail_windows.go b/vendor/github.com/ActiveState/tail/tail_windows.go new file mode 100644 index 000000000..ef2cfca1b --- /dev/null +++ b/vendor/github.com/ActiveState/tail/tail_windows.go @@ -0,0 +1,12 @@ +// +build windows + +package tail + +import ( + "github.com/hpcloud/tail/winfile" + "os" +) + +func OpenFile(name string) (file *os.File, err error) { + return winfile.OpenFile(name, os.O_RDONLY, 0) +} diff --git a/vendor/github.com/ActiveState/tail/util/util.go b/vendor/github.com/ActiveState/tail/util/util.go new file mode 100644 index 000000000..f58b3ee9d --- /dev/null +++ b/vendor/github.com/ActiveState/tail/util/util.go @@ -0,0 +1,47 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package util + +import ( + "fmt" + "log" + "os" + "runtime/debug" +) + +type Logger struct { + *log.Logger +} + +var LOGGER = &Logger{log.New(os.Stderr, "", log.LstdFlags)} + +// fatal is like panic except it displays only the current goroutine's stack. +func Fatal(format string, v ...interface{}) { + // https://github.com/ActiveState/log/blob/master/log.go#L45 + LOGGER.Output(2, fmt.Sprintf("FATAL -- "+format, v...)+"\n"+string(debug.Stack())) + os.Exit(1) +} + +// partitionString partitions the string into chunks of given size, +// with the last chunk of variable size. +func PartitionString(s string, chunkSize int) []string { + if chunkSize <= 0 { + panic("invalid chunkSize") + } + length := len(s) + chunks := 1 + length/chunkSize + start := 0 + end := chunkSize + parts := make([]string, 0, chunks) + for { + if end > length { + end = length + } + parts = append(parts, s[start:end]) + if end == length { + break + } + start, end = end, end+chunkSize + } + return parts +} diff --git a/vendor/github.com/ActiveState/tail/watch/filechanges.go b/vendor/github.com/ActiveState/tail/watch/filechanges.go new file mode 100644 index 000000000..fb0f9ef53 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/watch/filechanges.go @@ -0,0 +1,42 @@ +package watch + +type FileChanges struct { + Modified chan bool // Channel to get notified of modifications + Truncated chan bool // Channel to get notified of truncations + Deleted chan bool // Channel to get notified of deletions/renames +} + +func NewFileChanges() *FileChanges { + return &FileChanges{ + make(chan bool), make(chan bool), make(chan bool)} +} + +func (fc *FileChanges) NotifyModified() { + sendOnlyIfEmpty(fc.Modified) +} + +func (fc *FileChanges) NotifyTruncated() { + sendOnlyIfEmpty(fc.Truncated) +} + +func (fc *FileChanges) NotifyDeleted() { + sendOnlyIfEmpty(fc.Deleted) +} + +func (fc *FileChanges) Close() { + close(fc.Modified) + close(fc.Truncated) + close(fc.Deleted) +} + +// sendOnlyIfEmpty sends on a bool channel only if the channel has no +// backlog to be read by other goroutines. This concurrency pattern +// can be used to notify other goroutines if and only if they are +// looking for it (i.e., subsequent notifications can be compressed +// into one). +func sendOnlyIfEmpty(ch chan bool) { + select { + case ch <- true: + default: + } +} diff --git a/vendor/github.com/ActiveState/tail/watch/inotify.go b/vendor/github.com/ActiveState/tail/watch/inotify.go new file mode 100644 index 000000000..58efc10a3 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/watch/inotify.go @@ -0,0 +1,119 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/hpcloud/tail/util" + + "gopkg.in/fsnotify.v1" + "gopkg.in/tomb.v1" +) + +// InotifyFileWatcher uses inotify to monitor file changes. +type InotifyFileWatcher struct { + Filename string + Size int64 +} + +func NewInotifyFileWatcher(filename string) *InotifyFileWatcher { + fw := &InotifyFileWatcher{filepath.Clean(filename), 0} + return fw +} + +func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { + err := WatchCreate(fw.Filename) + if err != nil { + return err + } + defer RemoveWatchCreate(fw.Filename) + + // Do a real check now as the file might have been created before + // calling `WatchFlags` above. + if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) { + // file exists, or stat returned an error. + return err + } + + events := Events(fw.Filename) + + for { + select { + case evt, ok := <-events: + if !ok { + return fmt.Errorf("inotify watcher has been closed") + } else if filepath.Clean(evt.Name) == fw.Filename { + return nil + } + case <-t.Dying(): + return tomb.ErrDying + } + } + panic("unreachable") +} + +func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { + err := Watch(fw.Filename) + if err != nil { + return nil, err + } + + changes := NewFileChanges() + fw.Size = pos + + go func() { + defer RemoveWatch(fw.Filename) + defer changes.Close() + + events := Events(fw.Filename) + + for { + prevSize := fw.Size + + var evt fsnotify.Event + var ok bool + + select { + case evt, ok = <-events: + if !ok { + return + } + case <-t.Dying(): + return + } + + switch { + case evt.Op&fsnotify.Remove == fsnotify.Remove: + fallthrough + + case evt.Op&fsnotify.Rename == fsnotify.Rename: + changes.NotifyDeleted() + return + + case evt.Op&fsnotify.Write == fsnotify.Write: + fi, err := os.Stat(fw.Filename) + if err != nil { + if os.IsNotExist(err) { + changes.NotifyDeleted() + return + } + // XXX: report this error back to the user + util.Fatal("Failed to stat file %v: %v", fw.Filename, err) + } + fw.Size = fi.Size() + + if prevSize > 0 && prevSize > fw.Size { + changes.NotifyTruncated() + } else { + changes.NotifyModified() + } + prevSize = fw.Size + } + } + }() + + return changes, nil +} diff --git a/vendor/github.com/ActiveState/tail/watch/inotify_tracker.go b/vendor/github.com/ActiveState/tail/watch/inotify_tracker.go new file mode 100644 index 000000000..f53f2c30d --- /dev/null +++ b/vendor/github.com/ActiveState/tail/watch/inotify_tracker.go @@ -0,0 +1,254 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "log" + "os" + "path/filepath" + "sync" + "syscall" + + "github.com/hpcloud/tail/util" + + "gopkg.in/fsnotify.v1" +) + +type InotifyTracker struct { + mux sync.Mutex + watcher *fsnotify.Watcher + chans map[string]chan fsnotify.Event + done map[string]chan bool + watchNums map[string]int + watch chan *watchInfo + remove chan *watchInfo + error chan error +} + +type watchInfo struct { + op fsnotify.Op + fname string +} + +func (this *watchInfo) isCreate() bool { + return this.op == fsnotify.Create +} + +var ( + // globally shared InotifyTracker; ensures only one fsnotify.Watcher is used + shared *InotifyTracker + + // these are used to ensure the shared InotifyTracker is run exactly once + once = sync.Once{} + goRun = func() { + shared = &InotifyTracker{ + mux: sync.Mutex{}, + chans: make(map[string]chan fsnotify.Event), + done: make(map[string]chan bool), + watchNums: make(map[string]int), + watch: make(chan *watchInfo), + remove: make(chan *watchInfo), + error: make(chan error), + } + go shared.run() + } + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +// Watch signals the run goroutine to begin watching the input filename +func Watch(fname string) error { + return watch(&watchInfo{ + fname: fname, + }) +} + +// Watch create signals the run goroutine to begin watching the input filename +// if call the WatchCreate function, don't call the Cleanup, call the RemoveWatchCreate +func WatchCreate(fname string) error { + return watch(&watchInfo{ + op: fsnotify.Create, + fname: fname, + }) +} + +func watch(winfo *watchInfo) error { + // start running the shared InotifyTracker if not already running + once.Do(goRun) + + winfo.fname = filepath.Clean(winfo.fname) + shared.watch <- winfo + return <-shared.error +} + +// RemoveWatch signals the run goroutine to remove the watch for the input filename +func RemoveWatch(fname string) { + remove(&watchInfo{ + fname: fname, + }) +} + +// RemoveWatch create signals the run goroutine to remove the watch for the input filename +func RemoveWatchCreate(fname string) { + remove(&watchInfo{ + op: fsnotify.Create, + fname: fname, + }) +} + +func remove(winfo *watchInfo) { + // start running the shared InotifyTracker if not already running + once.Do(goRun) + + winfo.fname = filepath.Clean(winfo.fname) + shared.mux.Lock() + done := shared.done[winfo.fname] + if done != nil { + delete(shared.done, winfo.fname) + close(done) + } + shared.mux.Unlock() + + shared.remove <- winfo +} + +// Events returns a channel to which FileEvents corresponding to the input filename +// will be sent. This channel will be closed when removeWatch is called on this +// filename. +func Events(fname string) chan fsnotify.Event { + shared.mux.Lock() + defer shared.mux.Unlock() + + return shared.chans[fname] +} + +// Cleanup removes the watch for the input filename if necessary. +func Cleanup(fname string) { + RemoveWatch(fname) +} + +// watchFlags calls fsnotify.WatchFlags for the input filename and flags, creating +// a new Watcher if the previous Watcher was closed. +func (shared *InotifyTracker) addWatch(winfo *watchInfo) error { + shared.mux.Lock() + defer shared.mux.Unlock() + + if shared.chans[winfo.fname] == nil { + shared.chans[winfo.fname] = make(chan fsnotify.Event) + shared.done[winfo.fname] = make(chan bool) + } + + fname := winfo.fname + if winfo.isCreate() { + // Watch for new files to be created in the parent directory. + fname = filepath.Dir(fname) + } + + // already in inotify watch + if shared.watchNums[fname] > 0 { + shared.watchNums[fname]++ + if winfo.isCreate() { + shared.watchNums[winfo.fname]++ + } + return nil + } + + err := shared.watcher.Add(fname) + if err == nil { + shared.watchNums[fname]++ + if winfo.isCreate() { + shared.watchNums[winfo.fname]++ + } + } + return err +} + +// removeWatch calls fsnotify.RemoveWatch for the input filename and closes the +// corresponding events channel. +func (shared *InotifyTracker) removeWatch(winfo *watchInfo) { + shared.mux.Lock() + defer shared.mux.Unlock() + + ch := shared.chans[winfo.fname] + if ch == nil { + return + } + + fname := winfo.fname + if winfo.isCreate() { + // Watch for new files to be created in the parent directory. + fname = filepath.Dir(fname) + } + + shared.watchNums[fname]-- + if shared.watchNums[fname] == 0 { + delete(shared.watchNums, fname) + // TODO: handle error + shared.watcher.Remove(fname) + } + + delete(shared.chans, winfo.fname) + close(ch) + + if !winfo.isCreate() { + return + } + + shared.watchNums[winfo.fname]-- + if shared.watchNums[winfo.fname] == 0 { + delete(shared.watchNums, winfo.fname) + } +} + +// sendEvent sends the input event to the appropriate Tail. +func (shared *InotifyTracker) sendEvent(event fsnotify.Event) { + name := filepath.Clean(event.Name) + + shared.mux.Lock() + ch := shared.chans[name] + done := shared.done[name] + shared.mux.Unlock() + + if ch != nil && done != nil { + select { + case ch <- event: + case <-done: + } + } +} + +// run starts the goroutine in which the shared struct reads events from its +// Watcher's Event channel and sends the events to the appropriate Tail. +func (shared *InotifyTracker) run() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + util.Fatal("failed to create Watcher") + } + shared.watcher = watcher + + for { + select { + case winfo := <-shared.watch: + shared.error <- shared.addWatch(winfo) + + case winfo := <-shared.remove: + shared.removeWatch(winfo) + + case event, open := <-shared.watcher.Events: + if !open { + return + } + shared.sendEvent(event) + + case err, open := <-shared.watcher.Errors: + if !open { + return + } else if err != nil { + sysErr, ok := err.(*os.SyscallError) + if !ok || sysErr.Err != syscall.EINTR { + logger.Printf("Error in Watcher Error channel: %s", err) + } + } + } + } +} diff --git a/vendor/github.com/ActiveState/tail/watch/polling.go b/vendor/github.com/ActiveState/tail/watch/polling.go new file mode 100644 index 000000000..33b8b4db1 --- /dev/null +++ b/vendor/github.com/ActiveState/tail/watch/polling.go @@ -0,0 +1,119 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "os" + "runtime" + "time" + + "github.com/hpcloud/tail/util" + "gopkg.in/tomb.v1" +) + +// PollingFileWatcher polls the file for changes. +type PollingFileWatcher struct { + Filename string + Size int64 +} + +func NewPollingFileWatcher(filename string) *PollingFileWatcher { + fw := &PollingFileWatcher{filename, 0} + return fw +} + +var POLL_DURATION time.Duration + +func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error { + for { + if _, err := os.Stat(fw.Filename); err == nil { + return nil + } else if !os.IsNotExist(err) { + return err + } + select { + case <-time.After(POLL_DURATION): + continue + case <-t.Dying(): + return tomb.ErrDying + } + } + panic("unreachable") +} + +func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { + origFi, err := os.Stat(fw.Filename) + if err != nil { + return nil, err + } + + changes := NewFileChanges() + var prevModTime time.Time + + // XXX: use tomb.Tomb to cleanly manage these goroutines. replace + // the fatal (below) with tomb's Kill. + + fw.Size = pos + + go func() { + defer changes.Close() + + prevSize := fw.Size + for { + select { + case <-t.Dying(): + return + default: + } + + time.Sleep(POLL_DURATION) + fi, err := os.Stat(fw.Filename) + if err != nil { + // Windows cannot delete a file if a handle is still open (tail keeps one open) + // so it gives access denied to anything trying to read it until all handles are released. + if os.IsNotExist(err) || (runtime.GOOS == "windows" && os.IsPermission(err)) { + // File does not exist (has been deleted). + changes.NotifyDeleted() + return + } + + // XXX: report this error back to the user + util.Fatal("Failed to stat file %v: %v", fw.Filename, err) + } + + // File got moved/renamed? + if !os.SameFile(origFi, fi) { + changes.NotifyDeleted() + return + } + + // File got truncated? + fw.Size = fi.Size() + if prevSize > 0 && prevSize > fw.Size { + changes.NotifyTruncated() + prevSize = fw.Size + continue + } + // File got bigger? + if prevSize > 0 && prevSize < fw.Size { + changes.NotifyModified() + prevSize = fw.Size + continue + } + prevSize = fw.Size + + // File was appended to (changed)? + modTime := fi.ModTime() + if modTime != prevModTime { + prevModTime = modTime + changes.NotifyModified() + } + } + }() + + return changes, nil +} + +func init() { + POLL_DURATION = 250 * time.Millisecond +} diff --git a/vendor/github.com/ActiveState/tail/watch/watch.go b/vendor/github.com/ActiveState/tail/watch/watch.go new file mode 100644 index 000000000..05baea10f --- /dev/null +++ b/vendor/github.com/ActiveState/tail/watch/watch.go @@ -0,0 +1,19 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import "gopkg.in/tomb.v1" + +// FileWatcher monitors file-level events. +type FileWatcher interface { + // BlockUntilExists blocks until the file comes into existence. + BlockUntilExists(*tomb.Tomb) error + + // ChangeEvents reports on changes to a file, be it modification, + // deletion, renames or truncations. Returned FileChanges group of + // channels will be closed, thus become unusable, after a deletion + // or truncation event. + // In order to properly report truncations, ChangeEvents requires + // the caller to pass their current offset in the file. + ChangeEvents(*tomb.Tomb, int64) (*FileChanges, error) +} diff --git a/vendor/github.com/ActiveState/tail/winfile/winfile.go b/vendor/github.com/ActiveState/tail/winfile/winfile.go new file mode 100644 index 000000000..aa7e7bc5d --- /dev/null +++ b/vendor/github.com/ActiveState/tail/winfile/winfile.go @@ -0,0 +1,92 @@ +// +build windows + +package winfile + +import ( + "os" + "syscall" + "unsafe" +) + +// issue also described here +//https://codereview.appspot.com/8203043/ + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L218 +func Open(path string, mode int, perm uint32) (fd syscall.Handle, err error) { + if len(path) == 0 { + return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return syscall.InvalidHandle, err + } + var access uint32 + switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) { + case syscall.O_RDONLY: + access = syscall.GENERIC_READ + case syscall.O_WRONLY: + access = syscall.GENERIC_WRITE + case syscall.O_RDWR: + access = syscall.GENERIC_READ | syscall.GENERIC_WRITE + } + if mode&syscall.O_CREAT != 0 { + access |= syscall.GENERIC_WRITE + } + if mode&syscall.O_APPEND != 0 { + access &^= syscall.GENERIC_WRITE + access |= syscall.FILE_APPEND_DATA + } + sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE) + var sa *syscall.SecurityAttributes + if mode&syscall.O_CLOEXEC == 0 { + sa = makeInheritSa() + } + var createmode uint32 + switch { + case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL): + createmode = syscall.CREATE_NEW + case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC): + createmode = syscall.CREATE_ALWAYS + case mode&syscall.O_CREAT == syscall.O_CREAT: + createmode = syscall.OPEN_ALWAYS + case mode&syscall.O_TRUNC == syscall.O_TRUNC: + createmode = syscall.TRUNCATE_EXISTING + default: + createmode = syscall.OPEN_EXISTING + } + h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0) + return h, e +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L211 +func makeInheritSa() *syscall.SecurityAttributes { + var sa syscall.SecurityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + sa.InheritHandle = 1 + return &sa +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_windows.go#L133 +func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { + r, e := Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) + if e != nil { + return nil, e + } + return os.NewFile(uintptr(r), name), nil +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_posix.go#L61 +func syscallMode(i os.FileMode) (o uint32) { + o |= uint32(i.Perm()) + if i&os.ModeSetuid != 0 { + o |= syscall.S_ISUID + } + if i&os.ModeSetgid != 0 { + o |= syscall.S_ISGID + } + if i&os.ModeSticky != 0 { + o |= syscall.S_ISVTX + } + // No mapping for Go's ModeTemporary (plan9 only). + return +} diff --git a/vendor/github.com/armon/go-radix/.gitignore b/vendor/github.com/armon/go-radix/.gitignore new file mode 100644 index 000000000..00268614f --- /dev/null +++ b/vendor/github.com/armon/go-radix/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/armon/go-radix/.travis.yml b/vendor/github.com/armon/go-radix/.travis.yml new file mode 100644 index 000000000..1a0bbea6c --- /dev/null +++ b/vendor/github.com/armon/go-radix/.travis.yml @@ -0,0 +1,3 @@ +language: go +go: + - tip diff --git a/vendor/github.com/armon/go-radix/LICENSE b/vendor/github.com/armon/go-radix/LICENSE new file mode 100644 index 000000000..a5df10e67 --- /dev/null +++ b/vendor/github.com/armon/go-radix/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Armon Dadgar + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/armon/go-radix/README.md b/vendor/github.com/armon/go-radix/README.md new file mode 100644 index 000000000..26f42a283 --- /dev/null +++ b/vendor/github.com/armon/go-radix/README.md @@ -0,0 +1,38 @@ +go-radix [![Build Status](https://travis-ci.org/armon/go-radix.png)](https://travis-ci.org/armon/go-radix) +========= + +Provides the `radix` package that implements a [radix tree](http://en.wikipedia.org/wiki/Radix_tree). +The package only provides a single `Tree` implementation, optimized for sparse nodes. + +As a radix tree, it provides the following: + * O(k) operations. In many cases, this can be faster than a hash table since + the hash function is an O(k) operation, and hash tables have very poor cache locality. + * Minimum / Maximum value lookups + * Ordered iteration + +For an immutable variant, see [go-immutable-radix](https://github.com/hashicorp/go-immutable-radix). + +Documentation +============= + +The full documentation is available on [Godoc](http://godoc.org/github.com/armon/go-radix). + +Example +======= + +Below is a simple example of usage + +```go +// Create a tree +r := radix.New() +r.Insert("foo", 1) +r.Insert("bar", 2) +r.Insert("foobar", 2) + +// Find the longest prefix match +m, _, _ := r.LongestPrefix("foozip") +if m != "foo" { + panic("should be foo") +} +``` + diff --git a/vendor/github.com/armon/go-radix/radix.go b/vendor/github.com/armon/go-radix/radix.go new file mode 100644 index 000000000..d2914c13b --- /dev/null +++ b/vendor/github.com/armon/go-radix/radix.go @@ -0,0 +1,496 @@ +package radix + +import ( + "sort" + "strings" +) + +// WalkFn is used when walking the tree. Takes a +// key and value, returning if iteration should +// be terminated. +type WalkFn func(s string, v interface{}) bool + +// leafNode is used to represent a value +type leafNode struct { + key string + val interface{} +} + +// edge is used to represent an edge node +type edge struct { + label byte + node *node +} + +type node struct { + // leaf is used to store possible leaf + leaf *leafNode + + // prefix is the common prefix we ignore + prefix string + + // Edges should be stored in-order for iteration. + // We avoid a fully materialized slice to save memory, + // since in most cases we expect to be sparse + edges edges +} + +func (n *node) isLeaf() bool { + return n.leaf != nil +} + +func (n *node) addEdge(e edge) { + n.edges = append(n.edges, e) + n.edges.Sort() +} + +func (n *node) replaceEdge(e edge) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= e.label + }) + if idx < num && n.edges[idx].label == e.label { + n.edges[idx].node = e.node + return + } + panic("replacing missing edge") +} + +func (n *node) getEdge(label byte) *node { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + return n.edges[idx].node + } + return nil +} + +func (n *node) delEdge(label byte) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + copy(n.edges[idx:], n.edges[idx+1:]) + n.edges[len(n.edges)-1] = edge{} + n.edges = n.edges[:len(n.edges)-1] + } +} + +type edges []edge + +func (e edges) Len() int { + return len(e) +} + +func (e edges) Less(i, j int) bool { + return e[i].label < e[j].label +} + +func (e edges) Swap(i, j int) { + e[i], e[j] = e[j], e[i] +} + +func (e edges) Sort() { + sort.Sort(e) +} + +// Tree implements a radix tree. This can be treated as a +// Dictionary abstract data type. The main advantage over +// a standard hash map is prefix-based lookups and +// ordered iteration, +type Tree struct { + root *node + size int +} + +// New returns an empty Tree +func New() *Tree { + return NewFromMap(nil) +} + +// NewFromMap returns a new tree containing the keys +// from an existing map +func NewFromMap(m map[string]interface{}) *Tree { + t := &Tree{root: &node{}} + for k, v := range m { + t.Insert(k, v) + } + return t +} + +// Len is used to return the number of elements in the tree +func (t *Tree) Len() int { + return t.size +} + +// longestPrefix finds the length of the shared prefix +// of two strings +func longestPrefix(k1, k2 string) int { + max := len(k1) + if l := len(k2); l < max { + max = l + } + var i int + for i = 0; i < max; i++ { + if k1[i] != k2[i] { + break + } + } + return i +} + +// Insert is used to add a newentry or update +// an existing entry. Returns if updated. +func (t *Tree) Insert(s string, v interface{}) (interface{}, bool) { + var parent *node + n := t.root + search := s + for { + // Handle key exhaution + if len(search) == 0 { + if n.isLeaf() { + old := n.leaf.val + n.leaf.val = v + return old, true + } + + n.leaf = &leafNode{ + key: s, + val: v, + } + t.size++ + return nil, false + } + + // Look for the edge + parent = n + n = n.getEdge(search[0]) + + // No edge, create one + if n == nil { + e := edge{ + label: search[0], + node: &node{ + leaf: &leafNode{ + key: s, + val: v, + }, + prefix: search, + }, + } + parent.addEdge(e) + t.size++ + return nil, false + } + + // Determine longest prefix of the search key on match + commonPrefix := longestPrefix(search, n.prefix) + if commonPrefix == len(n.prefix) { + search = search[commonPrefix:] + continue + } + + // Split the node + t.size++ + child := &node{ + prefix: search[:commonPrefix], + } + parent.replaceEdge(edge{ + label: search[0], + node: child, + }) + + // Restore the existing node + child.addEdge(edge{ + label: n.prefix[commonPrefix], + node: n, + }) + n.prefix = n.prefix[commonPrefix:] + + // Create a new leaf node + leaf := &leafNode{ + key: s, + val: v, + } + + // If the new key is a subset, add to to this node + search = search[commonPrefix:] + if len(search) == 0 { + child.leaf = leaf + return nil, false + } + + // Create a new edge for the node + child.addEdge(edge{ + label: search[0], + node: &node{ + leaf: leaf, + prefix: search, + }, + }) + return nil, false + } +} + +// Delete is used to delete a key, returning the previous +// value and if it was deleted +func (t *Tree) Delete(s string) (interface{}, bool) { + var parent *node + var label byte + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if !n.isLeaf() { + break + } + goto DELETE + } + + // Look for an edge + parent = n + label = search[0] + n = n.getEdge(label) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return nil, false + +DELETE: + // Delete the leaf + leaf := n.leaf + n.leaf = nil + t.size-- + + // Check if we should delete this node from the parent + if parent != nil && len(n.edges) == 0 { + parent.delEdge(label) + } + + // Check if we should merge this node + if n != t.root && len(n.edges) == 1 { + n.mergeChild() + } + + // Check if we should merge the parent's other child + if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() { + parent.mergeChild() + } + + return leaf.val, true +} + +func (n *node) mergeChild() { + e := n.edges[0] + child := e.node + n.prefix = n.prefix + child.prefix + n.leaf = child.leaf + n.edges = child.edges +} + +// Get is used to lookup a specific key, returning +// the value and if it was found +func (t *Tree) Get(s string) (interface{}, bool) { + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if n.isLeaf() { + return n.leaf.val, true + } + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return nil, false +} + +// LongestPrefix is like Get, but instead of an +// exact match, it will return the longest prefix match. +func (t *Tree) LongestPrefix(s string) (string, interface{}, bool) { + var last *leafNode + n := t.root + search := s + for { + // Look for a leaf node + if n.isLeaf() { + last = n.leaf + } + + // Check for key exhaution + if len(search) == 0 { + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + if last != nil { + return last.key, last.val, true + } + return "", nil, false +} + +// Minimum is used to return the minimum value in the tree +func (t *Tree) Minimum() (string, interface{}, bool) { + n := t.root + for { + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + if len(n.edges) > 0 { + n = n.edges[0].node + } else { + break + } + } + return "", nil, false +} + +// Maximum is used to return the maximum value in the tree +func (t *Tree) Maximum() (string, interface{}, bool) { + n := t.root + for { + if num := len(n.edges); num > 0 { + n = n.edges[num-1].node + continue + } + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + break + } + return "", nil, false +} + +// Walk is used to walk the tree +func (t *Tree) Walk(fn WalkFn) { + recursiveWalk(t.root, fn) +} + +// WalkPrefix is used to walk the tree under a prefix +func (t *Tree) WalkPrefix(prefix string, fn WalkFn) { + n := t.root + search := prefix + for { + // Check for key exhaution + if len(search) == 0 { + recursiveWalk(n, fn) + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + + } else if strings.HasPrefix(n.prefix, search) { + // Child may be under our search prefix + recursiveWalk(n, fn) + return + } else { + break + } + } + +} + +// WalkPath is used to walk the tree, but only visiting nodes +// from the root down to a given leaf. Where WalkPrefix walks +// all the entries *under* the given prefix, this walks the +// entries *above* the given prefix. +func (t *Tree) WalkPath(path string, fn WalkFn) { + n := t.root + search := path + for { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return + } + + // Check for key exhaution + if len(search) == 0 { + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + return + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } +} + +// recursiveWalk is used to do a pre-order walk of a node +// recursively. Returns true if the walk should be aborted +func recursiveWalk(n *node, fn WalkFn) bool { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return true + } + + // Recurse on the children + for _, e := range n.edges { + if recursiveWalk(e.node, fn) { + return true + } + } + return false +} + +// ToMap is used to walk the tree and convert it into a map +func (t *Tree) ToMap() map[string]interface{} { + out := make(map[string]interface{}, t.size) + t.Walk(func(k string, v interface{}) bool { + out[k] = v + return false + }) + return out +} diff --git a/vendor/github.com/aws/aws-sdk-go/LICENSE.txt b/vendor/github.com/aws/aws-sdk-go/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/LICENSE.txt @@ -0,0 +1,202 @@ + + 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. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/aws/aws-sdk-go/NOTICE.txt b/vendor/github.com/aws/aws-sdk-go/NOTICE.txt new file mode 100644 index 000000000..5f14d1162 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/NOTICE.txt @@ -0,0 +1,3 @@ +AWS SDK for Go +Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2014-2015 Stripe, Inc. diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go b/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go new file mode 100644 index 000000000..1d2c0d8b9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go @@ -0,0 +1,127 @@ +// Package awserr represents API error interface accessors for the SDK. +package awserr + +// An Error wraps lower level errors with code, message and an original error. +// The underlying concrete error type may also satisfy other interfaces which +// can be to used to obtain more specific information about the error. +// +// Calling Error() or String() will always include the full information about +// an error based on its underlying type. +// +// Example: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if awsErr, ok := err.(awserr.Error); ok { +// // Get error details +// log.Println("Error:", awsErr.Code(), awsErr.Message()) +// +// // Prints out full error message, including original error if there was one. +// log.Println("Error:", awsErr.Error()) +// +// // Get original error +// if origErr := awsErr.OrigErr(); origErr != nil { +// // operate on original error. +// } +// } else { +// fmt.Println(err.Error()) +// } +// } +// +type Error interface { + // Satisfy the generic error interface. + error + + // Returns the short phrase depicting the classification of the error. + Code() string + + // Returns the error details message. + Message() string + + // Returns the original error if one was set. Nil is returned if not set. + OrigErr() error +} + +// BatchError is a batch of errors which also wraps lower level errors with code, message, +// and original errors. Calling Error() will only return the error that is at the end +// of the list. +type BatchError interface { + // Satisfy the generic error interface. + error + + // Returns the short phrase depicting the classification of the error. + Code() string + + // Returns the error details message. + Message() string + + // Returns the original error if one was set. Nil is returned if not set. + OrigErrs() []error +} + +// New returns an Error object described by the code, message, and origErr. +// +// If origErr satisfies the Error interface it will not be wrapped within a new +// Error object and will instead be returned. +func New(code, message string, origErr error) Error { + if e, ok := origErr.(Error); ok && e != nil { + return e + } + return newBaseError(code, message, origErr) +} + +// NewBatchError returns an baseError with an expectation of an array of errors +func NewBatchError(code, message string, errs []error) BatchError { + return newBaseErrors(code, message, errs) +} + +// A RequestFailure is an interface to extract request failure information from +// an Error such as the request ID of the failed request returned by a service. +// RequestFailures may not always have a requestID value if the request failed +// prior to reaching the service such as a connection error. +// +// Example: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if reqerr, ok := err.(RequestFailure); ok { +// log.Printf("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID()) +// } else { +// log.Printf("Error:", err.Error() +// } +// } +// +// Combined with awserr.Error: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if awsErr, ok := err.(awserr.Error); ok { +// // Generic AWS Error with Code, Message, and original error (if any) +// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) +// +// if reqErr, ok := err.(awserr.RequestFailure); ok { +// // A service error occurred +// fmt.Println(reqErr.StatusCode(), reqErr.RequestID()) +// } +// } else { +// fmt.Println(err.Error()) +// } +// } +// +type RequestFailure interface { + Error + + // The status code of the HTTP response. + StatusCode() int + + // The request ID returned by the service for a request failure. This will + // be empty if no request ID is available such as the request failed due + // to a connection error. + RequestID() string +} + +// NewRequestFailure returns a new request error wrapper for the given Error +// provided. +func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure { + return newRequestError(err, statusCode, reqID) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go b/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go new file mode 100644 index 000000000..605f73c5d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go @@ -0,0 +1,197 @@ +package awserr + +import "fmt" + +// SprintError returns a string of the formatted error code. +// +// Both extra and origErr are optional. If they are included their lines +// will be added, but if they are not included their lines will be ignored. +func SprintError(code, message, extra string, origErr error) string { + msg := fmt.Sprintf("%s: %s", code, message) + if extra != "" { + msg = fmt.Sprintf("%s\n\t%s", msg, extra) + } + if origErr != nil { + msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error()) + } + return msg +} + +// A baseError wraps the code and message which defines an error. It also +// can be used to wrap an original error object. +// +// Should be used as the root for errors satisfying the awserr.Error. Also +// for any error which does not fit into a specific error wrapper type. +type baseError struct { + // Classification of error + code string + + // Detailed information about error + message string + + // Optional original error this error is based off of. Allows building + // chained errors. + errs []error +} + +// newBaseError returns an error object for the code, message, and err. +// +// code is a short no whitespace phrase depicting the classification of +// the error that is being created. +// +// message is the free flow string containing detailed information about the error. +// +// origErr is the error object which will be nested under the new error to be returned. +func newBaseError(code, message string, origErr error) *baseError { + b := &baseError{ + code: code, + message: message, + } + + if origErr != nil { + b.errs = append(b.errs, origErr) + } + + return b +} + +// newBaseErrors returns an error object for the code, message, and errors. +// +// code is a short no whitespace phrase depicting the classification of +// the error that is being created. +// +// message is the free flow string containing detailed information about the error. +// +// origErrs is the error objects which will be nested under the new errors to be returned. +func newBaseErrors(code, message string, origErrs []error) *baseError { + b := &baseError{ + code: code, + message: message, + errs: origErrs, + } + + return b +} + +// Error returns the string representation of the error. +// +// See ErrorWithExtra for formatting. +// +// Satisfies the error interface. +func (b baseError) Error() string { + size := len(b.errs) + if size > 0 { + return SprintError(b.code, b.message, "", errorList(b.errs)) + } + + return SprintError(b.code, b.message, "", nil) +} + +// String returns the string representation of the error. +// Alias for Error to satisfy the stringer interface. +func (b baseError) String() string { + return b.Error() +} + +// Code returns the short phrase depicting the classification of the error. +func (b baseError) Code() string { + return b.code +} + +// Message returns the error details message. +func (b baseError) Message() string { + return b.message +} + +// OrigErr returns the original error if one was set. Nil is returned if no error +// was set. This only returns the first element in the list. If the full list is +// needed, use BatchError +func (b baseError) OrigErr() error { + if size := len(b.errs); size > 0 { + return b.errs[0] + } + + return nil +} + +// OrigErrs returns the original errors if one was set. An empty slice is returned if +// no error was set:w +func (b baseError) OrigErrs() []error { + return b.errs +} + +// So that the Error interface type can be included as an anonymous field +// in the requestError struct and not conflict with the error.Error() method. +type awsError Error + +// A requestError wraps a request or service error. +// +// Composed of baseError for code, message, and original error. +type requestError struct { + awsError + statusCode int + requestID string +} + +// newRequestError returns a wrapped error with additional information for request +// status code, and service requestID. +// +// Should be used to wrap all request which involve service requests. Even if +// the request failed without a service response, but had an HTTP status code +// that may be meaningful. +// +// Also wraps original errors via the baseError. +func newRequestError(err Error, statusCode int, requestID string) *requestError { + return &requestError{ + awsError: err, + statusCode: statusCode, + requestID: requestID, + } +} + +// Error returns the string representation of the error. +// Satisfies the error interface. +func (r requestError) Error() string { + extra := fmt.Sprintf("status code: %d, request id: %s", + r.statusCode, r.requestID) + return SprintError(r.Code(), r.Message(), extra, r.OrigErr()) +} + +// String returns the string representation of the error. +// Alias for Error to satisfy the stringer interface. +func (r requestError) String() string { + return r.Error() +} + +// StatusCode returns the wrapped status code for the error +func (r requestError) StatusCode() int { + return r.statusCode +} + +// RequestID returns the wrapped requestID +func (r requestError) RequestID() string { + return r.requestID +} + +// An error list that satisfies the golang interface +type errorList []error + +// Error returns the string representation of the error. +// +// Satisfies the error interface. +func (e errorList) Error() string { + msg := "" + // How do we want to handle the array size being zero + if size := len(e); size > 0 { + for i := 0; i < size; i++ { + msg += fmt.Sprintf("%s", e[i].Error()) + // We check the next index to see if it is within the slice. + // If it is, then we append a newline. We do this, because unit tests + // could be broken with the additional '\n' + if i+1 < size { + msg += "\n" + } + } + } + return msg +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go new file mode 100644 index 000000000..8429470b9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go @@ -0,0 +1,100 @@ +package awsutil + +import ( + "io" + "reflect" +) + +// Copy deeply copies a src structure to dst. Useful for copying request and +// response structures. +// +// Can copy between structs of different type, but will only copy fields which +// are assignable, and exist in both structs. Fields which are not assignable, +// or do not exist in both structs are ignored. +func Copy(dst, src interface{}) { + dstval := reflect.ValueOf(dst) + if !dstval.IsValid() { + panic("Copy dst cannot be nil") + } + + rcopy(dstval, reflect.ValueOf(src), true) +} + +// CopyOf returns a copy of src while also allocating the memory for dst. +// src must be a pointer type or this operation will fail. +func CopyOf(src interface{}) (dst interface{}) { + dsti := reflect.New(reflect.TypeOf(src).Elem()) + dst = dsti.Interface() + rcopy(dsti, reflect.ValueOf(src), true) + return +} + +// rcopy performs a recursive copy of values from the source to destination. +// +// root is used to skip certain aspects of the copy which are not valid +// for the root node of a object. +func rcopy(dst, src reflect.Value, root bool) { + if !src.IsValid() { + return + } + + switch src.Kind() { + case reflect.Ptr: + if _, ok := src.Interface().(io.Reader); ok { + if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() { + dst.Elem().Set(src) + } else if dst.CanSet() { + dst.Set(src) + } + } else { + e := src.Type().Elem() + if dst.CanSet() && !src.IsNil() { + dst.Set(reflect.New(e)) + } + if src.Elem().IsValid() { + // Keep the current root state since the depth hasn't changed + rcopy(dst.Elem(), src.Elem(), root) + } + } + case reflect.Struct: + t := dst.Type() + for i := 0; i < t.NumField(); i++ { + name := t.Field(i).Name + srcVal := src.FieldByName(name) + dstVal := dst.FieldByName(name) + if srcVal.IsValid() && dstVal.CanSet() { + rcopy(dstVal, srcVal, false) + } + } + case reflect.Slice: + if src.IsNil() { + break + } + + s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) + dst.Set(s) + for i := 0; i < src.Len(); i++ { + rcopy(dst.Index(i), src.Index(i), false) + } + case reflect.Map: + if src.IsNil() { + break + } + + s := reflect.MakeMap(src.Type()) + dst.Set(s) + for _, k := range src.MapKeys() { + v := src.MapIndex(k) + v2 := reflect.New(v.Type()).Elem() + rcopy(v2, v, false) + dst.SetMapIndex(k, v2) + } + default: + // Assign the value if possible. If its not assignable, the value would + // need to be converted and the impact of that may be unexpected, or is + // not compatible with the dst type. + if src.Type().AssignableTo(dst.Type()) { + dst.Set(src) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go new file mode 100644 index 000000000..59fa4a558 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go @@ -0,0 +1,27 @@ +package awsutil + +import ( + "reflect" +) + +// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual. +// In addition to this, this method will also dereference the input values if +// possible so the DeepEqual performed will not fail if one parameter is a +// pointer and the other is not. +// +// DeepEqual will not perform indirection of nested values of the input parameters. +func DeepEqual(a, b interface{}) bool { + ra := reflect.Indirect(reflect.ValueOf(a)) + rb := reflect.Indirect(reflect.ValueOf(b)) + + if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid { + // If the elements are both nil, and of the same type the are equal + // If they are of different types they are not equal + return reflect.TypeOf(a) == reflect.TypeOf(b) + } else if raValid != rbValid { + // Both values must be valid to be equal + return false + } + + return reflect.DeepEqual(ra.Interface(), rb.Interface()) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go new file mode 100644 index 000000000..4d2a01e8c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go @@ -0,0 +1,222 @@ +package awsutil + +import ( + "reflect" + "regexp" + "strconv" + "strings" + + "github.com/jmespath/go-jmespath" +) + +var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`) + +// rValuesAtPath returns a slice of values found in value v. The values +// in v are explored recursively so all nested values are collected. +func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value { + pathparts := strings.Split(path, "||") + if len(pathparts) > 1 { + for _, pathpart := range pathparts { + vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm) + if len(vals) > 0 { + return vals + } + } + return nil + } + + values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))} + components := strings.Split(path, ".") + for len(values) > 0 && len(components) > 0 { + var index *int64 + var indexStar bool + c := strings.TrimSpace(components[0]) + if c == "" { // no actual component, illegal syntax + return nil + } else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] { + // TODO normalize case for user + return nil // don't support unexported fields + } + + // parse this component + if m := indexRe.FindStringSubmatch(c); m != nil { + c = m[1] + if m[2] == "" { + index = nil + indexStar = true + } else { + i, _ := strconv.ParseInt(m[2], 10, 32) + index = &i + indexStar = false + } + } + + nextvals := []reflect.Value{} + for _, value := range values { + // pull component name out of struct member + if value.Kind() != reflect.Struct { + continue + } + + if c == "*" { // pull all members + for i := 0; i < value.NumField(); i++ { + if f := reflect.Indirect(value.Field(i)); f.IsValid() { + nextvals = append(nextvals, f) + } + } + continue + } + + value = value.FieldByNameFunc(func(name string) bool { + if c == name { + return true + } else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) { + return true + } + return false + }) + + if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 { + if !value.IsNil() { + value.Set(reflect.Zero(value.Type())) + } + return []reflect.Value{value} + } + + if createPath && value.Kind() == reflect.Ptr && value.IsNil() { + // TODO if the value is the terminus it should not be created + // if the value to be set to its position is nil. + value.Set(reflect.New(value.Type().Elem())) + value = value.Elem() + } else { + value = reflect.Indirect(value) + } + + if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { + if !createPath && value.IsNil() { + value = reflect.ValueOf(nil) + } + } + + if value.IsValid() { + nextvals = append(nextvals, value) + } + } + values = nextvals + + if indexStar || index != nil { + nextvals = []reflect.Value{} + for _, value := range values { + value := reflect.Indirect(value) + if value.Kind() != reflect.Slice { + continue + } + + if indexStar { // grab all indices + for i := 0; i < value.Len(); i++ { + idx := reflect.Indirect(value.Index(i)) + if idx.IsValid() { + nextvals = append(nextvals, idx) + } + } + continue + } + + // pull out index + i := int(*index) + if i >= value.Len() { // check out of bounds + if createPath { + // TODO resize slice + } else { + continue + } + } else if i < 0 { // support negative indexing + i = value.Len() + i + } + value = reflect.Indirect(value.Index(i)) + + if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { + if !createPath && value.IsNil() { + value = reflect.ValueOf(nil) + } + } + + if value.IsValid() { + nextvals = append(nextvals, value) + } + } + values = nextvals + } + + components = components[1:] + } + return values +} + +// ValuesAtPath returns a list of values at the case insensitive lexical +// path inside of a structure. +func ValuesAtPath(i interface{}, path string) ([]interface{}, error) { + result, err := jmespath.Search(path, i) + if err != nil { + return nil, err + } + + v := reflect.ValueOf(result) + if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) { + return nil, nil + } + if s, ok := result.([]interface{}); ok { + return s, err + } + if v.Kind() == reflect.Map && v.Len() == 0 { + return nil, nil + } + if v.Kind() == reflect.Slice { + out := make([]interface{}, v.Len()) + for i := 0; i < v.Len(); i++ { + out[i] = v.Index(i).Interface() + } + return out, nil + } + + return []interface{}{result}, nil +} + +// SetValueAtPath sets a value at the case insensitive lexical path inside +// of a structure. +func SetValueAtPath(i interface{}, path string, v interface{}) { + if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil { + for _, rval := range rvals { + if rval.Kind() == reflect.Ptr && rval.IsNil() { + continue + } + setValue(rval, v) + } + } +} + +func setValue(dstVal reflect.Value, src interface{}) { + if dstVal.Kind() == reflect.Ptr { + dstVal = reflect.Indirect(dstVal) + } + srcVal := reflect.ValueOf(src) + + if !srcVal.IsValid() { // src is literal nil + if dstVal.CanAddr() { + // Convert to pointer so that pointer's value can be nil'ed + // dstVal = dstVal.Addr() + } + dstVal.Set(reflect.Zero(dstVal.Type())) + + } else if srcVal.Kind() == reflect.Ptr { + if srcVal.IsNil() { + srcVal = reflect.Zero(dstVal.Type()) + } else { + srcVal = reflect.ValueOf(src).Elem() + } + dstVal.Set(srcVal) + } else { + dstVal.Set(srcVal) + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go new file mode 100644 index 000000000..0de3eaa0f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go @@ -0,0 +1,103 @@ +package awsutil + +import ( + "bytes" + "fmt" + "io" + "reflect" + "strings" +) + +// Prettify returns the string representation of a value. +func Prettify(i interface{}) string { + var buf bytes.Buffer + prettify(reflect.ValueOf(i), 0, &buf) + return buf.String() +} + +// prettify will recursively walk value v to build a textual +// representation of the value. +func prettify(v reflect.Value, indent int, buf *bytes.Buffer) { + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + strtype := v.Type().String() + if strtype == "time.Time" { + fmt.Fprintf(buf, "%s", v.Interface()) + break + } else if strings.HasPrefix(strtype, "io.") { + buf.WriteString("") + break + } + + buf.WriteString("{\n") + + names := []string{} + for i := 0; i < v.Type().NumField(); i++ { + name := v.Type().Field(i).Name + f := v.Field(i) + if name[0:1] == strings.ToLower(name[0:1]) { + continue // ignore unexported fields + } + if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() { + continue // ignore unset fields + } + names = append(names, name) + } + + for i, n := range names { + val := v.FieldByName(n) + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(n + ": ") + prettify(val, indent+2, buf) + + if i < len(names)-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + case reflect.Slice: + nl, id, id2 := "", "", "" + if v.Len() > 3 { + nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2) + } + buf.WriteString("[" + nl) + for i := 0; i < v.Len(); i++ { + buf.WriteString(id2) + prettify(v.Index(i), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString("," + nl) + } + } + + buf.WriteString(nl + id + "]") + case reflect.Map: + buf.WriteString("{\n") + + for i, k := range v.MapKeys() { + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(k.String() + ": ") + prettify(v.MapIndex(k), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + default: + format := "%v" + switch v.Interface().(type) { + case string: + format = "%q" + case io.ReadSeeker, io.Reader: + format = "buffer(%p)" + } + fmt.Fprintf(buf, format, v.Interface()) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go new file mode 100644 index 000000000..b6432f1a1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go @@ -0,0 +1,89 @@ +package awsutil + +import ( + "bytes" + "fmt" + "reflect" + "strings" +) + +// StringValue returns the string representation of a value. +func StringValue(i interface{}) string { + var buf bytes.Buffer + stringValue(reflect.ValueOf(i), 0, &buf) + return buf.String() +} + +func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) { + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + buf.WriteString("{\n") + + names := []string{} + for i := 0; i < v.Type().NumField(); i++ { + name := v.Type().Field(i).Name + f := v.Field(i) + if name[0:1] == strings.ToLower(name[0:1]) { + continue // ignore unexported fields + } + if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice) && f.IsNil() { + continue // ignore unset fields + } + names = append(names, name) + } + + for i, n := range names { + val := v.FieldByName(n) + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(n + ": ") + stringValue(val, indent+2, buf) + + if i < len(names)-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + case reflect.Slice: + nl, id, id2 := "", "", "" + if v.Len() > 3 { + nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2) + } + buf.WriteString("[" + nl) + for i := 0; i < v.Len(); i++ { + buf.WriteString(id2) + stringValue(v.Index(i), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString("," + nl) + } + } + + buf.WriteString(nl + id + "]") + case reflect.Map: + buf.WriteString("{\n") + + for i, k := range v.MapKeys() { + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(k.String() + ": ") + stringValue(v.MapIndex(k), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + default: + format := "%v" + switch v.Interface().(type) { + case string: + format = "%q" + } + fmt.Fprintf(buf, format, v.Interface()) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/client.go b/vendor/github.com/aws/aws-sdk-go/aws/client/client.go new file mode 100644 index 000000000..c8d0564d8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/client.go @@ -0,0 +1,120 @@ +package client + +import ( + "fmt" + "io/ioutil" + "net/http/httputil" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" +) + +// A Config provides configuration to a service client instance. +type Config struct { + Config *aws.Config + Handlers request.Handlers + Endpoint, SigningRegion string +} + +// ConfigProvider provides a generic way for a service client to receive +// the ClientConfig without circular dependencies. +type ConfigProvider interface { + ClientConfig(serviceName string, cfgs ...*aws.Config) Config +} + +// A Client implements the base client request and response handling +// used by all service clients. +type Client struct { + request.Retryer + metadata.ClientInfo + + Config aws.Config + Handlers request.Handlers +} + +// New will return a pointer to a new initialized service client. +func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client { + svc := &Client{ + Config: cfg, + ClientInfo: info, + Handlers: handlers, + } + + switch retryer, ok := cfg.Retryer.(request.Retryer); { + case ok: + svc.Retryer = retryer + case cfg.Retryer != nil && cfg.Logger != nil: + s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer) + cfg.Logger.Log(s) + fallthrough + default: + maxRetries := aws.IntValue(cfg.MaxRetries) + if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries { + maxRetries = 3 + } + svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries} + } + + svc.AddDebugHandlers() + + for _, option := range options { + option(svc) + } + + return svc +} + +// NewRequest returns a new Request pointer for the service API +// operation and parameters. +func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request { + return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data) +} + +// AddDebugHandlers injects debug logging handlers into the service to log request +// debug information. +func (c *Client) AddDebugHandlers() { + if !c.Config.LogLevel.AtLeast(aws.LogDebug) { + return + } + + c.Handlers.Send.PushFront(logRequest) + c.Handlers.Send.PushBack(logResponse) +} + +const logReqMsg = `DEBUG: Request %s/%s Details: +---[ REQUEST POST-SIGN ]----------------------------- +%s +-----------------------------------------------------` + +func logRequest(r *request.Request) { + logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) + dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody) + + if logBody { + // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's + // Body as a NoOpCloser and will not be reset after read by the HTTP + // client reader. + r.Body.Seek(r.BodyStart, 0) + r.HTTPRequest.Body = ioutil.NopCloser(r.Body) + } + + r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody))) +} + +const logRespMsg = `DEBUG: Response %s/%s Details: +---[ RESPONSE ]-------------------------------------- +%s +-----------------------------------------------------` + +func logResponse(r *request.Request) { + var msg = "no response data" + if r.HTTPResponse != nil { + logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) + dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody) + msg = string(dumpedBody) + } else if r.Error != nil { + msg = r.Error.Error() + } + r.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.ClientInfo.ServiceName, r.Operation.Name, msg)) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go new file mode 100644 index 000000000..24d39ce56 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go @@ -0,0 +1,45 @@ +package client + +import ( + "math" + "math/rand" + "time" + + "github.com/aws/aws-sdk-go/aws/request" +) + +// DefaultRetryer implements basic retry logic using exponential backoff for +// most services. If you want to implement custom retry logic, implement the +// request.Retryer interface or create a structure type that composes this +// struct and override the specific methods. For example, to override only +// the MaxRetries method: +// +// type retryer struct { +// service.DefaultRetryer +// } +// +// // This implementation always has 100 max retries +// func (d retryer) MaxRetries() uint { return 100 } +type DefaultRetryer struct { + NumMaxRetries int +} + +// MaxRetries returns the number of maximum returns the service will use to make +// an individual API request. +func (d DefaultRetryer) MaxRetries() int { + return d.NumMaxRetries +} + +// RetryRules returns the delay duration before retrying this request again +func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration { + delay := int(math.Pow(2, float64(r.RetryCount))) * (rand.Intn(30) + 30) + return time.Duration(delay) * time.Millisecond +} + +// ShouldRetry returns if the request should be retried. +func (d DefaultRetryer) ShouldRetry(r *request.Request) bool { + if r.HTTPResponse.StatusCode >= 500 { + return true + } + return r.IsErrorRetryable() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go b/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go new file mode 100644 index 000000000..4778056dd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go @@ -0,0 +1,12 @@ +package metadata + +// ClientInfo wraps immutable data from the client.Client structure. +type ClientInfo struct { + ServiceName string + APIVersion string + Endpoint string + SigningName string + SigningRegion string + JSONVersion string + TargetPrefix string +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/config.go b/vendor/github.com/aws/aws-sdk-go/aws/config.go new file mode 100644 index 000000000..9e83e9260 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/config.go @@ -0,0 +1,311 @@ +package aws + +import ( + "net/http" + "time" + + "github.com/aws/aws-sdk-go/aws/credentials" +) + +// UseServiceDefaultRetries instructs the config to use the service's own default +// number of retries. This will be the default action if Config.MaxRetries +// is nil also. +const UseServiceDefaultRetries = -1 + +// RequestRetryer is an alias for a type that implements the request.Retryer interface. +type RequestRetryer interface{} + +// A Config provides service configuration for service clients. By default, +// all clients will use the {defaults.DefaultConfig} structure. +type Config struct { + // Enables verbose error printing of all credential chain errors. + // Should be used when wanting to see all errors while attempting to retreive + // credentials. + CredentialsChainVerboseErrors *bool + + // The credentials object to use when signing requests. Defaults to + // a chain of credential providers to search for credentials in environment + // variables, shared credential file, and EC2 Instance Roles. + Credentials *credentials.Credentials + + // An optional endpoint URL (hostname only or fully qualified URI) + // that overrides the default generated endpoint for a client. Set this + // to `""` to use the default generated endpoint. + // + // @note You must still provide a `Region` value when specifying an + // endpoint for a client. + Endpoint *string + + // The region to send requests to. This parameter is required and must + // be configured globally or on a per-client basis unless otherwise + // noted. A full list of regions is found in the "Regions and Endpoints" + // document. + // + // @see http://docs.aws.amazon.com/general/latest/gr/rande.html + // AWS Regions and Endpoints + Region *string + + // Set this to `true` to disable SSL when sending requests. Defaults + // to `false`. + DisableSSL *bool + + // The HTTP client to use when sending requests. Defaults to + // `http.DefaultClient`. + HTTPClient *http.Client + + // An integer value representing the logging level. The default log level + // is zero (LogOff), which represents no logging. To enable logging set + // to a LogLevel Value. + LogLevel *LogLevelType + + // The logger writer interface to write logging messages to. Defaults to + // standard out. + Logger Logger + + // The maximum number of times that a request will be retried for failures. + // Defaults to -1, which defers the max retry setting to the service specific + // configuration. + MaxRetries *int + + // Retryer guides how HTTP requests should be retried in case of recoverable failures. + // + // When nil or the value does not implement the request.Retryer interface, + // the request.DefaultRetryer will be used. + // + // When both Retryer and MaxRetries are non-nil, the former is used and + // the latter ignored. + // + // To set the Retryer field in a type-safe manner and with chaining, use + // the request.WithRetryer helper function: + // + // cfg := request.WithRetryer(aws.NewConfig(), myRetryer) + // + Retryer RequestRetryer + + // Disables semantic parameter validation, which validates input for missing + // required fields and/or other semantic request input errors. + DisableParamValidation *bool + + // Disables the computation of request and response checksums, e.g., + // CRC32 checksums in Amazon DynamoDB. + DisableComputeChecksums *bool + + // Set this to `true` to force the request to use path-style addressing, + // i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client will + // use virtual hosted bucket addressing when possible + // (`http://BUCKET.s3.amazonaws.com/KEY`). + // + // @note This configuration option is specific to the Amazon S3 service. + // @see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html + // Amazon S3: Virtual Hosting of Buckets + S3ForcePathStyle *bool + + // Set this to `true` to disable the EC2Metadata client from overriding the + // default http.Client's Timeout. This is helpful if you do not want the EC2Metadata + // client to create a new http.Client. This options is only meaningful if you're not + // already using a custom HTTP client with the SDK. Enabled by default. + // + // Must be set and provided to the session.New() in order to disable the EC2Metadata + // overriding the timeout for default credentials chain. + // + // Example: + // sess := session.New(aws.NewConfig().WithEC2MetadataDiableTimeoutOverride(true)) + // svc := s3.New(sess) + // + EC2MetadataDisableTimeoutOverride *bool + + SleepDelay func(time.Duration) +} + +// NewConfig returns a new Config pointer that can be chained with builder methods to +// set multiple configuration values inline without using pointers. +// +// svc := s3.New(aws.NewConfig().WithRegion("us-west-2").WithMaxRetries(10)) +// +func NewConfig() *Config { + return &Config{} +} + +// WithCredentialsChainVerboseErrors sets a config verbose errors boolean and returning +// a Config pointer. +func (c *Config) WithCredentialsChainVerboseErrors(verboseErrs bool) *Config { + c.CredentialsChainVerboseErrors = &verboseErrs + return c +} + +// WithCredentials sets a config Credentials value returning a Config pointer +// for chaining. +func (c *Config) WithCredentials(creds *credentials.Credentials) *Config { + c.Credentials = creds + return c +} + +// WithEndpoint sets a config Endpoint value returning a Config pointer for +// chaining. +func (c *Config) WithEndpoint(endpoint string) *Config { + c.Endpoint = &endpoint + return c +} + +// WithRegion sets a config Region value returning a Config pointer for +// chaining. +func (c *Config) WithRegion(region string) *Config { + c.Region = ®ion + return c +} + +// WithDisableSSL sets a config DisableSSL value returning a Config pointer +// for chaining. +func (c *Config) WithDisableSSL(disable bool) *Config { + c.DisableSSL = &disable + return c +} + +// WithHTTPClient sets a config HTTPClient value returning a Config pointer +// for chaining. +func (c *Config) WithHTTPClient(client *http.Client) *Config { + c.HTTPClient = client + return c +} + +// WithMaxRetries sets a config MaxRetries value returning a Config pointer +// for chaining. +func (c *Config) WithMaxRetries(max int) *Config { + c.MaxRetries = &max + return c +} + +// WithDisableParamValidation sets a config DisableParamValidation value +// returning a Config pointer for chaining. +func (c *Config) WithDisableParamValidation(disable bool) *Config { + c.DisableParamValidation = &disable + return c +} + +// WithDisableComputeChecksums sets a config DisableComputeChecksums value +// returning a Config pointer for chaining. +func (c *Config) WithDisableComputeChecksums(disable bool) *Config { + c.DisableComputeChecksums = &disable + return c +} + +// WithLogLevel sets a config LogLevel value returning a Config pointer for +// chaining. +func (c *Config) WithLogLevel(level LogLevelType) *Config { + c.LogLevel = &level + return c +} + +// WithLogger sets a config Logger value returning a Config pointer for +// chaining. +func (c *Config) WithLogger(logger Logger) *Config { + c.Logger = logger + return c +} + +// WithS3ForcePathStyle sets a config S3ForcePathStyle value returning a Config +// pointer for chaining. +func (c *Config) WithS3ForcePathStyle(force bool) *Config { + c.S3ForcePathStyle = &force + return c +} + +// WithEC2MetadataDisableTimeoutOverride sets a config EC2MetadataDisableTimeoutOverride value +// returning a Config pointer for chaining. +func (c *Config) WithEC2MetadataDisableTimeoutOverride(enable bool) *Config { + c.EC2MetadataDisableTimeoutOverride = &enable + return c +} + +// WithSleepDelay overrides the function used to sleep while waiting for the +// next retry. Defaults to time.Sleep. +func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config { + c.SleepDelay = fn + return c +} + +// MergeIn merges the passed in configs into the existing config object. +func (c *Config) MergeIn(cfgs ...*Config) { + for _, other := range cfgs { + mergeInConfig(c, other) + } +} + +func mergeInConfig(dst *Config, other *Config) { + if other == nil { + return + } + + if other.CredentialsChainVerboseErrors != nil { + dst.CredentialsChainVerboseErrors = other.CredentialsChainVerboseErrors + } + + if other.Credentials != nil { + dst.Credentials = other.Credentials + } + + if other.Endpoint != nil { + dst.Endpoint = other.Endpoint + } + + if other.Region != nil { + dst.Region = other.Region + } + + if other.DisableSSL != nil { + dst.DisableSSL = other.DisableSSL + } + + if other.HTTPClient != nil { + dst.HTTPClient = other.HTTPClient + } + + if other.LogLevel != nil { + dst.LogLevel = other.LogLevel + } + + if other.Logger != nil { + dst.Logger = other.Logger + } + + if other.MaxRetries != nil { + dst.MaxRetries = other.MaxRetries + } + + if other.Retryer != nil { + dst.Retryer = other.Retryer + } + + if other.DisableParamValidation != nil { + dst.DisableParamValidation = other.DisableParamValidation + } + + if other.DisableComputeChecksums != nil { + dst.DisableComputeChecksums = other.DisableComputeChecksums + } + + if other.S3ForcePathStyle != nil { + dst.S3ForcePathStyle = other.S3ForcePathStyle + } + + if other.EC2MetadataDisableTimeoutOverride != nil { + dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride + } + + if other.SleepDelay != nil { + dst.SleepDelay = other.SleepDelay + } +} + +// Copy will return a shallow copy of the Config object. If any additional +// configurations are provided they will be merged into the new config returned. +func (c *Config) Copy(cfgs ...*Config) *Config { + dst := &Config{} + dst.MergeIn(c) + + for _, cfg := range cfgs { + dst.MergeIn(cfg) + } + + return dst +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go new file mode 100644 index 000000000..d6a7b08df --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go @@ -0,0 +1,357 @@ +package aws + +import "time" + +// String returns a pointer to of the string value passed in. +func String(v string) *string { + return &v +} + +// StringValue returns the value of the string pointer passed in or +// "" if the pointer is nil. +func StringValue(v *string) string { + if v != nil { + return *v + } + return "" +} + +// StringSlice converts a slice of string values into a slice of +// string pointers +func StringSlice(src []string) []*string { + dst := make([]*string, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// StringValueSlice converts a slice of string pointers into a slice of +// string values +func StringValueSlice(src []*string) []string { + dst := make([]string, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// StringMap converts a string map of string values into a string +// map of string pointers +func StringMap(src map[string]string) map[string]*string { + dst := make(map[string]*string) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// StringValueMap converts a string map of string pointers into a string +// map of string values +func StringValueMap(src map[string]*string) map[string]string { + dst := make(map[string]string) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Bool returns a pointer to of the bool value passed in. +func Bool(v bool) *bool { + return &v +} + +// BoolValue returns the value of the bool pointer passed in or +// false if the pointer is nil. +func BoolValue(v *bool) bool { + if v != nil { + return *v + } + return false +} + +// BoolSlice converts a slice of bool values into a slice of +// bool pointers +func BoolSlice(src []bool) []*bool { + dst := make([]*bool, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// BoolValueSlice converts a slice of bool pointers into a slice of +// bool values +func BoolValueSlice(src []*bool) []bool { + dst := make([]bool, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// BoolMap converts a string map of bool values into a string +// map of bool pointers +func BoolMap(src map[string]bool) map[string]*bool { + dst := make(map[string]*bool) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// BoolValueMap converts a string map of bool pointers into a string +// map of bool values +func BoolValueMap(src map[string]*bool) map[string]bool { + dst := make(map[string]bool) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int returns a pointer to of the int value passed in. +func Int(v int) *int { + return &v +} + +// IntValue returns the value of the int pointer passed in or +// 0 if the pointer is nil. +func IntValue(v *int) int { + if v != nil { + return *v + } + return 0 +} + +// IntSlice converts a slice of int values into a slice of +// int pointers +func IntSlice(src []int) []*int { + dst := make([]*int, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// IntValueSlice converts a slice of int pointers into a slice of +// int values +func IntValueSlice(src []*int) []int { + dst := make([]int, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// IntMap converts a string map of int values into a string +// map of int pointers +func IntMap(src map[string]int) map[string]*int { + dst := make(map[string]*int) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// IntValueMap converts a string map of int pointers into a string +// map of int values +func IntValueMap(src map[string]*int) map[string]int { + dst := make(map[string]int) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int64 returns a pointer to of the int64 value passed in. +func Int64(v int64) *int64 { + return &v +} + +// Int64Value returns the value of the int64 pointer passed in or +// 0 if the pointer is nil. +func Int64Value(v *int64) int64 { + if v != nil { + return *v + } + return 0 +} + +// Int64Slice converts a slice of int64 values into a slice of +// int64 pointers +func Int64Slice(src []int64) []*int64 { + dst := make([]*int64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int64ValueSlice converts a slice of int64 pointers into a slice of +// int64 values +func Int64ValueSlice(src []*int64) []int64 { + dst := make([]int64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int64Map converts a string map of int64 values into a string +// map of int64 pointers +func Int64Map(src map[string]int64) map[string]*int64 { + dst := make(map[string]*int64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int64ValueMap converts a string map of int64 pointers into a string +// map of int64 values +func Int64ValueMap(src map[string]*int64) map[string]int64 { + dst := make(map[string]int64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Float64 returns a pointer to of the float64 value passed in. +func Float64(v float64) *float64 { + return &v +} + +// Float64Value returns the value of the float64 pointer passed in or +// 0 if the pointer is nil. +func Float64Value(v *float64) float64 { + if v != nil { + return *v + } + return 0 +} + +// Float64Slice converts a slice of float64 values into a slice of +// float64 pointers +func Float64Slice(src []float64) []*float64 { + dst := make([]*float64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Float64ValueSlice converts a slice of float64 pointers into a slice of +// float64 values +func Float64ValueSlice(src []*float64) []float64 { + dst := make([]float64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Float64Map converts a string map of float64 values into a string +// map of float64 pointers +func Float64Map(src map[string]float64) map[string]*float64 { + dst := make(map[string]*float64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Float64ValueMap converts a string map of float64 pointers into a string +// map of float64 values +func Float64ValueMap(src map[string]*float64) map[string]float64 { + dst := make(map[string]float64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Time returns a pointer to of the time.Time value passed in. +func Time(v time.Time) *time.Time { + return &v +} + +// TimeValue returns the value of the time.Time pointer passed in or +// time.Time{} if the pointer is nil. +func TimeValue(v *time.Time) time.Time { + if v != nil { + return *v + } + return time.Time{} +} + +// TimeSlice converts a slice of time.Time values into a slice of +// time.Time pointers +func TimeSlice(src []time.Time) []*time.Time { + dst := make([]*time.Time, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// TimeValueSlice converts a slice of time.Time pointers into a slice of +// time.Time values +func TimeValueSlice(src []*time.Time) []time.Time { + dst := make([]time.Time, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// TimeMap converts a string map of time.Time values into a string +// map of time.Time pointers +func TimeMap(src map[string]time.Time) map[string]*time.Time { + dst := make(map[string]*time.Time) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// TimeValueMap converts a string map of time.Time pointers into a string +// map of time.Time values +func TimeValueMap(src map[string]*time.Time) map[string]time.Time { + dst := make(map[string]time.Time) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go new file mode 100644 index 000000000..1d3e656fd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go @@ -0,0 +1,139 @@ +package corehandlers + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "regexp" + "runtime" + "strconv" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +// Interface for matching types which also have a Len method. +type lener interface { + Len() int +} + +// BuildContentLengthHandler builds the content length of a request based on the body, +// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable +// to determine request body length and no "Content-Length" was specified it will panic. +var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) { + if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" { + length, _ := strconv.ParseInt(slength, 10, 64) + r.HTTPRequest.ContentLength = length + return + } + + var length int64 + switch body := r.Body.(type) { + case nil: + length = 0 + case lener: + length = int64(body.Len()) + case io.Seeker: + r.BodyStart, _ = body.Seek(0, 1) + end, _ := body.Seek(0, 2) + body.Seek(r.BodyStart, 0) // make sure to seek back to original location + length = end - r.BodyStart + default: + panic("Cannot get length of body, must provide `ContentLength`") + } + + r.HTTPRequest.ContentLength = length + r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length)) +}} + +// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent. +var SDKVersionUserAgentHandler = request.NamedHandler{ + Name: "core.SDKVersionUserAgentHandler", + Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion, + runtime.Version(), runtime.GOOS, runtime.GOARCH), +} + +var reStatusCode = regexp.MustCompile(`^(\d{3})`) + +// SendHandler is a request handler to send service request using HTTP client. +var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) { + var err error + r.HTTPResponse, err = r.Config.HTTPClient.Do(r.HTTPRequest) + if err != nil { + // Capture the case where url.Error is returned for error processing + // response. e.g. 301 without location header comes back as string + // error and r.HTTPResponse is nil. Other url redirect errors will + // comeback in a similar method. + if e, ok := err.(*url.Error); ok && e.Err != nil { + if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil { + code, _ := strconv.ParseInt(s[1], 10, 64) + r.HTTPResponse = &http.Response{ + StatusCode: int(code), + Status: http.StatusText(int(code)), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + return + } + } + if r.HTTPResponse == nil { + // Add a dummy request response object to ensure the HTTPResponse + // value is consistent. + r.HTTPResponse = &http.Response{ + StatusCode: int(0), + Status: http.StatusText(int(0)), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + } + // Catch all other request errors. + r.Error = awserr.New("RequestError", "send request failed", err) + r.Retryable = aws.Bool(true) // network errors are retryable + } +}} + +// ValidateResponseHandler is a request handler to validate service response. +var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) { + if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 { + // this may be replaced by an UnmarshalError handler + r.Error = awserr.New("UnknownError", "unknown error", nil) + } +}} + +// AfterRetryHandler performs final checks to determine if the request should +// be retried and how long to delay. +var AfterRetryHandler = request.NamedHandler{Name: "core.AfterRetryHandler", Fn: func(r *request.Request) { + // If one of the other handlers already set the retry state + // we don't want to override it based on the service's state + if r.Retryable == nil { + r.Retryable = aws.Bool(r.ShouldRetry(r)) + } + + if r.WillRetry() { + r.RetryDelay = r.RetryRules(r) + r.Config.SleepDelay(r.RetryDelay) + + // when the expired token exception occurs the credentials + // need to be expired locally so that the next request to + // get credentials will trigger a credentials refresh. + if r.IsErrorExpired() { + r.Config.Credentials.Expire() + } + + r.RetryCount++ + r.Error = nil + } +}} + +// ValidateEndpointHandler is a request handler to validate a request had the +// appropriate Region and Endpoint set. Will set r.Error if the endpoint or +// region is not valid. +var ValidateEndpointHandler = request.NamedHandler{Name: "core.ValidateEndpointHandler", Fn: func(r *request.Request) { + if r.ClientInfo.SigningRegion == "" && aws.StringValue(r.Config.Region) == "" { + r.Error = aws.ErrMissingRegion + } else if r.ClientInfo.Endpoint == "" { + r.Error = aws.ErrMissingEndpoint + } +}} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go new file mode 100644 index 000000000..3b53f5e02 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go @@ -0,0 +1,144 @@ +package corehandlers + +import ( + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +// ValidateParametersHandler is a request handler to validate the input parameters. +// Validating parameters only has meaning if done prior to the request being sent. +var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) { + if r.ParamsFilled() { + v := validator{errors: []string{}} + v.validateAny(reflect.ValueOf(r.Params), "") + + if count := len(v.errors); count > 0 { + format := "%d validation errors:\n- %s" + msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- ")) + r.Error = awserr.New("InvalidParameter", msg, nil) + } + } +}} + +// A validator validates values. Collects validations errors which occurs. +type validator struct { + errors []string +} + +// validateAny will validate any struct, slice or map type. All validations +// are also performed recursively for nested types. +func (v *validator) validateAny(value reflect.Value, path string) { + value = reflect.Indirect(value) + if !value.IsValid() { + return + } + + switch value.Kind() { + case reflect.Struct: + v.validateStruct(value, path) + case reflect.Slice: + for i := 0; i < value.Len(); i++ { + v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i)) + } + case reflect.Map: + for _, n := range value.MapKeys() { + v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String())) + } + } +} + +// validateStruct will validate the struct value's fields. If the structure has +// nested types those types will be validated also. +func (v *validator) validateStruct(value reflect.Value, path string) { + prefix := "." + if path == "" { + prefix = "" + } + + for i := 0; i < value.Type().NumField(); i++ { + f := value.Type().Field(i) + if strings.ToLower(f.Name[0:1]) == f.Name[0:1] { + continue + } + fvalue := value.FieldByName(f.Name) + + err := validateField(f, fvalue, validateFieldRequired, validateFieldMin) + if err != nil { + v.errors = append(v.errors, fmt.Sprintf("%s: %s", err.Error(), path+prefix+f.Name)) + continue + } + + v.validateAny(fvalue, path+prefix+f.Name) + } +} + +type validatorFunc func(f reflect.StructField, fvalue reflect.Value) error + +func validateField(f reflect.StructField, fvalue reflect.Value, funcs ...validatorFunc) error { + for _, fn := range funcs { + if err := fn(f, fvalue); err != nil { + return err + } + } + return nil +} + +// Validates that a field has a valid value provided for required fields. +func validateFieldRequired(f reflect.StructField, fvalue reflect.Value) error { + if f.Tag.Get("required") == "" { + return nil + } + + switch fvalue.Kind() { + case reflect.Ptr, reflect.Slice, reflect.Map: + if fvalue.IsNil() { + return fmt.Errorf("missing required parameter") + } + default: + if !fvalue.IsValid() { + return fmt.Errorf("missing required parameter") + } + } + return nil +} + +// Validates that if a value is provided for a field, that value must be at +// least a minimum length. +func validateFieldMin(f reflect.StructField, fvalue reflect.Value) error { + minStr := f.Tag.Get("min") + if minStr == "" { + return nil + } + min, _ := strconv.ParseInt(minStr, 10, 64) + + kind := fvalue.Kind() + if kind == reflect.Ptr { + if fvalue.IsNil() { + return nil + } + fvalue = fvalue.Elem() + } + + switch fvalue.Kind() { + case reflect.String: + if int64(fvalue.Len()) < min { + return fmt.Errorf("field too short, minimum length %d", min) + } + case reflect.Slice, reflect.Map: + if fvalue.IsNil() { + return nil + } + if int64(fvalue.Len()) < min { + return fmt.Errorf("field too short, minimum length %d", min) + } + + // TODO min can also apply to number minimum value. + + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go new file mode 100644 index 000000000..857311f64 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go @@ -0,0 +1,100 @@ +package credentials + +import ( + "github.com/aws/aws-sdk-go/aws/awserr" +) + +var ( + // ErrNoValidProvidersFoundInChain Is returned when there are no valid + // providers in the ChainProvider. + // + // This has been deprecated. For verbose error messaging set + // aws.Config.CredentialsChainVerboseErrors to true + // + // @readonly + ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders", + `no valid providers in chain. Deprecated. + For verbose messaging see aws.Config.CredentialsChainVerboseErrors`, + nil) +) + +// A ChainProvider will search for a provider which returns credentials +// and cache that provider until Retrieve is called again. +// +// The ChainProvider provides a way of chaining multiple providers together +// which will pick the first available using priority order of the Providers +// in the list. +// +// If none of the Providers retrieve valid credentials Value, ChainProvider's +// Retrieve() will return the error ErrNoValidProvidersFoundInChain. +// +// If a Provider is found which returns valid credentials Value ChainProvider +// will cache that Provider for all calls to IsExpired(), until Retrieve is +// called again. +// +// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider. +// In this example EnvProvider will first check if any credentials are available +// vai the environment variables. If there are none ChainProvider will check +// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider +// does not return any credentials ChainProvider will return the error +// ErrNoValidProvidersFoundInChain +// +// creds := NewChainCredentials( +// []Provider{ +// &EnvProvider{}, +// &EC2RoleProvider{ +// Client: ec2metadata.New(sess), +// }, +// }) +// +// // Usage of ChainCredentials with aws.Config +// svc := ec2.New(&aws.Config{Credentials: creds}) +// +type ChainProvider struct { + Providers []Provider + curr Provider + VerboseErrors bool +} + +// NewChainCredentials returns a pointer to a new Credentials object +// wrapping a chain of providers. +func NewChainCredentials(providers []Provider) *Credentials { + return NewCredentials(&ChainProvider{ + Providers: append([]Provider{}, providers...), + }) +} + +// Retrieve returns the credentials value or error if no provider returned +// without error. +// +// If a provider is found it will be cached and any calls to IsExpired() +// will return the expired state of the cached provider. +func (c *ChainProvider) Retrieve() (Value, error) { + var errs []error + for _, p := range c.Providers { + creds, err := p.Retrieve() + if err == nil { + c.curr = p + return creds, nil + } + errs = append(errs, err) + } + c.curr = nil + + var err error + err = ErrNoValidProvidersFoundInChain + if c.VerboseErrors { + err = awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs) + } + return Value{}, err +} + +// IsExpired will returned the expired state of the currently cached provider +// if there is one. If there is no current provider, true will be returned. +func (c *ChainProvider) IsExpired() bool { + if c.curr != nil { + return c.curr.IsExpired() + } + + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go new file mode 100644 index 000000000..7b8ebf5f9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go @@ -0,0 +1,223 @@ +// Package credentials provides credential retrieval and management +// +// The Credentials is the primary method of getting access to and managing +// credentials Values. Using dependency injection retrieval of the credential +// values is handled by a object which satisfies the Provider interface. +// +// By default the Credentials.Get() will cache the successful result of a +// Provider's Retrieve() until Provider.IsExpired() returns true. At which +// point Credentials will call Provider's Retrieve() to get new credential Value. +// +// The Provider is responsible for determining when credentials Value have expired. +// It is also important to note that Credentials will always call Retrieve the +// first time Credentials.Get() is called. +// +// Example of using the environment variable credentials. +// +// creds := NewEnvCredentials() +// +// // Retrieve the credentials value +// credValue, err := creds.Get() +// if err != nil { +// // handle error +// } +// +// Example of forcing credentials to expire and be refreshed on the next Get(). +// This may be helpful to proactively expire credentials and refresh them sooner +// than they would naturally expire on their own. +// +// creds := NewCredentials(&EC2RoleProvider{}) +// creds.Expire() +// credsValue, err := creds.Get() +// // New credentials will be retrieved instead of from cache. +// +// +// Custom Provider +// +// Each Provider built into this package also provides a helper method to generate +// a Credentials pointer setup with the provider. To use a custom Provider just +// create a type which satisfies the Provider interface and pass it to the +// NewCredentials method. +// +// type MyProvider struct{} +// func (m *MyProvider) Retrieve() (Value, error) {...} +// func (m *MyProvider) IsExpired() bool {...} +// +// creds := NewCredentials(&MyProvider{}) +// credValue, err := creds.Get() +// +package credentials + +import ( + "sync" + "time" +) + +// AnonymousCredentials is an empty Credential object that can be used as +// dummy placeholder credentials for requests that do not need signed. +// +// This Credentials can be used to configure a service to not sign requests +// when making service API calls. For example, when accessing public +// s3 buckets. +// +// svc := s3.New(&aws.Config{Credentials: AnonymousCredentials}) +// // Access public S3 buckets. +// +// @readonly +var AnonymousCredentials = NewStaticCredentials("", "", "") + +// A Value is the AWS credentials value for individual credential fields. +type Value struct { + // AWS Access key ID + AccessKeyID string + + // AWS Secret Access Key + SecretAccessKey string + + // AWS Session Token + SessionToken string + + // Provider used to get credentials + ProviderName string +} + +// A Provider is the interface for any component which will provide credentials +// Value. A provider is required to manage its own Expired state, and what to +// be expired means. +// +// The Provider should not need to implement its own mutexes, because +// that will be managed by Credentials. +type Provider interface { + // Refresh returns nil if it successfully retrieved the value. + // Error is returned if the value were not obtainable, or empty. + Retrieve() (Value, error) + + // IsExpired returns if the credentials are no longer valid, and need + // to be retrieved. + IsExpired() bool +} + +// A Expiry provides shared expiration logic to be used by credentials +// providers to implement expiry functionality. +// +// The best method to use this struct is as an anonymous field within the +// provider's struct. +// +// Example: +// type EC2RoleProvider struct { +// Expiry +// ... +// } +type Expiry struct { + // The date/time when to expire on + expiration time.Time + + // If set will be used by IsExpired to determine the current time. + // Defaults to time.Now if CurrentTime is not set. Available for testing + // to be able to mock out the current time. + CurrentTime func() time.Time +} + +// SetExpiration sets the expiration IsExpired will check when called. +// +// If window is greater than 0 the expiration time will be reduced by the +// window value. +// +// Using a window is helpful to trigger credentials to expire sooner than +// the expiration time given to ensure no requests are made with expired +// tokens. +func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) { + e.expiration = expiration + if window > 0 { + e.expiration = e.expiration.Add(-window) + } +} + +// IsExpired returns if the credentials are expired. +func (e *Expiry) IsExpired() bool { + if e.CurrentTime == nil { + e.CurrentTime = time.Now + } + return e.expiration.Before(e.CurrentTime()) +} + +// A Credentials provides synchronous safe retrieval of AWS credentials Value. +// Credentials will cache the credentials value until they expire. Once the value +// expires the next Get will attempt to retrieve valid credentials. +// +// Credentials is safe to use across multiple goroutines and will manage the +// synchronous state so the Providers do not need to implement their own +// synchronization. +// +// The first Credentials.Get() will always call Provider.Retrieve() to get the +// first instance of the credentials Value. All calls to Get() after that +// will return the cached credentials Value until IsExpired() returns true. +type Credentials struct { + creds Value + forceRefresh bool + m sync.Mutex + + provider Provider +} + +// NewCredentials returns a pointer to a new Credentials with the provider set. +func NewCredentials(provider Provider) *Credentials { + return &Credentials{ + provider: provider, + forceRefresh: true, + } +} + +// Get returns the credentials value, or error if the credentials Value failed +// to be retrieved. +// +// Will return the cached credentials Value if it has not expired. If the +// credentials Value has expired the Provider's Retrieve() will be called +// to refresh the credentials. +// +// If Credentials.Expire() was called the credentials Value will be force +// expired, and the next call to Get() will cause them to be refreshed. +func (c *Credentials) Get() (Value, error) { + c.m.Lock() + defer c.m.Unlock() + + if c.isExpired() { + creds, err := c.provider.Retrieve() + if err != nil { + return Value{}, err + } + c.creds = creds + c.forceRefresh = false + } + + return c.creds, nil +} + +// Expire expires the credentials and forces them to be retrieved on the +// next call to Get(). +// +// This will override the Provider's expired state, and force Credentials +// to call the Provider's Retrieve(). +func (c *Credentials) Expire() { + c.m.Lock() + defer c.m.Unlock() + + c.forceRefresh = true +} + +// IsExpired returns if the credentials are no longer valid, and need +// to be retrieved. +// +// If the Credentials were forced to be expired with Expire() this will +// reflect that override. +func (c *Credentials) IsExpired() bool { + c.m.Lock() + defer c.m.Unlock() + + return c.isExpired() +} + +// isExpired helper method wrapping the definition of expired credentials. +func (c *Credentials) isExpired() bool { + return c.forceRefresh || c.provider.IsExpired() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go new file mode 100644 index 000000000..36f8add35 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go @@ -0,0 +1,178 @@ +package ec2rolecreds + +import ( + "bufio" + "encoding/json" + "fmt" + "path" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/ec2metadata" +) + +// ProviderName provides a name of EC2Role provider +const ProviderName = "EC2RoleProvider" + +// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if +// those credentials are expired. +// +// Example how to configure the EC2RoleProvider with custom http Client, Endpoint +// or ExpiryWindow +// +// p := &ec2rolecreds.EC2RoleProvider{ +// // Pass in a custom timeout to be used when requesting +// // IAM EC2 Role credentials. +// Client: ec2metadata.New(sess, aws.Config{ +// HTTPClient: &http.Client{Timeout: 10 * time.Second}, +// }), +// +// // Do not use early expiry of credentials. If a non zero value is +// // specified the credentials will be expired early +// ExpiryWindow: 0, +// } +type EC2RoleProvider struct { + credentials.Expiry + + // Required EC2Metadata client to use when connecting to EC2 metadata service. + Client *ec2metadata.EC2Metadata + + // ExpiryWindow will allow the credentials to trigger refreshing prior to + // the credentials actually expiring. This is beneficial so race conditions + // with expiring credentials do not cause request to fail unexpectedly + // due to ExpiredTokenException exceptions. + // + // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true + // 10 seconds before the credentials are actually expired. + // + // If ExpiryWindow is 0 or less it will be ignored. + ExpiryWindow time.Duration +} + +// NewCredentials returns a pointer to a new Credentials object wrapping +// the EC2RoleProvider. Takes a ConfigProvider to create a EC2Metadata client. +// The ConfigProvider is satisfied by the session.Session type. +func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials { + p := &EC2RoleProvider{ + Client: ec2metadata.New(c), + } + + for _, option := range options { + option(p) + } + + return credentials.NewCredentials(p) +} + +// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping +// the EC2RoleProvider. Takes a EC2Metadata client to use when connecting to EC2 +// metadata service. +func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*EC2RoleProvider)) *credentials.Credentials { + p := &EC2RoleProvider{ + Client: client, + } + + for _, option := range options { + option(p) + } + + return credentials.NewCredentials(p) +} + +// Retrieve retrieves credentials from the EC2 service. +// Error will be returned if the request fails, or unable to extract +// the desired credentials. +func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) { + credsList, err := requestCredList(m.Client) + if err != nil { + return credentials.Value{ProviderName: ProviderName}, err + } + + if len(credsList) == 0 { + return credentials.Value{ProviderName: ProviderName}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil) + } + credsName := credsList[0] + + roleCreds, err := requestCred(m.Client, credsName) + if err != nil { + return credentials.Value{ProviderName: ProviderName}, err + } + + m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow) + + return credentials.Value{ + AccessKeyID: roleCreds.AccessKeyID, + SecretAccessKey: roleCreds.SecretAccessKey, + SessionToken: roleCreds.Token, + ProviderName: ProviderName, + }, nil +} + +// A ec2RoleCredRespBody provides the shape for unmarshalling credential +// request responses. +type ec2RoleCredRespBody struct { + // Success State + Expiration time.Time + AccessKeyID string + SecretAccessKey string + Token string + + // Error state + Code string + Message string +} + +const iamSecurityCredsPath = "/iam/security-credentials" + +// requestCredList requests a list of credentials from the EC2 service. +// If there are no credentials, or there is an error making or receiving the request +func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) { + resp, err := client.GetMetadata(iamSecurityCredsPath) + if err != nil { + return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err) + } + + credsList := []string{} + s := bufio.NewScanner(strings.NewReader(resp)) + for s.Scan() { + credsList = append(credsList, s.Text()) + } + + if err := s.Err(); err != nil { + return nil, awserr.New("SerializationError", "failed to read list of EC2 Roles", err) + } + + return credsList, nil +} + +// requestCred requests the credentials for a specific credentials from the EC2 service. +// +// If the credentials cannot be found, or there is an error reading the response +// and error will be returned. +func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) { + resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName)) + if err != nil { + return ec2RoleCredRespBody{}, + awserr.New("EC2RoleRequestError", + fmt.Sprintf("failed to get %s EC2 Role credentials", credsName), + err) + } + + respCreds := ec2RoleCredRespBody{} + if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil { + return ec2RoleCredRespBody{}, + awserr.New("SerializationError", + fmt.Sprintf("failed to decode %s EC2 Role credentials", credsName), + err) + } + + if respCreds.Code != "Success" { + // If an error code was returned something failed requesting the role. + return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil) + } + + return respCreds, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go new file mode 100644 index 000000000..96655bc46 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go @@ -0,0 +1,77 @@ +package credentials + +import ( + "os" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// EnvProviderName provides a name of Env provider +const EnvProviderName = "EnvProvider" + +var ( + // ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be + // found in the process's environment. + // + // @readonly + ErrAccessKeyIDNotFound = awserr.New("EnvAccessKeyNotFound", "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment", nil) + + // ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key + // can't be found in the process's environment. + // + // @readonly + ErrSecretAccessKeyNotFound = awserr.New("EnvSecretNotFound", "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment", nil) +) + +// A EnvProvider retrieves credentials from the environment variables of the +// running process. Environment credentials never expire. +// +// Environment variables used: +// +// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY +// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY +type EnvProvider struct { + retrieved bool +} + +// NewEnvCredentials returns a pointer to a new Credentials object +// wrapping the environment variable provider. +func NewEnvCredentials() *Credentials { + return NewCredentials(&EnvProvider{}) +} + +// Retrieve retrieves the keys from the environment. +func (e *EnvProvider) Retrieve() (Value, error) { + e.retrieved = false + + id := os.Getenv("AWS_ACCESS_KEY_ID") + if id == "" { + id = os.Getenv("AWS_ACCESS_KEY") + } + + secret := os.Getenv("AWS_SECRET_ACCESS_KEY") + if secret == "" { + secret = os.Getenv("AWS_SECRET_KEY") + } + + if id == "" { + return Value{ProviderName: EnvProviderName}, ErrAccessKeyIDNotFound + } + + if secret == "" { + return Value{ProviderName: EnvProviderName}, ErrSecretAccessKeyNotFound + } + + e.retrieved = true + return Value{ + AccessKeyID: id, + SecretAccessKey: secret, + SessionToken: os.Getenv("AWS_SESSION_TOKEN"), + ProviderName: EnvProviderName, + }, nil +} + +// IsExpired returns if the credentials have been retrieved. +func (e *EnvProvider) IsExpired() bool { + return !e.retrieved +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini b/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini new file mode 100644 index 000000000..7fc91d9d2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini @@ -0,0 +1,12 @@ +[default] +aws_access_key_id = accessKey +aws_secret_access_key = secret +aws_session_token = token + +[no_token] +aws_access_key_id = accessKey +aws_secret_access_key = secret + +[with_colon] +aws_access_key_id: accessKey +aws_secret_access_key: secret diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go new file mode 100644 index 000000000..7fb7cbf0d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go @@ -0,0 +1,151 @@ +package credentials + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/go-ini/ini" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// SharedCredsProviderName provides a name of SharedCreds provider +const SharedCredsProviderName = "SharedCredentialsProvider" + +var ( + // ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found. + // + // @readonly + ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil) +) + +// A SharedCredentialsProvider retrieves credentials from the current user's home +// directory, and keeps track if those credentials are expired. +// +// Profile ini file example: $HOME/.aws/credentials +type SharedCredentialsProvider struct { + // Path to the shared credentials file. + // + // If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the + // env value is empty will default to current user's home directory. + // Linux/OSX: "$HOME/.aws/credentials" + // Windows: "%USERPROFILE%\.aws\credentials" + Filename string + + // AWS Profile to extract credentials from the shared credentials file. If empty + // will default to environment variable "AWS_PROFILE" or "default" if + // environment variable is also not set. + Profile string + + // retrieved states if the credentials have been successfully retrieved. + retrieved bool +} + +// NewSharedCredentials returns a pointer to a new Credentials object +// wrapping the Profile file provider. +func NewSharedCredentials(filename, profile string) *Credentials { + return NewCredentials(&SharedCredentialsProvider{ + Filename: filename, + Profile: profile, + }) +} + +// Retrieve reads and extracts the shared credentials from the current +// users home directory. +func (p *SharedCredentialsProvider) Retrieve() (Value, error) { + p.retrieved = false + + filename, err := p.filename() + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, err + } + + creds, err := loadProfile(filename, p.profile()) + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, err + } + + p.retrieved = true + return creds, nil +} + +// IsExpired returns if the shared credentials have expired. +func (p *SharedCredentialsProvider) IsExpired() bool { + return !p.retrieved +} + +// loadProfiles loads from the file pointed to by shared credentials filename for profile. +// The credentials retrieved from the profile will be returned or error. Error will be +// returned if it fails to read from the file, or the data is invalid. +func loadProfile(filename, profile string) (Value, error) { + config, err := ini.Load(filename) + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err) + } + iniProfile, err := config.GetSection(profile) + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to get profile", err) + } + + id, err := iniProfile.GetKey("aws_access_key_id") + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsAccessKey", + fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename), + err) + } + + secret, err := iniProfile.GetKey("aws_secret_access_key") + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsSecret", + fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename), + nil) + } + + // Default to empty string if not found + token := iniProfile.Key("aws_session_token") + + return Value{ + AccessKeyID: id.String(), + SecretAccessKey: secret.String(), + SessionToken: token.String(), + ProviderName: SharedCredsProviderName, + }, nil +} + +// filename returns the filename to use to read AWS shared credentials. +// +// Will return an error if the user's home directory path cannot be found. +func (p *SharedCredentialsProvider) filename() (string, error) { + if p.Filename == "" { + if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" { + return p.Filename, nil + } + + homeDir := os.Getenv("HOME") // *nix + if homeDir == "" { // Windows + homeDir = os.Getenv("USERPROFILE") + } + if homeDir == "" { + return "", ErrSharedCredentialsHomeNotFound + } + + p.Filename = filepath.Join(homeDir, ".aws", "credentials") + } + + return p.Filename, nil +} + +// profile returns the AWS shared credentials profile. If empty will read +// environment variable "AWS_PROFILE". If that is not set profile will +// return "default". +func (p *SharedCredentialsProvider) profile() string { + if p.Profile == "" { + p.Profile = os.Getenv("AWS_PROFILE") + } + if p.Profile == "" { + p.Profile = "default" + } + + return p.Profile +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go new file mode 100644 index 000000000..71189e733 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go @@ -0,0 +1,48 @@ +package credentials + +import ( + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// StaticProviderName provides a name of Static provider +const StaticProviderName = "StaticProvider" + +var ( + // ErrStaticCredentialsEmpty is emitted when static credentials are empty. + // + // @readonly + ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil) +) + +// A StaticProvider is a set of credentials which are set pragmatically, +// and will never expire. +type StaticProvider struct { + Value +} + +// NewStaticCredentials returns a pointer to a new Credentials object +// wrapping a static credentials value provider. +func NewStaticCredentials(id, secret, token string) *Credentials { + return NewCredentials(&StaticProvider{Value: Value{ + AccessKeyID: id, + SecretAccessKey: secret, + SessionToken: token, + }}) +} + +// Retrieve returns the credentials or error if the credentials are invalid. +func (s *StaticProvider) Retrieve() (Value, error) { + if s.AccessKeyID == "" || s.SecretAccessKey == "" { + return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty + } + + s.Value.ProviderName = StaticProviderName + return s.Value, nil +} + +// IsExpired returns if the credentials are expired. +// +// For StaticProvider, the credentials never expired. +func (s *StaticProvider) IsExpired() bool { + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go new file mode 100644 index 000000000..4d6408b9d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go @@ -0,0 +1,134 @@ +// Package stscreds are credential Providers to retrieve STS AWS credentials. +// +// STS provides multiple ways to retrieve credentials which can be used when making +// future AWS service API operation calls. +package stscreds + +import ( + "fmt" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/service/sts" +) + +// ProviderName provides a name of AssumeRole provider +const ProviderName = "AssumeRoleProvider" + +// AssumeRoler represents the minimal subset of the STS client API used by this provider. +type AssumeRoler interface { + AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) +} + +// DefaultDuration is the default amount of time in minutes that the credentials +// will be valid for. +var DefaultDuration = time.Duration(15) * time.Minute + +// AssumeRoleProvider retrieves temporary credentials from the STS service, and +// keeps track of their expiration time. This provider must be used explicitly, +// as it is not included in the credentials chain. +type AssumeRoleProvider struct { + credentials.Expiry + + // STS client to make assume role request with. + Client AssumeRoler + + // Role to be assumed. + RoleARN string + + // Session name, if you wish to reuse the credentials elsewhere. + RoleSessionName string + + // Expiry duration of the STS credentials. Defaults to 15 minutes if not set. + Duration time.Duration + + // Optional ExternalID to pass along, defaults to nil if not set. + ExternalID *string + + // ExpiryWindow will allow the credentials to trigger refreshing prior to + // the credentials actually expiring. This is beneficial so race conditions + // with expiring credentials do not cause request to fail unexpectedly + // due to ExpiredTokenException exceptions. + // + // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true + // 10 seconds before the credentials are actually expired. + // + // If ExpiryWindow is 0 or less it will be ignored. + ExpiryWindow time.Duration +} + +// NewCredentials returns a pointer to a new Credentials object wrapping the +// AssumeRoleProvider. The credentials will expire every 15 minutes and the +// role will be named after a nanosecond timestamp of this operation. +// +// Takes a Config provider to create the STS client. The ConfigProvider is +// satisfied by the session.Session type. +func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials { + p := &AssumeRoleProvider{ + Client: sts.New(c), + RoleARN: roleARN, + Duration: DefaultDuration, + } + + for _, option := range options { + option(p) + } + + return credentials.NewCredentials(p) +} + +// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the +// AssumeRoleProvider. The credentials will expire every 15 minutes and the +// role will be named after a nanosecond timestamp of this operation. +// +// Takes an AssumeRoler which can be satisfiede by the STS client. +func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials { + p := &AssumeRoleProvider{ + Client: svc, + RoleARN: roleARN, + Duration: DefaultDuration, + } + + for _, option := range options { + option(p) + } + + return credentials.NewCredentials(p) +} + +// Retrieve generates a new set of temporary credentials using STS. +func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) { + + // Apply defaults where parameters are not set. + if p.RoleSessionName == "" { + // Try to work out a role name that will hopefully end up unique. + p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano()) + } + if p.Duration == 0 { + // Expire as often as AWS permits. + p.Duration = DefaultDuration + } + + roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{ + DurationSeconds: aws.Int64(int64(p.Duration / time.Second)), + RoleArn: aws.String(p.RoleARN), + RoleSessionName: aws.String(p.RoleSessionName), + ExternalId: p.ExternalID, + }) + + if err != nil { + return credentials.Value{ProviderName: ProviderName}, err + } + + // We will proactively generate new credentials before they expire. + p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow) + + return credentials.Value{ + AccessKeyID: *roleOutput.Credentials.AccessKeyId, + SecretAccessKey: *roleOutput.Credentials.SecretAccessKey, + SessionToken: *roleOutput.Credentials.SessionToken, + ProviderName: ProviderName, + }, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go new file mode 100644 index 000000000..42c883aa9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go @@ -0,0 +1,96 @@ +// Package defaults is a collection of helpers to retrieve the SDK's default +// configuration and handlers. +// +// Generally this package shouldn't be used directly, but session.Session +// instead. This package is useful when you need to reset the defaults +// of a session or service client to the SDK defaults before setting +// additional parameters. +package defaults + +import ( + "net/http" + "os" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/corehandlers" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" + "github.com/aws/aws-sdk-go/aws/ec2metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/endpoints" +) + +// A Defaults provides a collection of default values for SDK clients. +type Defaults struct { + Config *aws.Config + Handlers request.Handlers +} + +// Get returns the SDK's default values with Config and handlers pre-configured. +func Get() Defaults { + cfg := Config() + handlers := Handlers() + cfg.Credentials = CredChain(cfg, handlers) + + return Defaults{ + Config: cfg, + Handlers: handlers, + } +} + +// Config returns the default configuration without credentials. +// To retrieve a config with credentials also included use +// `defaults.Get().Config` instead. +// +// Generally you shouldn't need to use this method directly, but +// is available if you need to reset the configuration of an +// existing service client or session. +func Config() *aws.Config { + return aws.NewConfig(). + WithCredentials(credentials.AnonymousCredentials). + WithRegion(os.Getenv("AWS_REGION")). + WithHTTPClient(http.DefaultClient). + WithMaxRetries(aws.UseServiceDefaultRetries). + WithLogger(aws.NewDefaultLogger()). + WithLogLevel(aws.LogOff). + WithSleepDelay(time.Sleep) +} + +// Handlers returns the default request handlers. +// +// Generally you shouldn't need to use this method directly, but +// is available if you need to reset the request handlers of an +// existing service client or session. +func Handlers() request.Handlers { + var handlers request.Handlers + + handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) + handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler) + handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) + handlers.Send.PushBackNamed(corehandlers.SendHandler) + handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) + handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler) + + return handlers +} + +// CredChain returns the default credential chain. +// +// Generally you shouldn't need to use this method directly, but +// is available if you need to reset the credentials of an +// existing service client or session's Config. +func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials { + endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true) + + return credentials.NewCredentials(&credentials.ChainProvider{ + VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), + Providers: []credentials.Provider{ + &credentials.EnvProvider{}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, + &ec2rolecreds.EC2RoleProvider{ + Client: ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion), + ExpiryWindow: 5 * time.Minute, + }, + }}) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go new file mode 100644 index 000000000..e5137ca17 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go @@ -0,0 +1,43 @@ +package ec2metadata + +import ( + "path" + + "github.com/aws/aws-sdk-go/aws/request" +) + +// GetMetadata uses the path provided to request +func (c *EC2Metadata) GetMetadata(p string) (string, error) { + op := &request.Operation{ + Name: "GetMetadata", + HTTPMethod: "GET", + HTTPPath: path.Join("/", "meta-data", p), + } + + output := &metadataOutput{} + req := c.NewRequest(op, nil, output) + + return output.Content, req.Send() +} + +// Region returns the region the instance is running in. +func (c *EC2Metadata) Region() (string, error) { + resp, err := c.GetMetadata("placement/availability-zone") + if err != nil { + return "", err + } + + // returns region without the suffix. Eg: us-west-2a becomes us-west-2 + return resp[:len(resp)-1], nil +} + +// Available returns if the application has access to the EC2 Metadata service. +// Can be used to determine if application is running within an EC2 Instance and +// the metadata service is available. +func (c *EC2Metadata) Available() bool { + if _, err := c.GetMetadata("instance-id"); err != nil { + return false + } + + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go new file mode 100644 index 000000000..9e16c1cf7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go @@ -0,0 +1,117 @@ +// Package ec2metadata provides the client for making API calls to the +// EC2 Metadata service. +package ec2metadata + +import ( + "io/ioutil" + "net/http" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" +) + +// ServiceName is the name of the service. +const ServiceName = "ec2metadata" + +// A EC2Metadata is an EC2 Metadata service Client. +type EC2Metadata struct { + *client.Client +} + +// New creates a new instance of the EC2Metadata client with a session. +// This client is safe to use across multiple goroutines. +// +// +// Example: +// // Create a EC2Metadata client from just a session. +// svc := ec2metadata.New(mySession) +// +// // Create a EC2Metadata client with additional configuration +// svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody)) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata { + c := p.ClientConfig(ServiceName, cfgs...) + return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) +} + +// NewClient returns a new EC2Metadata client. Should be used to create +// a client when not using a session. Generally using just New with a session +// is preferred. +// +// If an unmodified HTTP client is provided from the stdlib default, or no client +// the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened. +// To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default. +func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata { + if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) { + // If the http client is unmodified and this feature is not disabled + // set custom timeouts for EC2Metadata requests. + cfg.HTTPClient = &http.Client{ + // use a shorter timeout than default because the metadata + // service is local if it is running, and to fail faster + // if not running on an ec2 instance. + Timeout: 5 * time.Second, + } + } + + svc := &EC2Metadata{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + Endpoint: endpoint, + APIVersion: "latest", + }, + handlers, + ), + } + + svc.Handlers.Unmarshal.PushBack(unmarshalHandler) + svc.Handlers.UnmarshalError.PushBack(unmarshalError) + svc.Handlers.Validate.Clear() + svc.Handlers.Validate.PushBack(validateEndpointHandler) + + // Add additional options to the service config + for _, option := range opts { + option(svc.Client) + } + + return svc +} + +func httpClientZero(c *http.Client) bool { + return c == nil || (c.Transport == nil && c.CheckRedirect == nil && c.Jar == nil && c.Timeout == 0) +} + +type metadataOutput struct { + Content string +} + +func unmarshalHandler(r *request.Request) { + defer r.HTTPResponse.Body.Close() + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err) + } + + data := r.Data.(*metadataOutput) + data.Content = string(b) +} + +func unmarshalError(r *request.Request) { + defer r.HTTPResponse.Body.Close() + _, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err) + } + + // TODO extract the error... +} + +func validateEndpointHandler(r *request.Request) { + if r.ClientInfo.Endpoint == "" { + r.Error = aws.ErrMissingEndpoint + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/errors.go b/vendor/github.com/aws/aws-sdk-go/aws/errors.go new file mode 100644 index 000000000..576636168 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/errors.go @@ -0,0 +1,17 @@ +package aws + +import "github.com/aws/aws-sdk-go/aws/awserr" + +var ( + // ErrMissingRegion is an error that is returned if region configuration is + // not found. + // + // @readonly + ErrMissingRegion = awserr.New("MissingRegion", "could not find region configuration", nil) + + // ErrMissingEndpoint is an error that is returned if an endpoint cannot be + // resolved for a service. + // + // @readonly + ErrMissingEndpoint = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil) +) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/logger.go b/vendor/github.com/aws/aws-sdk-go/aws/logger.go new file mode 100644 index 000000000..f53694873 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/logger.go @@ -0,0 +1,98 @@ +package aws + +import ( + "log" + "os" +) + +// A LogLevelType defines the level logging should be performed at. Used to instruct +// the SDK which statements should be logged. +type LogLevelType uint + +// LogLevel returns the pointer to a LogLevel. Should be used to workaround +// not being able to take the address of a non-composite literal. +func LogLevel(l LogLevelType) *LogLevelType { + return &l +} + +// Value returns the LogLevel value or the default value LogOff if the LogLevel +// is nil. Safe to use on nil value LogLevelTypes. +func (l *LogLevelType) Value() LogLevelType { + if l != nil { + return *l + } + return LogOff +} + +// Matches returns true if the v LogLevel is enabled by this LogLevel. Should be +// used with logging sub levels. Is safe to use on nil value LogLevelTypes. If +// LogLevel is nill, will default to LogOff comparison. +func (l *LogLevelType) Matches(v LogLevelType) bool { + c := l.Value() + return c&v == v +} + +// AtLeast returns true if this LogLevel is at least high enough to satisfies v. +// Is safe to use on nil value LogLevelTypes. If LogLevel is nill, will default +// to LogOff comparison. +func (l *LogLevelType) AtLeast(v LogLevelType) bool { + c := l.Value() + return c >= v +} + +const ( + // LogOff states that no logging should be performed by the SDK. This is the + // default state of the SDK, and should be use to disable all logging. + LogOff LogLevelType = iota * 0x1000 + + // LogDebug state that debug output should be logged by the SDK. This should + // be used to inspect request made and responses received. + LogDebug +) + +// Debug Logging Sub Levels +const ( + // LogDebugWithSigning states that the SDK should log request signing and + // presigning events. This should be used to log the signing details of + // requests for debugging. Will also enable LogDebug. + LogDebugWithSigning LogLevelType = LogDebug | (1 << iota) + + // LogDebugWithHTTPBody states the SDK should log HTTP request and response + // HTTP bodys in addition to the headers and path. This should be used to + // see the body content of requests and responses made while using the SDK + // Will also enable LogDebug. + LogDebugWithHTTPBody + + // LogDebugWithRequestRetries states the SDK should log when service requests will + // be retried. This should be used to log when you want to log when service + // requests are being retried. Will also enable LogDebug. + LogDebugWithRequestRetries + + // LogDebugWithRequestErrors states the SDK should log when service requests fail + // to build, send, validate, or unmarshal. + LogDebugWithRequestErrors +) + +// A Logger is a minimalistic interface for the SDK to log messages to. Should +// be used to provide custom logging writers for the SDK to use. +type Logger interface { + Log(...interface{}) +} + +// NewDefaultLogger returns a Logger which will write log messages to stdout, and +// use same formatting runes as the stdlib log.Logger +func NewDefaultLogger() Logger { + return &defaultLogger{ + logger: log.New(os.Stdout, "", log.LstdFlags), + } +} + +// A defaultLogger provides a minimalistic logger satisfying the Logger interface. +type defaultLogger struct { + logger *log.Logger +} + +// Log logs the parameters to the stdlib logger. See log.Println. +func (l defaultLogger) Log(args ...interface{}) { + l.logger.Println(args...) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go new file mode 100644 index 000000000..3e90a7976 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go @@ -0,0 +1,140 @@ +package request + +import ( + "fmt" + "strings" +) + +// A Handlers provides a collection of request handlers for various +// stages of handling requests. +type Handlers struct { + Validate HandlerList + Build HandlerList + Sign HandlerList + Send HandlerList + ValidateResponse HandlerList + Unmarshal HandlerList + UnmarshalMeta HandlerList + UnmarshalError HandlerList + Retry HandlerList + AfterRetry HandlerList +} + +// Copy returns of this handler's lists. +func (h *Handlers) Copy() Handlers { + return Handlers{ + Validate: h.Validate.copy(), + Build: h.Build.copy(), + Sign: h.Sign.copy(), + Send: h.Send.copy(), + ValidateResponse: h.ValidateResponse.copy(), + Unmarshal: h.Unmarshal.copy(), + UnmarshalError: h.UnmarshalError.copy(), + UnmarshalMeta: h.UnmarshalMeta.copy(), + Retry: h.Retry.copy(), + AfterRetry: h.AfterRetry.copy(), + } +} + +// Clear removes callback functions for all handlers +func (h *Handlers) Clear() { + h.Validate.Clear() + h.Build.Clear() + h.Send.Clear() + h.Sign.Clear() + h.Unmarshal.Clear() + h.UnmarshalMeta.Clear() + h.UnmarshalError.Clear() + h.ValidateResponse.Clear() + h.Retry.Clear() + h.AfterRetry.Clear() +} + +// A HandlerList manages zero or more handlers in a list. +type HandlerList struct { + list []NamedHandler +} + +// A NamedHandler is a struct that contains a name and function callback. +type NamedHandler struct { + Name string + Fn func(*Request) +} + +// copy creates a copy of the handler list. +func (l *HandlerList) copy() HandlerList { + var n HandlerList + n.list = append([]NamedHandler{}, l.list...) + return n +} + +// Clear clears the handler list. +func (l *HandlerList) Clear() { + l.list = []NamedHandler{} +} + +// Len returns the number of handlers in the list. +func (l *HandlerList) Len() int { + return len(l.list) +} + +// PushBack pushes handler f to the back of the handler list. +func (l *HandlerList) PushBack(f func(*Request)) { + l.list = append(l.list, NamedHandler{"__anonymous", f}) +} + +// PushFront pushes handler f to the front of the handler list. +func (l *HandlerList) PushFront(f func(*Request)) { + l.list = append([]NamedHandler{{"__anonymous", f}}, l.list...) +} + +// PushBackNamed pushes named handler f to the back of the handler list. +func (l *HandlerList) PushBackNamed(n NamedHandler) { + l.list = append(l.list, n) +} + +// PushFrontNamed pushes named handler f to the front of the handler list. +func (l *HandlerList) PushFrontNamed(n NamedHandler) { + l.list = append([]NamedHandler{n}, l.list...) +} + +// Remove removes a NamedHandler n +func (l *HandlerList) Remove(n NamedHandler) { + newlist := []NamedHandler{} + for _, m := range l.list { + if m.Name != n.Name { + newlist = append(newlist, m) + } + } + l.list = newlist +} + +// Run executes all handlers in the list with a given request object. +func (l *HandlerList) Run(r *Request) { + for _, f := range l.list { + f.Fn(r) + } +} + +// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request +// header. If the extra parameters are provided they will be added as metadata to the +// name/version pair resulting in the following format. +// "name/version (extra0; extra1; ...)" +// The user agent part will be concatenated with this current request's user agent string. +func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) { + ua := fmt.Sprintf("%s/%s", name, version) + if len(extra) > 0 { + ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; ")) + } + return func(r *Request) { + AddToUserAgent(r, ua) + } +} + +// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header. +// The input string will be concatenated with the current request's user agent string. +func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) { + return func(r *Request) { + AddToUserAgent(r, s) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go new file mode 100644 index 000000000..61bb4a8ca --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go @@ -0,0 +1,294 @@ +package request + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client/metadata" +) + +// A Request is the service request to be made. +type Request struct { + Config aws.Config + ClientInfo metadata.ClientInfo + Handlers Handlers + + Retryer + Time time.Time + ExpireTime time.Duration + Operation *Operation + HTTPRequest *http.Request + HTTPResponse *http.Response + Body io.ReadSeeker + BodyStart int64 // offset from beginning of Body that the request body starts + Params interface{} + Error error + Data interface{} + RequestID string + RetryCount int + Retryable *bool + RetryDelay time.Duration + NotHoist bool + SignedHeaderVals http.Header + + built bool +} + +// An Operation is the service API operation to be made. +type Operation struct { + Name string + HTTPMethod string + HTTPPath string + *Paginator +} + +// Paginator keeps track of pagination configuration for an API operation. +type Paginator struct { + InputTokens []string + OutputTokens []string + LimitToken string + TruncationToken string +} + +// New returns a new Request pointer for the service API +// operation and parameters. +// +// Params is any value of input parameters to be the request payload. +// Data is pointer value to an object which the request's response +// payload will be deserialized to. +func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers, + retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request { + + method := operation.HTTPMethod + if method == "" { + method = "POST" + } + p := operation.HTTPPath + if p == "" { + p = "/" + } + + httpReq, _ := http.NewRequest(method, "", nil) + httpReq.URL, _ = url.Parse(clientInfo.Endpoint + p) + + r := &Request{ + Config: cfg, + ClientInfo: clientInfo, + Handlers: handlers.Copy(), + + Retryer: retryer, + Time: time.Now(), + ExpireTime: 0, + Operation: operation, + HTTPRequest: httpReq, + Body: nil, + Params: params, + Error: nil, + Data: data, + } + r.SetBufferBody([]byte{}) + + return r +} + +// WillRetry returns if the request's can be retried. +func (r *Request) WillRetry() bool { + return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries() +} + +// ParamsFilled returns if the request's parameters have been populated +// and the parameters are valid. False is returned if no parameters are +// provided or invalid. +func (r *Request) ParamsFilled() bool { + return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid() +} + +// DataFilled returns true if the request's data for response deserialization +// target has been set and is a valid. False is returned if data is not +// set, or is invalid. +func (r *Request) DataFilled() bool { + return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid() +} + +// SetBufferBody will set the request's body bytes that will be sent to +// the service API. +func (r *Request) SetBufferBody(buf []byte) { + r.SetReaderBody(bytes.NewReader(buf)) +} + +// SetStringBody sets the body of the request to be backed by a string. +func (r *Request) SetStringBody(s string) { + r.SetReaderBody(strings.NewReader(s)) +} + +// SetReaderBody will set the request's body reader. +func (r *Request) SetReaderBody(reader io.ReadSeeker) { + r.HTTPRequest.Body = ioutil.NopCloser(reader) + r.Body = reader +} + +// Presign returns the request's signed URL. Error will be returned +// if the signing fails. +func (r *Request) Presign(expireTime time.Duration) (string, error) { + r.ExpireTime = expireTime + r.NotHoist = false + r.Sign() + if r.Error != nil { + return "", r.Error + } + return r.HTTPRequest.URL.String(), nil +} + +// PresignRequest behaves just like presign, but hoists all headers and signs them. +// Also returns the signed hash back to the user +func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error) { + r.ExpireTime = expireTime + r.NotHoist = true + r.Sign() + if r.Error != nil { + return "", nil, r.Error + } + return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil +} + +func debugLogReqError(r *Request, stage string, retrying bool, err error) { + if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) { + return + } + + retryStr := "not retrying" + if retrying { + retryStr = "will retry" + } + + r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v", + stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err)) +} + +// Build will build the request's object so it can be signed and sent +// to the service. Build will also validate all the request's parameters. +// Anny additional build Handlers set on this request will be run +// in the order they were set. +// +// The request will only be built once. Multiple calls to build will have +// no effect. +// +// If any Validate or Build errors occur the build will stop and the error +// which occurred will be returned. +func (r *Request) Build() error { + if !r.built { + r.Error = nil + r.Handlers.Validate.Run(r) + if r.Error != nil { + debugLogReqError(r, "Validate Request", false, r.Error) + return r.Error + } + r.Handlers.Build.Run(r) + r.built = true + } + + return r.Error +} + +// Sign will sign the request retuning error if errors are encountered. +// +// Send will build the request prior to signing. All Sign Handlers will +// be executed in the order they were set. +func (r *Request) Sign() error { + r.Build() + if r.Error != nil { + debugLogReqError(r, "Build Request", false, r.Error) + return r.Error + } + + r.Handlers.Sign.Run(r) + return r.Error +} + +// Send will send the request returning error if errors are encountered. +// +// Send will sign the request prior to sending. All Send Handlers will +// be executed in the order they were set. +func (r *Request) Send() error { + for { + r.Sign() + if r.Error != nil { + return r.Error + } + + if aws.BoolValue(r.Retryable) { + if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) { + r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d", + r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount)) + } + + // Re-seek the body back to the original point in for a retry so that + // send will send the body's contents again in the upcoming request. + r.Body.Seek(r.BodyStart, 0) + r.HTTPRequest.Body = ioutil.NopCloser(r.Body) + } + r.Retryable = nil + + r.Handlers.Send.Run(r) + if r.Error != nil { + err := r.Error + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Send Request", false, r.Error) + return r.Error + } + debugLogReqError(r, "Send Request", true, err) + continue + } + + r.Handlers.UnmarshalMeta.Run(r) + r.Handlers.ValidateResponse.Run(r) + if r.Error != nil { + err := r.Error + r.Handlers.UnmarshalError.Run(r) + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Validate Response", false, r.Error) + return r.Error + } + debugLogReqError(r, "Validate Response", true, err) + continue + } + + r.Handlers.Unmarshal.Run(r) + if r.Error != nil { + err := r.Error + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Unmarshal Response", false, r.Error) + return r.Error + } + debugLogReqError(r, "Unmarshal Response", true, err) + continue + } + + break + } + + return nil +} + +// AddToUserAgent adds the string to the end of the request's current user agent. +func AddToUserAgent(r *Request, s string) { + curUA := r.HTTPRequest.Header.Get("User-Agent") + if len(curUA) > 0 { + s = curUA + " " + s + } + r.HTTPRequest.Header.Set("User-Agent", s) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go new file mode 100644 index 000000000..2939ec473 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go @@ -0,0 +1,104 @@ +package request + +import ( + "reflect" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" +) + +//type Paginater interface { +// HasNextPage() bool +// NextPage() *Request +// EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error +//} + +// HasNextPage returns true if this request has more pages of data available. +func (r *Request) HasNextPage() bool { + return len(r.nextPageTokens()) > 0 +} + +// nextPageTokens returns the tokens to use when asking for the next page of +// data. +func (r *Request) nextPageTokens() []interface{} { + if r.Operation.Paginator == nil { + return nil + } + + if r.Operation.TruncationToken != "" { + tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken) + if len(tr) == 0 { + return nil + } + + switch v := tr[0].(type) { + case *bool: + if !aws.BoolValue(v) { + return nil + } + case bool: + if v == false { + return nil + } + } + } + + tokens := []interface{}{} + tokenAdded := false + for _, outToken := range r.Operation.OutputTokens { + v, _ := awsutil.ValuesAtPath(r.Data, outToken) + if len(v) > 0 { + tokens = append(tokens, v[0]) + tokenAdded = true + } else { + tokens = append(tokens, nil) + } + } + if !tokenAdded { + return nil + } + + return tokens +} + +// NextPage returns a new Request that can be executed to return the next +// page of result data. Call .Send() on this request to execute it. +func (r *Request) NextPage() *Request { + tokens := r.nextPageTokens() + if len(tokens) == 0 { + return nil + } + + data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface() + nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data) + for i, intok := range nr.Operation.InputTokens { + awsutil.SetValueAtPath(nr.Params, intok, tokens[i]) + } + return nr +} + +// EachPage iterates over each page of a paginated request object. The fn +// parameter should be a function with the following sample signature: +// +// func(page *T, lastPage bool) bool { +// return true // return false to stop iterating +// } +// +// Where "T" is the structure type matching the output structure of the given +// operation. For example, a request object generated by +// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput +// as the structure "T". The lastPage value represents whether the page is +// the last page of data or not. The return value of this function should +// return true to keep iterating or false to stop. +func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error { + for page := r; page != nil; page = page.NextPage() { + if err := page.Send(); err != nil { + return err + } + if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage { + return page.Error + } + } + + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go new file mode 100644 index 000000000..ab6fff5ac --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go @@ -0,0 +1,82 @@ +package request + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// Retryer is an interface to control retry logic for a given service. +// The default implementation used by most services is the service.DefaultRetryer +// structure, which contains basic retry logic using exponential backoff. +type Retryer interface { + RetryRules(*Request) time.Duration + ShouldRetry(*Request) bool + MaxRetries() int +} + +// WithRetryer sets a config Retryer value to the given Config returning it +// for chaining. +func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config { + cfg.Retryer = retryer + return cfg +} + +// retryableCodes is a collection of service response codes which are retry-able +// without any further action. +var retryableCodes = map[string]struct{}{ + "RequestError": {}, + "RequestTimeout": {}, + "ProvisionedThroughputExceededException": {}, + "Throttling": {}, + "ThrottlingException": {}, + "RequestLimitExceeded": {}, + "RequestThrottled": {}, + "LimitExceededException": {}, // Deleting 10+ DynamoDb tables at once + "TooManyRequestsException": {}, // Lambda functions +} + +// credsExpiredCodes is a collection of error codes which signify the credentials +// need to be refreshed. Expired tokens require refreshing of credentials, and +// resigning before the request can be retried. +var credsExpiredCodes = map[string]struct{}{ + "ExpiredToken": {}, + "ExpiredTokenException": {}, + "RequestExpired": {}, // EC2 Only +} + +func isCodeRetryable(code string) bool { + if _, ok := retryableCodes[code]; ok { + return true + } + + return isCodeExpiredCreds(code) +} + +func isCodeExpiredCreds(code string) bool { + _, ok := credsExpiredCodes[code] + return ok +} + +// IsErrorRetryable returns whether the error is retryable, based on its Code. +// Returns false if the request has no Error set. +func (r *Request) IsErrorRetryable() bool { + if r.Error != nil { + if err, ok := r.Error.(awserr.Error); ok { + return isCodeRetryable(err.Code()) + } + } + return false +} + +// IsErrorExpired returns whether the error code is a credential expiry error. +// Returns false if the request has no Error set. +func (r *Request) IsErrorExpired() bool { + if r.Error != nil { + if err, ok := r.Error.(awserr.Error); ok { + return isCodeExpiredCreds(err.Code()) + } + } + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/session.go b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go new file mode 100644 index 000000000..47e4536ff --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go @@ -0,0 +1,120 @@ +// Package session provides a way to create service clients with shared configuration +// and handlers. +// +// Generally this package should be used instead of the `defaults` package. +// +// A session should be used to share configurations and request handlers between multiple +// service clients. When service clients need specific configuration aws.Config can be +// used to provide additional configuration directly to the service client. +package session + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/corehandlers" + "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/endpoints" +) + +// A Session provides a central location to create service clients from and +// store configurations and request handlers for those services. +// +// Sessions are safe to create service clients concurrently, but it is not safe +// to mutate the session concurrently. +type Session struct { + Config *aws.Config + Handlers request.Handlers +} + +// New creates a new instance of the handlers merging in the provided Configs +// on top of the SDK's default configurations. Once the session is created it +// can be mutated to modify Configs or Handlers. The session is safe to be read +// concurrently, but it should not be written to concurrently. +// +// Example: +// // Create a session with the default config and request handlers. +// sess := session.New() +// +// // Create a session with a custom region +// sess := session.New(&aws.Config{Region: aws.String("us-east-1")}) +// +// // Create a session, and add additional handlers for all service +// // clients created with the session to inherit. Adds logging handler. +// sess := session.New() +// sess.Handlers.Send.PushFront(func(r *request.Request) { +// // Log every request made and its payload +// logger.Println("Request: %s/%s, Payload: %s", r.ClientInfo.ServiceName, r.Operation, r.Params) +// }) +// +// // Create a S3 client instance from a session +// sess := session.New() +// svc := s3.New(sess) +func New(cfgs ...*aws.Config) *Session { + cfg := defaults.Config() + handlers := defaults.Handlers() + + // Apply the passed in configs so the configuration can be applied to the + // default credential chain + cfg.MergeIn(cfgs...) + cfg.Credentials = defaults.CredChain(cfg, handlers) + + // Reapply any passed in configs to override credentials if set + cfg.MergeIn(cfgs...) + + s := &Session{ + Config: cfg, + Handlers: handlers, + } + + initHandlers(s) + + return s +} + +func initHandlers(s *Session) { + // Add the Validate parameter handler if it is not disabled. + s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) + if !aws.BoolValue(s.Config.DisableParamValidation) { + s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) + } +} + +// Copy creates and returns a copy of the current session, coping the config +// and handlers. If any additional configs are provided they will be merged +// on top of the session's copied config. +// +// Example: +// // Create a copy of the current session, configured for the us-west-2 region. +// sess.Copy(&aws.Config{Region: aws.String("us-west-2"}) +func (s *Session) Copy(cfgs ...*aws.Config) *Session { + newSession := &Session{ + Config: s.Config.Copy(cfgs...), + Handlers: s.Handlers.Copy(), + } + + initHandlers(newSession) + + return newSession +} + +// ClientConfig satisfies the client.ConfigProvider interface and is used to +// configure the service client instances. Passing the Session to the service +// client's constructor (New) will use this method to configure the client. +// +// Example: +// sess := session.New() +// s3.New(sess) +func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config { + s = s.Copy(cfgs...) + endpoint, signingRegion := endpoints.NormalizeEndpoint( + aws.StringValue(s.Config.Endpoint), serviceName, + aws.StringValue(s.Config.Region), aws.BoolValue(s.Config.DisableSSL)) + + return client.Config{ + Config: s.Config, + Handlers: s.Handlers, + Endpoint: endpoint, + SigningRegion: signingRegion, + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/types.go b/vendor/github.com/aws/aws-sdk-go/aws/types.go new file mode 100644 index 000000000..0f067c57f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/types.go @@ -0,0 +1,88 @@ +package aws + +import ( + "io" + "sync" +) + +// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser +func ReadSeekCloser(r io.Reader) ReaderSeekerCloser { + return ReaderSeekerCloser{r} +} + +// ReaderSeekerCloser represents a reader that can also delegate io.Seeker and +// io.Closer interfaces to the underlying object if they are available. +type ReaderSeekerCloser struct { + r io.Reader +} + +// Read reads from the reader up to size of p. The number of bytes read, and +// error if it occurred will be returned. +// +// If the reader is not an io.Reader zero bytes read, and nil error will be returned. +// +// Performs the same functionality as io.Reader Read +func (r ReaderSeekerCloser) Read(p []byte) (int, error) { + switch t := r.r.(type) { + case io.Reader: + return t.Read(p) + } + return 0, nil +} + +// Seek sets the offset for the next Read to offset, interpreted according to +// whence: 0 means relative to the origin of the file, 1 means relative to the +// current offset, and 2 means relative to the end. Seek returns the new offset +// and an error, if any. +// +// If the ReaderSeekerCloser is not an io.Seeker nothing will be done. +func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) { + switch t := r.r.(type) { + case io.Seeker: + return t.Seek(offset, whence) + } + return int64(0), nil +} + +// Close closes the ReaderSeekerCloser. +// +// If the ReaderSeekerCloser is not an io.Closer nothing will be done. +func (r ReaderSeekerCloser) Close() error { + switch t := r.r.(type) { + case io.Closer: + return t.Close() + } + return nil +} + +// A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface +// Can be used with the s3manager.Downloader to download content to a buffer +// in memory. Safe to use concurrently. +type WriteAtBuffer struct { + buf []byte + m sync.Mutex +} + +// WriteAt writes a slice of bytes to a buffer starting at the position provided +// The number of bytes written will be returned, or error. Can overwrite previous +// written slices if the write ats overlap. +func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + + expLen := pos + int64(len(p)) + if int64(len(b.buf)) < expLen { + newBuf := make([]byte, expLen) + copy(newBuf, b.buf) + b.buf = newBuf + } + copy(b.buf[pos:], p) + return len(p), nil +} + +// Bytes returns a slice of bytes written to the buffer. +func (b *WriteAtBuffer) Bytes() []byte { + b.m.Lock() + defer b.m.Unlock() + return b.buf[:len(b.buf):len(b.buf)] +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go new file mode 100644 index 000000000..ad215ea8e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -0,0 +1,8 @@ +// Package aws provides core functionality for making requests to AWS services. +package aws + +// SDKName is the name of this AWS SDK +const SDKName = "aws-sdk-go" + +// SDKVersion is the version of this SDK +const SDKVersion = "1.1.0" diff --git a/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go new file mode 100644 index 000000000..2b279e659 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go @@ -0,0 +1,65 @@ +// Package endpoints validates regional endpoints for services. +package endpoints + +//go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go +//go:generate gofmt -s -w endpoints_map.go + +import ( + "fmt" + "regexp" + "strings" +) + +// NormalizeEndpoint takes and endpoint and service API information to return a +// normalized endpoint and signing region. If the endpoint is not an empty string +// the service name and region will be used to look up the service's API endpoint. +// If the endpoint is provided the scheme will be added if it is not present. +func NormalizeEndpoint(endpoint, serviceName, region string, disableSSL bool) (normEndpoint, signingRegion string) { + if endpoint == "" { + return EndpointForRegion(serviceName, region, disableSSL) + } + + return AddScheme(endpoint, disableSSL), "" +} + +// EndpointForRegion returns an endpoint and its signing region for a service and region. +// if the service and region pair are not found endpoint and signingRegion will be empty. +func EndpointForRegion(svcName, region string, disableSSL bool) (endpoint, signingRegion string) { + derivedKeys := []string{ + region + "/" + svcName, + region + "/*", + "*/" + svcName, + "*/*", + } + + for _, key := range derivedKeys { + if val, ok := endpointsMap.Endpoints[key]; ok { + ep := val.Endpoint + ep = strings.Replace(ep, "{region}", region, -1) + ep = strings.Replace(ep, "{service}", svcName, -1) + + endpoint = ep + signingRegion = val.SigningRegion + break + } + } + + return AddScheme(endpoint, disableSSL), signingRegion +} + +// Regular expression to determine if the endpoint string is prefixed with a scheme. +var schemeRE = regexp.MustCompile("^([^:]+)://") + +// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no +// scheme. If disableSSL is true HTTP will be added instead of the default HTTPS. +func AddScheme(endpoint string, disableSSL bool) string { + if endpoint != "" && !schemeRE.MatchString(endpoint) { + scheme := "https" + if disableSSL { + scheme = "http" + } + endpoint = fmt.Sprintf("%s://%s", scheme, endpoint) + } + + return endpoint +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json new file mode 100644 index 000000000..7819eedc3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json @@ -0,0 +1,92 @@ +{ + "version": 2, + "endpoints": { + "*/*": { + "endpoint": "{service}.{region}.amazonaws.com" + }, + "cn-north-1/*": { + "endpoint": "{service}.{region}.amazonaws.com.cn", + "signatureVersion": "v4" + }, + "us-gov-west-1/iam": { + "endpoint": "iam.us-gov.amazonaws.com" + }, + "us-gov-west-1/sts": { + "endpoint": "sts.us-gov-west-1.amazonaws.com" + }, + "us-gov-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "*/cloudfront": { + "endpoint": "cloudfront.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/cloudsearchdomain": { + "endpoint": "", + "signingRegion": "us-east-1" + }, + "*/data.iot": { + "endpoint": "", + "signingRegion": "us-east-1" + }, + "*/ec2metadata": { + "endpoint": "http://169.254.169.254/latest", + "signingRegion": "us-east-1" + }, + "*/iam": { + "endpoint": "iam.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/importexport": { + "endpoint": "importexport.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/route53": { + "endpoint": "route53.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/sts": { + "endpoint": "sts.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/waf": { + "endpoint": "waf.amazonaws.com", + "signingRegion": "us-east-1" + }, + "us-east-1/sdb": { + "endpoint": "sdb.amazonaws.com", + "signingRegion": "us-east-1" + }, + "us-east-1/s3": { + "endpoint": "s3.amazonaws.com" + }, + "us-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "us-west-2/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "eu-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-southeast-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-southeast-2/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-northeast-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-northeast-2/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "sa-east-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "eu-central-1/s3": { + "endpoint": "{service}.{region}.amazonaws.com", + "signatureVersion": "v4" + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go new file mode 100644 index 000000000..9b2e1b699 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go @@ -0,0 +1,104 @@ +package endpoints + +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +type endpointStruct struct { + Version int + Endpoints map[string]endpointEntry +} + +type endpointEntry struct { + Endpoint string + SigningRegion string +} + +var endpointsMap = endpointStruct{ + Version: 2, + Endpoints: map[string]endpointEntry{ + "*/*": { + Endpoint: "{service}.{region}.amazonaws.com", + }, + "*/cloudfront": { + Endpoint: "cloudfront.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/cloudsearchdomain": { + Endpoint: "", + SigningRegion: "us-east-1", + }, + "*/data.iot": { + Endpoint: "", + SigningRegion: "us-east-1", + }, + "*/ec2metadata": { + Endpoint: "http://169.254.169.254/latest", + SigningRegion: "us-east-1", + }, + "*/iam": { + Endpoint: "iam.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/importexport": { + Endpoint: "importexport.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/route53": { + Endpoint: "route53.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/sts": { + Endpoint: "sts.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/waf": { + Endpoint: "waf.amazonaws.com", + SigningRegion: "us-east-1", + }, + "ap-northeast-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "ap-northeast-2/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "ap-southeast-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "ap-southeast-2/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "cn-north-1/*": { + Endpoint: "{service}.{region}.amazonaws.com.cn", + }, + "eu-central-1/s3": { + Endpoint: "{service}.{region}.amazonaws.com", + }, + "eu-west-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "sa-east-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-east-1/s3": { + Endpoint: "s3.amazonaws.com", + }, + "us-east-1/sdb": { + Endpoint: "sdb.amazonaws.com", + SigningRegion: "us-east-1", + }, + "us-gov-west-1/iam": { + Endpoint: "iam.us-gov.amazonaws.com", + }, + "us-gov-west-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-gov-west-1/sts": { + Endpoint: "sts.us-gov-west-1.amazonaws.com", + }, + "us-west-1/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-west-2/s3": { + Endpoint: "s3-{region}.amazonaws.com", + }, + }, +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go new file mode 100644 index 000000000..68e344d1f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go @@ -0,0 +1,35 @@ +// Package ec2query provides serialisation of AWS EC2 requests and responses. +package ec2query + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/ec2.json build_test.go + +import ( + "net/url" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query/queryutil" +) + +// BuildHandler is a named request handler for building ec2query protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.ec2query.Build", Fn: Build} + +// Build builds a request for the EC2 protocol. +func Build(r *request.Request) { + body := url.Values{ + "Action": {r.Operation.Name}, + "Version": {r.ClientInfo.APIVersion}, + } + if err := queryutil.Parse(body, r.Params, true); err != nil { + r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err) + } + + if r.ExpireTime == 0 { + r.HTTPRequest.Method = "POST" + r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") + r.SetBufferBody([]byte(body.Encode())) + } else { // This is a pre-signed request + r.HTTPRequest.Method = "GET" + r.HTTPRequest.URL.RawQuery = body.Encode() + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal.go new file mode 100644 index 000000000..9223e8422 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal.go @@ -0,0 +1,63 @@ +package ec2query + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/ec2.json unmarshal_test.go + +import ( + "encoding/xml" + "io" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" +) + +// UnmarshalHandler is a named request handler for unmarshaling ec2query protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.ec2query.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling ec2query protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.ec2query.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling ec2query protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.ec2query.UnmarshalError", Fn: UnmarshalError} + +// Unmarshal unmarshals a response body for the EC2 protocol. +func Unmarshal(r *request.Request) { + defer r.HTTPResponse.Body.Close() + if r.DataFilled() { + decoder := xml.NewDecoder(r.HTTPResponse.Body) + err := xmlutil.UnmarshalXML(r.Data, decoder, "") + if err != nil { + r.Error = awserr.New("SerializationError", "failed decoding EC2 Query response", err) + return + } + } +} + +// UnmarshalMeta unmarshals response headers for the EC2 protocol. +func UnmarshalMeta(r *request.Request) { + // TODO implement unmarshaling of request IDs +} + +type xmlErrorResponse struct { + XMLName xml.Name `xml:"Response"` + Code string `xml:"Errors>Error>Code"` + Message string `xml:"Errors>Error>Message"` + RequestID string `xml:"RequestId"` +} + +// UnmarshalError unmarshals a response error for the EC2 protocol. +func UnmarshalError(r *request.Request) { + defer r.HTTPResponse.Body.Close() + + resp := &xmlErrorResponse{} + err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) + if err != nil && err != io.EOF { + r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err) + } else { + r.Error = awserr.NewRequestFailure( + awserr.New(resp.Code, resp.Message, nil), + r.HTTPResponse.StatusCode, + resp.RequestID, + ) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go new file mode 100644 index 000000000..53831dff9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go @@ -0,0 +1,75 @@ +package protocol + +import ( + "crypto/rand" + "fmt" + "reflect" +) + +// RandReader is the random reader the protocol package will use to read +// random bytes from. This is exported for testing, and should not be used. +var RandReader = rand.Reader + +const idempotencyTokenFillTag = `idempotencyToken` + +// CanSetIdempotencyToken returns true if the struct field should be +// automatically populated with a Idempotency token. +// +// Only *string and string type fields that are tagged with idempotencyToken +// which are not already set can be auto filled. +func CanSetIdempotencyToken(v reflect.Value, f reflect.StructField) bool { + switch u := v.Interface().(type) { + // To auto fill an Idempotency token the field must be a string, + // tagged for auto fill, and have a zero value. + case *string: + return u == nil && len(f.Tag.Get(idempotencyTokenFillTag)) != 0 + case string: + return len(u) == 0 && len(f.Tag.Get(idempotencyTokenFillTag)) != 0 + } + + return false +} + +// GetIdempotencyToken returns a randomly generated idempotency token. +func GetIdempotencyToken() string { + b := make([]byte, 16) + RandReader.Read(b) + + return UUIDVersion4(b) +} + +// SetIdempotencyToken will set the value provided with a Idempotency Token. +// Given that the value can be set. Will panic if value is not setable. +func SetIdempotencyToken(v reflect.Value) { + if v.Kind() == reflect.Ptr { + if v.IsNil() && v.CanSet() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + v = reflect.Indirect(v) + + if !v.CanSet() { + panic(fmt.Sprintf("unable to set idempotnecy token %v", v)) + } + + b := make([]byte, 16) + _, err := rand.Read(b) + if err != nil { + // TODO handle error + return + } + + v.Set(reflect.ValueOf(UUIDVersion4(b))) +} + +// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided +func UUIDVersion4(u []byte) string { + // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29 + // 13th character is "4" + u[6] = (u[6] | 0x40) & 0x4F + // 17th character is "8", "9", "a", or "b" + u[8] = (u[8] | 0x80) & 0xBF + + return fmt.Sprintf(`%X-%X-%X-%X-%X`, u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go new file mode 100644 index 000000000..1d552afe4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go @@ -0,0 +1,251 @@ +// Package jsonutil provides JSON serialisation of AWS requests and responses. +package jsonutil + +import ( + "bytes" + "encoding/base64" + "fmt" + "reflect" + "sort" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/private/protocol" +) + +var timeType = reflect.ValueOf(time.Time{}).Type() +var byteSliceType = reflect.ValueOf([]byte{}).Type() + +// BuildJSON builds a JSON string for a given object v. +func BuildJSON(v interface{}) ([]byte, error) { + var buf bytes.Buffer + + err := buildAny(reflect.ValueOf(v), &buf, "") + return buf.Bytes(), err +} + +func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + value = reflect.Indirect(value) + if !value.IsValid() { + return nil + } + + vtype := value.Type() + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if value.Type() != timeType { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return buildStruct(value, buf, tag) + case "list": + return buildList(value, buf, tag) + case "map": + return buildMap(value, buf, tag) + default: + return buildScalar(value, buf, tag) + } +} + +func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + // unwrap payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := value.Type().FieldByName(payload) + tag = field.Tag + value = elemOf(value.FieldByName(payload)) + + if !value.IsValid() { + return nil + } + } + + buf.WriteByte('{') + + t := value.Type() + first := true + for i := 0; i < t.NumField(); i++ { + member := value.Field(i) + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + if field.Tag.Get("json") == "-" { + continue + } + if field.Tag.Get("location") != "" { + continue // ignore non-body elements + } + + if protocol.CanSetIdempotencyToken(member, field) { + token := protocol.GetIdempotencyToken() + member = reflect.ValueOf(&token) + } + + if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() { + continue // ignore unset fields + } + + if first { + first = false + } else { + buf.WriteByte(',') + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + fmt.Fprintf(buf, "%q:", name) + + err := buildAny(member, buf, field.Tag) + if err != nil { + return err + } + + } + + buf.WriteString("}") + + return nil +} + +func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("[") + + for i := 0; i < value.Len(); i++ { + buildAny(value.Index(i), buf, "") + + if i < value.Len()-1 { + buf.WriteString(",") + } + } + + buf.WriteString("]") + + return nil +} + +type sortedValues []reflect.Value + +func (sv sortedValues) Len() int { return len(sv) } +func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() } + +func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("{") + + var sv sortedValues = value.MapKeys() + sort.Sort(sv) + + for i, k := range sv { + if i > 0 { + buf.WriteByte(',') + } + + fmt.Fprintf(buf, "%q:", k) + buildAny(value.MapIndex(k), buf, "") + } + + buf.WriteString("}") + + return nil +} + +func buildScalar(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + switch value.Kind() { + case reflect.String: + writeString(value.String(), buf) + case reflect.Bool: + buf.WriteString(strconv.FormatBool(value.Bool())) + case reflect.Int64: + buf.WriteString(strconv.FormatInt(value.Int(), 10)) + case reflect.Float64: + buf.WriteString(strconv.FormatFloat(value.Float(), 'f', -1, 64)) + default: + switch value.Type() { + case timeType: + converted := value.Interface().(time.Time) + buf.WriteString(strconv.FormatInt(converted.UTC().Unix(), 10)) + case byteSliceType: + if !value.IsNil() { + converted := value.Interface().([]byte) + buf.WriteByte('"') + if len(converted) < 1024 { + // for small buffers, using Encode directly is much faster. + dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted))) + base64.StdEncoding.Encode(dst, converted) + buf.Write(dst) + } else { + // for large buffers, avoid unnecessary extra temporary + // buffer space. + enc := base64.NewEncoder(base64.StdEncoding, buf) + enc.Write(converted) + enc.Close() + } + buf.WriteByte('"') + } + default: + return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type()) + } + } + return nil +} + +func writeString(s string, buf *bytes.Buffer) { + buf.WriteByte('"') + for _, r := range s { + if r == '"' { + buf.WriteString(`\"`) + } else if r == '\\' { + buf.WriteString(`\\`) + } else if r == '\b' { + buf.WriteString(`\b`) + } else if r == '\f' { + buf.WriteString(`\f`) + } else if r == '\r' { + buf.WriteString(`\r`) + } else if r == '\t' { + buf.WriteString(`\t`) + } else if r == '\n' { + buf.WriteString(`\n`) + } else if r < 32 { + fmt.Fprintf(buf, "\\u%0.4x", r) + } else { + buf.WriteRune(r) + } + } + buf.WriteByte('"') +} + +// Returns the reflection element of a value, if it is a pointer. +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go new file mode 100644 index 000000000..fea535613 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go @@ -0,0 +1,213 @@ +package jsonutil + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "reflect" + "time" +) + +// UnmarshalJSON reads a stream and unmarshals the results in object v. +func UnmarshalJSON(v interface{}, stream io.Reader) error { + var out interface{} + + b, err := ioutil.ReadAll(stream) + if err != nil { + return err + } + + if len(b) == 0 { + return nil + } + + if err := json.Unmarshal(b, &out); err != nil { + return err + } + + return unmarshalAny(reflect.ValueOf(v), out, "") +} + +func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error { + vtype := value.Type() + if vtype.Kind() == reflect.Ptr { + vtype = vtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if _, ok := value.Interface().(*time.Time); !ok { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return unmarshalStruct(value, data, tag) + case "list": + return unmarshalList(value, data, tag) + case "map": + return unmarshalMap(value, data, tag) + default: + return unmarshalScalar(value, data, tag) + } +} + +func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a structure (%#v)", data) + } + + t := value.Type() + if value.Kind() == reflect.Ptr { + if value.IsNil() { // create the structure if it's nil + s := reflect.New(value.Type().Elem()) + value.Set(s) + value = s + } + + value = value.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return unmarshalAny(value.FieldByName(payload), data, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if field.PkgPath != "" { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + member := value.FieldByIndex(field.Index) + err := unmarshalAny(member, mapData[name], field.Tag) + if err != nil { + return err + } + } + return nil +} + +func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + listData, ok := data.([]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a list (%#v)", data) + } + + if value.IsNil() { + l := len(listData) + value.Set(reflect.MakeSlice(value.Type(), l, l)) + } + + for i, c := range listData { + err := unmarshalAny(value.Index(i), c, "") + if err != nil { + return err + } + } + + return nil +} + +func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a map (%#v)", data) + } + + if value.IsNil() { + value.Set(reflect.MakeMap(value.Type())) + } + + for k, v := range mapData { + kvalue := reflect.ValueOf(k) + vvalue := reflect.New(value.Type().Elem()).Elem() + + unmarshalAny(vvalue, v, "") + value.SetMapIndex(kvalue, vvalue) + } + + return nil +} + +func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error { + errf := func() error { + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + + switch d := data.(type) { + case nil: + return nil // nothing to do here + case string: + switch value.Interface().(type) { + case *string: + value.Set(reflect.ValueOf(&d)) + case []byte: + b, err := base64.StdEncoding.DecodeString(d) + if err != nil { + return err + } + value.Set(reflect.ValueOf(b)) + default: + return errf() + } + case float64: + switch value.Interface().(type) { + case *int64: + di := int64(d) + value.Set(reflect.ValueOf(&di)) + case *float64: + value.Set(reflect.ValueOf(&d)) + case *time.Time: + t := time.Unix(int64(d), 0).UTC() + value.Set(reflect.ValueOf(&t)) + default: + return errf() + } + case bool: + switch value.Interface().(type) { + case *bool: + value.Set(reflect.ValueOf(&d)) + default: + return errf() + } + default: + return fmt.Errorf("unsupported JSON value (%v)", data) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go new file mode 100644 index 000000000..7aff0e0fa --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go @@ -0,0 +1,111 @@ +// Package jsonrpc provides JSON RPC utilities for serialisation of AWS +// requests and responses. +package jsonrpc + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/json.json build_test.go +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/json.json unmarshal_test.go + +import ( + "encoding/json" + "io/ioutil" + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +var emptyJSON = []byte("{}") + +// BuildHandler is a named request handler for building jsonrpc protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Build", Fn: Build} + +// UnmarshalHandler is a named request handler for unmarshaling jsonrpc protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling jsonrpc protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling jsonrpc protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalError", Fn: UnmarshalError} + +// Build builds a JSON payload for a JSON RPC request. +func Build(req *request.Request) { + var buf []byte + var err error + if req.ParamsFilled() { + buf, err = jsonutil.BuildJSON(req.Params) + if err != nil { + req.Error = awserr.New("SerializationError", "failed encoding JSON RPC request", err) + return + } + } else { + buf = emptyJSON + } + + if req.ClientInfo.TargetPrefix != "" || string(buf) != "{}" { + req.SetBufferBody(buf) + } + + if req.ClientInfo.TargetPrefix != "" { + target := req.ClientInfo.TargetPrefix + "." + req.Operation.Name + req.HTTPRequest.Header.Add("X-Amz-Target", target) + } + if req.ClientInfo.JSONVersion != "" { + jsonVersion := req.ClientInfo.JSONVersion + req.HTTPRequest.Header.Add("Content-Type", "application/x-amz-json-"+jsonVersion) + } +} + +// Unmarshal unmarshals a response for a JSON RPC service. +func Unmarshal(req *request.Request) { + defer req.HTTPResponse.Body.Close() + if req.DataFilled() { + err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.New("SerializationError", "failed decoding JSON RPC response", err) + } + } + return +} + +// UnmarshalMeta unmarshals headers from a response for a JSON RPC service. +func UnmarshalMeta(req *request.Request) { + rest.UnmarshalMeta(req) +} + +// UnmarshalError unmarshals an error response for a JSON RPC service. +func UnmarshalError(req *request.Request) { + defer req.HTTPResponse.Body.Close() + bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.New("SerializationError", "failed reading JSON RPC error response", err) + return + } + if len(bodyBytes) == 0 { + req.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", req.HTTPResponse.Status, nil), + req.HTTPResponse.StatusCode, + "", + ) + return + } + var jsonErr jsonErrorResponse + if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { + req.Error = awserr.New("SerializationError", "failed decoding JSON RPC error response", err) + return + } + + codes := strings.SplitN(jsonErr.Code, "#", 2) + req.Error = awserr.NewRequestFailure( + awserr.New(codes[len(codes)-1], jsonErr.Message, nil), + req.HTTPResponse.StatusCode, + req.RequestID, + ) +} + +type jsonErrorResponse struct { + Code string `json:"__type"` + Message string `json:"message"` +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go new file mode 100644 index 000000000..56d69db05 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go @@ -0,0 +1,36 @@ +// Package query provides serialisation of AWS query requests, and responses. +package query + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/query.json build_test.go + +import ( + "net/url" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query/queryutil" +) + +// BuildHandler is a named request handler for building query protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.query.Build", Fn: Build} + +// Build builds a request for an AWS Query service. +func Build(r *request.Request) { + body := url.Values{ + "Action": {r.Operation.Name}, + "Version": {r.ClientInfo.APIVersion}, + } + if err := queryutil.Parse(body, r.Params, false); err != nil { + r.Error = awserr.New("SerializationError", "failed encoding Query request", err) + return + } + + if r.ExpireTime == 0 { + r.HTTPRequest.Method = "POST" + r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") + r.SetBufferBody([]byte(body.Encode())) + } else { // This is a pre-signed request + r.HTTPRequest.Method = "GET" + r.HTTPRequest.URL.RawQuery = body.Encode() + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go new file mode 100644 index 000000000..60ea0bd1e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go @@ -0,0 +1,230 @@ +package queryutil + +import ( + "encoding/base64" + "fmt" + "net/url" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/private/protocol" +) + +// Parse parses an object i and fills a url.Values object. The isEC2 flag +// indicates if this is the EC2 Query sub-protocol. +func Parse(body url.Values, i interface{}, isEC2 bool) error { + q := queryParser{isEC2: isEC2} + return q.parseValue(body, reflect.ValueOf(i), "", "") +} + +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} + +type queryParser struct { + isEC2 bool +} + +func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + value = elemOf(value) + + // no need to handle zero values + if !value.IsValid() { + return nil + } + + t := tag.Get("type") + if t == "" { + switch value.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + return q.parseStruct(v, value, prefix) + case "list": + return q.parseList(v, value, prefix, tag) + case "map": + return q.parseMap(v, value, prefix, tag) + default: + return q.parseScalar(v, value, prefix, tag) + } +} + +func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error { + if !value.IsValid() { + return nil + } + + t := value.Type() + for i := 0; i < value.NumField(); i++ { + elemValue := elemOf(value.Field(i)) + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + + if protocol.CanSetIdempotencyToken(value.Field(i), field) { + token := protocol.GetIdempotencyToken() + elemValue = reflect.ValueOf(token) + } + + var name string + if q.isEC2 { + name = field.Tag.Get("queryName") + } + if name == "" { + if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { + name = field.Tag.Get("locationNameList") + } else if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + if name != "" && q.isEC2 { + name = strings.ToUpper(name[0:1]) + name[1:] + } + } + if name == "" { + name = field.Name + } + + if prefix != "" { + name = prefix + "." + name + } + + if err := q.parseValue(v, elemValue, name, field.Tag); err != nil { + return err + } + } + return nil +} + +func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + // If it's empty, generate an empty value + if !value.IsNil() && value.Len() == 0 { + v.Set(prefix, "") + return nil + } + + // check for unflattened list member + if !q.isEC2 && tag.Get("flattened") == "" { + prefix += ".member" + } + + for i := 0; i < value.Len(); i++ { + slicePrefix := prefix + if slicePrefix == "" { + slicePrefix = strconv.Itoa(i + 1) + } else { + slicePrefix = slicePrefix + "." + strconv.Itoa(i+1) + } + if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil { + return err + } + } + return nil +} + +func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + // If it's empty, generate an empty value + if !value.IsNil() && value.Len() == 0 { + v.Set(prefix, "") + return nil + } + + // check for unflattened list member + if !q.isEC2 && tag.Get("flattened") == "" { + prefix += ".entry" + } + + // sort keys for improved serialization consistency. + // this is not strictly necessary for protocol support. + mapKeyValues := value.MapKeys() + mapKeys := map[string]reflect.Value{} + mapKeyNames := make([]string, len(mapKeyValues)) + for i, mapKey := range mapKeyValues { + name := mapKey.String() + mapKeys[name] = mapKey + mapKeyNames[i] = name + } + sort.Strings(mapKeyNames) + + for i, mapKeyName := range mapKeyNames { + mapKey := mapKeys[mapKeyName] + mapValue := value.MapIndex(mapKey) + + kname := tag.Get("locationNameKey") + if kname == "" { + kname = "key" + } + vname := tag.Get("locationNameValue") + if vname == "" { + vname = "value" + } + + // serialize key + var keyName string + if prefix == "" { + keyName = strconv.Itoa(i+1) + "." + kname + } else { + keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname + } + + if err := q.parseValue(v, mapKey, keyName, ""); err != nil { + return err + } + + // serialize value + var valueName string + if prefix == "" { + valueName = strconv.Itoa(i+1) + "." + vname + } else { + valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname + } + + if err := q.parseValue(v, mapValue, valueName, ""); err != nil { + return err + } + } + + return nil +} + +func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error { + switch value := r.Interface().(type) { + case string: + v.Set(name, value) + case []byte: + if !r.IsNil() { + v.Set(name, base64.StdEncoding.EncodeToString(value)) + } + case bool: + v.Set(name, strconv.FormatBool(value)) + case int64: + v.Set(name, strconv.FormatInt(value, 10)) + case int: + v.Set(name, strconv.Itoa(value)) + case float64: + v.Set(name, strconv.FormatFloat(value, 'f', -1, 64)) + case float32: + v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32)) + case time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + v.Set(name, value.UTC().Format(ISO8601UTC)) + default: + return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name()) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go new file mode 100644 index 000000000..a3ea40955 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go @@ -0,0 +1,35 @@ +package query + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/query.json unmarshal_test.go + +import ( + "encoding/xml" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" +) + +// UnmarshalHandler is a named request handler for unmarshaling query protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.query.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling query protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalMeta", Fn: UnmarshalMeta} + +// Unmarshal unmarshals a response for an AWS Query service. +func Unmarshal(r *request.Request) { + defer r.HTTPResponse.Body.Close() + if r.DataFilled() { + decoder := xml.NewDecoder(r.HTTPResponse.Body) + err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result") + if err != nil { + r.Error = awserr.New("SerializationError", "failed decoding Query response", err) + return + } + } +} + +// UnmarshalMeta unmarshals header response values for an AWS Query service. +func UnmarshalMeta(r *request.Request) { + r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid") +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go new file mode 100644 index 000000000..b8e3c7a31 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go @@ -0,0 +1,40 @@ +package query + +import ( + "encoding/xml" + "io" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +type xmlErrorResponse struct { + XMLName xml.Name `xml:"ErrorResponse"` + Code string `xml:"Error>Code"` + Message string `xml:"Error>Message"` + RequestID string `xml:"RequestId"` +} + +// UnmarshalErrorHandler is a name request handler to unmarshal request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalError", Fn: UnmarshalError} + +// UnmarshalError unmarshals an error response for an AWS Query service. +func UnmarshalError(r *request.Request) { + defer r.HTTPResponse.Body.Close() + + resp := &xmlErrorResponse{} + err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) + if err != nil && err != io.EOF { + r.Error = awserr.New("SerializationError", "failed to decode query XML error response", err) + } else { + reqID := resp.RequestID + if reqID == "" { + reqID = r.RequestID + } + r.Error = awserr.NewRequestFailure( + awserr.New(resp.Code, resp.Message, nil), + r.HTTPResponse.StatusCode, + reqID, + ) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go new file mode 100644 index 000000000..5469edb60 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go @@ -0,0 +1,257 @@ +// Package rest provides RESTful serialization of AWS requests and responses. +package rest + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "net/http" + "net/url" + "path" + "reflect" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +// RFC822 returns an RFC822 formatted timestamp for AWS protocols +const RFC822 = "Mon, 2 Jan 2006 15:04:05 GMT" + +// Whether the byte value can be sent without escaping in AWS URLs +var noEscape [256]bool + +var errValueNotSet = fmt.Errorf("value not set") + +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 == '~' + } +} + +// BuildHandler is a named request handler for building rest protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.rest.Build", Fn: Build} + +// Build builds the REST component of a service request. +func Build(r *request.Request) { + if r.ParamsFilled() { + v := reflect.ValueOf(r.Params).Elem() + buildLocationElements(r, v) + buildBody(r, v) + } +} + +func buildLocationElements(r *request.Request, v reflect.Value) { + query := r.HTTPRequest.URL.Query() + + for i := 0; i < v.NumField(); i++ { + m := v.Field(i) + if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) { + continue + } + + if m.IsValid() { + field := v.Type().Field(i) + name := field.Tag.Get("locationName") + if name == "" { + name = field.Name + } + if m.Kind() == reflect.Ptr { + m = m.Elem() + } + if !m.IsValid() { + continue + } + + var err error + switch field.Tag.Get("location") { + case "headers": // header maps + err = buildHeaderMap(&r.HTTPRequest.Header, m, field.Tag.Get("locationName")) + case "header": + err = buildHeader(&r.HTTPRequest.Header, m, name) + case "uri": + err = buildURI(r.HTTPRequest.URL, m, name) + case "querystring": + err = buildQueryString(query, m, name) + } + r.Error = err + } + if r.Error != nil { + return + } + } + + r.HTTPRequest.URL.RawQuery = query.Encode() + updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path) +} + +func buildBody(r *request.Request, v reflect.Value) { + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + pfield, _ := v.Type().FieldByName(payloadName) + if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { + payload := reflect.Indirect(v.FieldByName(payloadName)) + if payload.IsValid() && payload.Interface() != nil { + switch reader := payload.Interface().(type) { + case io.ReadSeeker: + r.SetReaderBody(reader) + case []byte: + r.SetBufferBody(reader) + case string: + r.SetStringBody(reader) + default: + r.Error = awserr.New("SerializationError", + "failed to encode REST request", + fmt.Errorf("unknown payload type %s", payload.Type())) + } + } + } + } + } +} + +func buildHeader(header *http.Header, v reflect.Value, name string) error { + str, err := convertType(v) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + + header.Add(name, str) + + return nil +} + +func buildHeaderMap(header *http.Header, v reflect.Value, prefix string) error { + for _, key := range v.MapKeys() { + str, err := convertType(v.MapIndex(key)) + if err == errValueNotSet { + continue + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + + } + + header.Add(prefix+key.String(), str) + } + return nil +} + +func buildURI(u *url.URL, v reflect.Value, name string) error { + value, err := convertType(v) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + + uri := u.Path + uri = strings.Replace(uri, "{"+name+"}", EscapePath(value, true), -1) + uri = strings.Replace(uri, "{"+name+"+}", EscapePath(value, false), -1) + u.Path = uri + + return nil +} + +func buildQueryString(query url.Values, v reflect.Value, name string) error { + switch value := v.Interface().(type) { + case []*string: + for _, item := range value { + query.Add(name, *item) + } + case map[string]*string: + for key, item := range value { + query.Add(key, *item) + } + case map[string][]*string: + for key, items := range value { + for _, item := range items { + query.Add(key, *item) + } + } + default: + str, err := convertType(v) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + query.Set(name, str) + } + + return nil +} + +func updatePath(url *url.URL, urlPath string) { + scheme, query := url.Scheme, url.RawQuery + + hasSlash := strings.HasSuffix(urlPath, "/") + + // clean up path + urlPath = path.Clean(urlPath) + if hasSlash && !strings.HasSuffix(urlPath, "/") { + urlPath += "/" + } + + // get formatted URL minus scheme so we can build this into Opaque + url.Scheme, url.Path, url.RawQuery = "", "", "" + s := url.String() + url.Scheme = scheme + url.RawQuery = query + + // build opaque URI + url.Opaque = s + urlPath +} + +// 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 { + buf.WriteByte('%') + buf.WriteString(strings.ToUpper(strconv.FormatUint(uint64(c), 16))) + } + } + return buf.String() +} + +func convertType(v reflect.Value) (string, error) { + v = reflect.Indirect(v) + if !v.IsValid() { + return "", errValueNotSet + } + + var str string + switch value := v.Interface().(type) { + case string: + str = value + case []byte: + str = base64.StdEncoding.EncodeToString(value) + case bool: + str = strconv.FormatBool(value) + case int64: + str = strconv.FormatInt(value, 10) + case float64: + str = strconv.FormatFloat(value, 'f', -1, 64) + case time.Time: + str = value.UTC().Format(RFC822) + default: + err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) + return "", err + } + return str, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go new file mode 100644 index 000000000..4366de2e1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go @@ -0,0 +1,45 @@ +package rest + +import "reflect" + +// PayloadMember returns the payload field member of i if there is one, or nil. +func PayloadMember(i interface{}) interface{} { + if i == nil { + return nil + } + + v := reflect.ValueOf(i).Elem() + if !v.IsValid() { + return nil + } + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + field, _ := v.Type().FieldByName(payloadName) + if field.Tag.Get("type") != "structure" { + return nil + } + + payload := v.FieldByName(payloadName) + if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) { + return payload.Interface() + } + } + } + return nil +} + +// PayloadType returns the type of a payload field member of i if there is one, or "". +func PayloadType(i interface{}) string { + v := reflect.Indirect(reflect.ValueOf(i)) + if !v.IsValid() { + return "" + } + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + if member, ok := v.Type().FieldByName(payloadName); ok { + return member.Tag.Get("type") + } + } + } + return "" +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go new file mode 100644 index 000000000..ba46f5bc9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go @@ -0,0 +1,193 @@ +package rest + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "net/http" + "reflect" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +// UnmarshalHandler is a named request handler for unmarshaling rest protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.rest.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling rest protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.rest.UnmarshalMeta", Fn: UnmarshalMeta} + +// Unmarshal unmarshals the REST component of a response in a REST service. +func Unmarshal(r *request.Request) { + if r.DataFilled() { + v := reflect.Indirect(reflect.ValueOf(r.Data)) + unmarshalBody(r, v) + } +} + +// UnmarshalMeta unmarshals the REST metadata of a response in a REST service +func UnmarshalMeta(r *request.Request) { + r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid") + if r.RequestID == "" { + // Alternative version of request id in the header + r.RequestID = r.HTTPResponse.Header.Get("X-Amz-Request-Id") + } + if r.DataFilled() { + v := reflect.Indirect(reflect.ValueOf(r.Data)) + unmarshalLocationElements(r, v) + } +} + +func unmarshalBody(r *request.Request, v reflect.Value) { + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + pfield, _ := v.Type().FieldByName(payloadName) + if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { + payload := v.FieldByName(payloadName) + if payload.IsValid() { + switch payload.Interface().(type) { + case []byte: + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + } else { + payload.Set(reflect.ValueOf(b)) + } + case *string: + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + } else { + str := string(b) + payload.Set(reflect.ValueOf(&str)) + } + default: + switch payload.Type().String() { + case "io.ReadSeeker": + payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body))) + case "aws.ReadSeekCloser", "io.ReadCloser": + payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) + default: + r.Error = awserr.New("SerializationError", + "failed to decode REST response", + fmt.Errorf("unknown payload type %s", payload.Type())) + } + } + } + } + } + } +} + +func unmarshalLocationElements(r *request.Request, v reflect.Value) { + for i := 0; i < v.NumField(); i++ { + m, field := v.Field(i), v.Type().Field(i) + if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) { + continue + } + + if m.IsValid() { + name := field.Tag.Get("locationName") + if name == "" { + name = field.Name + } + + switch field.Tag.Get("location") { + case "statusCode": + unmarshalStatusCode(m, r.HTTPResponse.StatusCode) + case "header": + err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name)) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + break + } + case "headers": + prefix := field.Tag.Get("locationName") + err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + break + } + } + } + if r.Error != nil { + return + } + } +} + +func unmarshalStatusCode(v reflect.Value, statusCode int) { + if !v.IsValid() { + return + } + + switch v.Interface().(type) { + case *int64: + s := int64(statusCode) + v.Set(reflect.ValueOf(&s)) + } +} + +func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error { + switch r.Interface().(type) { + case map[string]*string: // we only support string map value types + out := map[string]*string{} + for k, v := range headers { + k = http.CanonicalHeaderKey(k) + if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) { + out[k[len(prefix):]] = &v[0] + } + } + r.Set(reflect.ValueOf(out)) + } + return nil +} + +func unmarshalHeader(v reflect.Value, header string) error { + if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) { + return nil + } + + switch v.Interface().(type) { + case *string: + v.Set(reflect.ValueOf(&header)) + case []byte: + b, err := base64.StdEncoding.DecodeString(header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&b)) + case *bool: + b, err := strconv.ParseBool(header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&b)) + case *int64: + i, err := strconv.ParseInt(header, 10, 64) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&i)) + case *float64: + f, err := strconv.ParseFloat(header, 64) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&f)) + case *time.Time: + t, err := time.Parse(RFC822, header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&t)) + default: + err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) + return err + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/restjson.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/restjson.go new file mode 100644 index 000000000..5a0877cb1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/restjson.go @@ -0,0 +1,91 @@ +// Package restjson provides RESTful JSON serialisation of AWS +// requests and responses. +package restjson + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/rest-json.json build_test.go +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/rest-json.json unmarshal_test.go + +import ( + "encoding/json" + "io/ioutil" + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +// BuildHandler is a named request handler for building restjson protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.restjson.Build", Fn: Build} + +// UnmarshalHandler is a named request handler for unmarshaling restjson protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.restjson.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling restjson protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.restjson.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling restjson protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.restjson.UnmarshalError", Fn: UnmarshalError} + +// Build builds a request for the REST JSON protocol. +func Build(r *request.Request) { + rest.Build(r) + + if t := rest.PayloadType(r.Params); t == "structure" || t == "" { + jsonrpc.Build(r) + } +} + +// Unmarshal unmarshals a response body for the REST JSON protocol. +func Unmarshal(r *request.Request) { + if t := rest.PayloadType(r.Data); t == "structure" || t == "" { + jsonrpc.Unmarshal(r) + } else { + rest.Unmarshal(r) + } +} + +// UnmarshalMeta unmarshals response headers for the REST JSON protocol. +func UnmarshalMeta(r *request.Request) { + rest.UnmarshalMeta(r) +} + +// UnmarshalError unmarshals a response error for the REST JSON protocol. +func UnmarshalError(r *request.Request) { + code := r.HTTPResponse.Header.Get("X-Amzn-Errortype") + bodyBytes, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed reading REST JSON error response", err) + return + } + if len(bodyBytes) == 0 { + r.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", r.HTTPResponse.Status, nil), + r.HTTPResponse.StatusCode, + "", + ) + return + } + var jsonErr jsonErrorResponse + if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { + r.Error = awserr.New("SerializationError", "failed decoding REST JSON error response", err) + return + } + + if code == "" { + code = jsonErr.Code + } + + code = strings.SplitN(code, ":", 2)[0] + r.Error = awserr.NewRequestFailure( + awserr.New(code, jsonErr.Message, nil), + r.HTTPResponse.StatusCode, + r.RequestID, + ) +} + +type jsonErrorResponse struct { + Code string `json:"code"` + Message string `json:"message"` +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/restxml/restxml.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/restxml/restxml.go new file mode 100644 index 000000000..c74088bfe --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/restxml/restxml.go @@ -0,0 +1,69 @@ +// Package restxml provides RESTful XML serialisation of AWS +// requests and responses. +package restxml + +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/rest-xml.json build_test.go +//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/rest-xml.json unmarshal_test.go + +import ( + "bytes" + "encoding/xml" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/protocol/rest" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" +) + +// BuildHandler is a named request handler for building restxml protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.restxml.Build", Fn: Build} + +// UnmarshalHandler is a named request handler for unmarshaling restxml protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.restxml.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling restxml protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.restxml.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling restxml protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.restxml.UnmarshalError", Fn: UnmarshalError} + +// Build builds a request payload for the REST XML protocol. +func Build(r *request.Request) { + rest.Build(r) + + if t := rest.PayloadType(r.Params); t == "structure" || t == "" { + var buf bytes.Buffer + err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf)) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to encode rest XML request", err) + return + } + r.SetBufferBody(buf.Bytes()) + } +} + +// Unmarshal unmarshals a payload response for the REST XML protocol. +func Unmarshal(r *request.Request) { + if t := rest.PayloadType(r.Data); t == "structure" || t == "" { + defer r.HTTPResponse.Body.Close() + decoder := xml.NewDecoder(r.HTTPResponse.Body) + err := xmlutil.UnmarshalXML(r.Data, decoder, "") + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST XML response", err) + return + } + } else { + rest.Unmarshal(r) + } +} + +// UnmarshalMeta unmarshals response headers for the REST XML protocol. +func UnmarshalMeta(r *request.Request) { + rest.UnmarshalMeta(r) +} + +// UnmarshalError unmarshals a response error for the REST XML protocol. +func UnmarshalError(r *request.Request) { + query.UnmarshalError(r) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go new file mode 100644 index 000000000..da1a68111 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go @@ -0,0 +1,21 @@ +package protocol + +import ( + "io" + "io/ioutil" + + "github.com/aws/aws-sdk-go/aws/request" +) + +// UnmarshalDiscardBodyHandler is a named request handler to empty and close a response's body +var UnmarshalDiscardBodyHandler = request.NamedHandler{Name: "awssdk.shared.UnmarshalDiscardBody", Fn: UnmarshalDiscardBody} + +// UnmarshalDiscardBody is a request handler to empty a response's body and closing it. +func UnmarshalDiscardBody(r *request.Request) { + if r.HTTPResponse == nil || r.HTTPResponse.Body == nil { + return + } + + io.Copy(ioutil.Discard, r.HTTPResponse.Body) + r.HTTPResponse.Body.Close() +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go new file mode 100644 index 000000000..ceb4132c5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go @@ -0,0 +1,293 @@ +// Package xmlutil provides XML serialisation of AWS requests and responses. +package xmlutil + +import ( + "encoding/base64" + "encoding/xml" + "fmt" + "reflect" + "sort" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/private/protocol" +) + +// BuildXML will serialize params into an xml.Encoder. +// Error will be returned if the serialization of any of the params or nested values fails. +func BuildXML(params interface{}, e *xml.Encoder) error { + b := xmlBuilder{encoder: e, namespaces: map[string]string{}} + root := NewXMLElement(xml.Name{}) + if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil { + return err + } + for _, c := range root.Children { + for _, v := range c { + return StructToXML(e, v, false) + } + } + return nil +} + +// Returns the reflection element of a value, if it is a pointer. +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} + +// A xmlBuilder serializes values from Go code to XML +type xmlBuilder struct { + encoder *xml.Encoder + namespaces map[string]string +} + +// buildValue generic XMLNode builder for any type. Will build value for their specific type +// struct, list, map, scalar. +// +// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If +// type is not provided reflect will be used to determine the value's type. +func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + value = elemOf(value) + if !value.IsValid() { // no need to handle zero values + return nil + } else if tag.Get("location") != "" { // don't handle non-body location values + return nil + } + + t := tag.Get("type") + if t == "" { + switch value.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := value.Type().FieldByName("_"); ok { + tag = tag + reflect.StructTag(" ") + field.Tag + } + return b.buildStruct(value, current, tag) + case "list": + return b.buildList(value, current, tag) + case "map": + return b.buildMap(value, current, tag) + default: + return b.buildScalar(value, current, tag) + } +} + +// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested +// types are converted to XMLNodes also. +func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + fieldAdded := false + + // unwrap payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := value.Type().FieldByName(payload) + tag = field.Tag + value = elemOf(value.FieldByName(payload)) + + if !value.IsValid() { + return nil + } + } + + child := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) + + // there is an xmlNamespace associated with this struct + if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" { + ns := xml.Attr{ + Name: xml.Name{Local: "xmlns"}, + Value: uri, + } + if prefix != "" { + b.namespaces[prefix] = uri // register the namespace + ns.Name.Local = "xmlns:" + prefix + } + + child.Attr = append(child.Attr, ns) + } + + t := value.Type() + for i := 0; i < value.NumField(); i++ { + member := elemOf(value.Field(i)) + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + + mTag := field.Tag + if mTag.Get("location") != "" { // skip non-body members + continue + } + + if protocol.CanSetIdempotencyToken(value.Field(i), field) { + token := protocol.GetIdempotencyToken() + member = reflect.ValueOf(token) + } + + memberName := mTag.Get("locationName") + if memberName == "" { + memberName = field.Name + mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`) + } + if err := b.buildValue(member, child, mTag); err != nil { + return err + } + + fieldAdded = true + } + + if fieldAdded { // only append this child if we have one ore more valid members + current.AddChild(child) + } + + return nil +} + +// buildList adds the value's list items to the current XMLNode as children nodes. All +// nested values in the list are converted to XMLNodes also. +func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if value.IsNil() { // don't build omitted lists + return nil + } + + // check for unflattened list member + flattened := tag.Get("flattened") != "" + + xname := xml.Name{Local: tag.Get("locationName")} + if flattened { + for i := 0; i < value.Len(); i++ { + child := NewXMLElement(xname) + current.AddChild(child) + if err := b.buildValue(value.Index(i), child, ""); err != nil { + return err + } + } + } else { + list := NewXMLElement(xname) + current.AddChild(list) + + for i := 0; i < value.Len(); i++ { + iname := tag.Get("locationNameList") + if iname == "" { + iname = "member" + } + + child := NewXMLElement(xml.Name{Local: iname}) + list.AddChild(child) + if err := b.buildValue(value.Index(i), child, ""); err != nil { + return err + } + } + } + + return nil +} + +// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All +// nested values in the map are converted to XMLNodes also. +// +// Error will be returned if it is unable to build the map's values into XMLNodes +func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if value.IsNil() { // don't build omitted maps + return nil + } + + maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) + current.AddChild(maproot) + current = maproot + + kname, vname := "key", "value" + if n := tag.Get("locationNameKey"); n != "" { + kname = n + } + if n := tag.Get("locationNameValue"); n != "" { + vname = n + } + + // sorting is not required for compliance, but it makes testing easier + keys := make([]string, value.Len()) + for i, k := range value.MapKeys() { + keys[i] = k.String() + } + sort.Strings(keys) + + for _, k := range keys { + v := value.MapIndex(reflect.ValueOf(k)) + + mapcur := current + if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps + child := NewXMLElement(xml.Name{Local: "entry"}) + mapcur.AddChild(child) + mapcur = child + } + + kchild := NewXMLElement(xml.Name{Local: kname}) + kchild.Text = k + vchild := NewXMLElement(xml.Name{Local: vname}) + mapcur.AddChild(kchild) + mapcur.AddChild(vchild) + + if err := b.buildValue(v, vchild, ""); err != nil { + return err + } + } + + return nil +} + +// buildScalar will convert the value into a string and append it as a attribute or child +// of the current XMLNode. +// +// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value. +// +// Error will be returned if the value type is unsupported. +func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + var str string + switch converted := value.Interface().(type) { + case string: + str = converted + case []byte: + if !value.IsNil() { + str = base64.StdEncoding.EncodeToString(converted) + } + case bool: + str = strconv.FormatBool(converted) + case int64: + str = strconv.FormatInt(converted, 10) + case int: + str = strconv.Itoa(converted) + case float64: + str = strconv.FormatFloat(converted, 'f', -1, 64) + case float32: + str = strconv.FormatFloat(float64(converted), 'f', -1, 32) + case time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + str = converted.UTC().Format(ISO8601UTC) + default: + return fmt.Errorf("unsupported value for param %s: %v (%s)", + tag.Get("locationName"), value.Interface(), value.Type().Name()) + } + + xname := xml.Name{Local: tag.Get("locationName")} + if tag.Get("xmlAttribute") != "" { // put into current node's attribute list + attr := xml.Attr{Name: xname, Value: str} + current.Attr = append(current.Attr, attr) + } else { // regular text node + current.AddChild(&XMLNode{Name: xname, Text: str}) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go new file mode 100644 index 000000000..49f291a85 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go @@ -0,0 +1,260 @@ +package xmlutil + +import ( + "encoding/base64" + "encoding/xml" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" +) + +// UnmarshalXML deserializes an xml.Decoder into the container v. V +// needs to match the shape of the XML expected to be decoded. +// If the shape doesn't match unmarshaling will fail. +func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error { + n, _ := XMLToStruct(d, nil) + if n.Children != nil { + for _, root := range n.Children { + for _, c := range root { + if wrappedChild, ok := c.Children[wrapper]; ok { + c = wrappedChild[0] // pull out wrapped element + } + + err := parse(reflect.ValueOf(v), c, "") + if err != nil { + if err == io.EOF { + return nil + } + return err + } + } + } + return nil + } + return nil +} + +// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect +// will be used to determine the type from r. +func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + rtype := r.Type() + if rtype.Kind() == reflect.Ptr { + rtype = rtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch rtype.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := rtype.FieldByName("_"); ok { + tag = field.Tag + } + return parseStruct(r, node, tag) + case "list": + return parseList(r, node, tag) + case "map": + return parseMap(r, node, tag) + default: + return parseScalar(r, node, tag) + } +} + +// parseStruct deserializes a structure and its fields from an XMLNode. Any nested +// types in the structure will also be deserialized. +func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + t := r.Type() + if r.Kind() == reflect.Ptr { + if r.IsNil() { // create the structure if it's nil + s := reflect.New(r.Type().Elem()) + r.Set(s) + r = s + } + + r = r.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return parseStruct(r.FieldByName(payload), node, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if c := field.Name[0:1]; strings.ToLower(c) == c { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { + name = field.Tag.Get("locationNameList") + } else if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + // try to find the field by name in elements + elems := node.Children[name] + + if elems == nil { // try to find the field in attributes + for _, a := range node.Attr { + if name == a.Name.Local { + // turn this into a text node for de-serializing + elems = []*XMLNode{{Text: a.Value}} + } + } + } + + member := r.FieldByName(field.Name) + for _, elem := range elems { + err := parse(member, elem, field.Tag) + if err != nil { + return err + } + } + } + return nil +} + +// parseList deserializes a list of values from an XML node. Each list entry +// will also be deserialized. +func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + t := r.Type() + + if tag.Get("flattened") == "" { // look at all item entries + mname := "member" + if name := tag.Get("locationNameList"); name != "" { + mname = name + } + + if Children, ok := node.Children[mname]; ok { + if r.IsNil() { + r.Set(reflect.MakeSlice(t, len(Children), len(Children))) + } + + for i, c := range Children { + err := parse(r.Index(i), c, "") + if err != nil { + return err + } + } + } + } else { // flattened list means this is a single element + if r.IsNil() { + r.Set(reflect.MakeSlice(t, 0, 0)) + } + + childR := reflect.Zero(t.Elem()) + r.Set(reflect.Append(r, childR)) + err := parse(r.Index(r.Len()-1), node, "") + if err != nil { + return err + } + } + + return nil +} + +// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode +// will also be deserialized as map entries. +func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + if r.IsNil() { + r.Set(reflect.MakeMap(r.Type())) + } + + if tag.Get("flattened") == "" { // look at all child entries + for _, entry := range node.Children["entry"] { + parseMapEntry(r, entry, tag) + } + } else { // this element is itself an entry + parseMapEntry(r, node, tag) + } + + return nil +} + +// parseMapEntry deserializes a map entry from a XML node. +func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + kname, vname := "key", "value" + if n := tag.Get("locationNameKey"); n != "" { + kname = n + } + if n := tag.Get("locationNameValue"); n != "" { + vname = n + } + + keys, ok := node.Children[kname] + values := node.Children[vname] + if ok { + for i, key := range keys { + keyR := reflect.ValueOf(key.Text) + value := values[i] + valueR := reflect.New(r.Type().Elem()).Elem() + + parse(valueR, value, "") + r.SetMapIndex(keyR, valueR) + } + } + return nil +} + +// parseScaller deserializes an XMLNode value into a concrete type based on the +// interface type of r. +// +// Error is returned if the deserialization fails due to invalid type conversion, +// or unsupported interface type. +func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + switch r.Interface().(type) { + case *string: + r.Set(reflect.ValueOf(&node.Text)) + return nil + case []byte: + b, err := base64.StdEncoding.DecodeString(node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(b)) + case *bool: + v, err := strconv.ParseBool(node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *int64: + v, err := strconv.ParseInt(node.Text, 10, 64) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *float64: + v, err := strconv.ParseFloat(node.Text, 64) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + t, err := time.Parse(ISO8601UTC, node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&t)) + default: + return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type()) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go new file mode 100644 index 000000000..72c198a9d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go @@ -0,0 +1,105 @@ +package xmlutil + +import ( + "encoding/xml" + "io" + "sort" +) + +// A XMLNode contains the values to be encoded or decoded. +type XMLNode struct { + Name xml.Name `json:",omitempty"` + Children map[string][]*XMLNode `json:",omitempty"` + Text string `json:",omitempty"` + Attr []xml.Attr `json:",omitempty"` +} + +// NewXMLElement returns a pointer to a new XMLNode initialized to default values. +func NewXMLElement(name xml.Name) *XMLNode { + return &XMLNode{ + Name: name, + Children: map[string][]*XMLNode{}, + Attr: []xml.Attr{}, + } +} + +// AddChild adds child to the XMLNode. +func (n *XMLNode) AddChild(child *XMLNode) { + if _, ok := n.Children[child.Name.Local]; !ok { + n.Children[child.Name.Local] = []*XMLNode{} + } + n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child) +} + +// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values. +func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) { + out := &XMLNode{} + for { + tok, err := d.Token() + if tok == nil || err == io.EOF { + break + } + if err != nil { + return out, err + } + + switch typed := tok.(type) { + case xml.CharData: + out.Text = string(typed.Copy()) + case xml.StartElement: + el := typed.Copy() + out.Attr = el.Attr + if out.Children == nil { + out.Children = map[string][]*XMLNode{} + } + + name := typed.Name.Local + slice := out.Children[name] + if slice == nil { + slice = []*XMLNode{} + } + node, e := XMLToStruct(d, &el) + if e != nil { + return out, e + } + node.Name = typed.Name + slice = append(slice, node) + out.Children[name] = slice + case xml.EndElement: + if s != nil && s.Name.Local == typed.Name.Local { // matching end token + return out, nil + } + } + } + return out, nil +} + +// StructToXML writes an XMLNode to a xml.Encoder as tokens. +func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error { + e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr}) + + if node.Text != "" { + e.EncodeToken(xml.CharData([]byte(node.Text))) + } else if sorted { + sortedNames := []string{} + for k := range node.Children { + sortedNames = append(sortedNames, k) + } + sort.Strings(sortedNames) + + for _, k := range sortedNames { + for _, v := range node.Children[k] { + StructToXML(e, v, sorted) + } + } + } else { + for _, c := range node.Children { + for _, v := range c { + StructToXML(e, v, sorted) + } + } + } + + e.EncodeToken(xml.EndElement{Name: node.Name}) + return e.Flush() +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/signer/v4/header_rules.go b/vendor/github.com/aws/aws-sdk-go/private/signer/v4/header_rules.go new file mode 100644 index 000000000..244c86da0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/signer/v4/header_rules.go @@ -0,0 +1,82 @@ +package v4 + +import ( + "net/http" + "strings" +) + +// validator houses a set of rule needed for validation of a +// string value +type rules []rule + +// rule interface allows for more flexible rules and just simply +// checks whether or not a value adheres to that rule +type rule interface { + IsValid(value string) bool +} + +// IsValid will iterate through all rules and see if any rules +// apply to the value and supports nested rules +func (r rules) IsValid(value string) bool { + for _, rule := range r { + if rule.IsValid(value) { + return true + } + } + return false +} + +// mapRule generic rule for maps +type mapRule map[string]struct{} + +// IsValid for the map rule satisfies whether it exists in the map +func (m mapRule) IsValid(value string) bool { + _, ok := m[value] + return ok +} + +// whitelist is a generic rule for whitelisting +type whitelist struct { + rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (w whitelist) IsValid(value string) bool { + return w.rule.IsValid(value) +} + +// blacklist is a generic rule for blacklisting +type blacklist struct { + rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (b blacklist) IsValid(value string) bool { + return !b.rule.IsValid(value) +} + +type patterns []string + +// IsValid for patterns checks each pattern and returns if a match has +// been found +func (p patterns) IsValid(value string) bool { + for _, pattern := range p { + if strings.HasPrefix(http.CanonicalHeaderKey(value), pattern) { + return true + } + } + return false +} + +// inclusiveRules rules allow for rules to depend on one another +type inclusiveRules []rule + +// IsValid will return true if all rules are true +func (r inclusiveRules) IsValid(value string) bool { + for _, rule := range r { + if !rule.IsValid(value) { + return false + } + } + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/signer/v4/v4.go b/vendor/github.com/aws/aws-sdk-go/private/signer/v4/v4.go new file mode 100644 index 000000000..14b0c6616 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/signer/v4/v4.go @@ -0,0 +1,438 @@ +// Package v4 implements signing for AWS V4 signer +package v4 + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +const ( + authHeaderPrefix = "AWS4-HMAC-SHA256" + timeFormat = "20060102T150405Z" + shortTimeFormat = "20060102" +) + +var ignoredHeaders = rules{ + blacklist{ + mapRule{ + "Content-Length": struct{}{}, + "User-Agent": struct{}{}, + }, + }, +} + +// requiredSignedHeaders is a whitelist for build canonical headers. +var requiredSignedHeaders = rules{ + whitelist{ + mapRule{ + "Cache-Control": struct{}{}, + "Content-Disposition": struct{}{}, + "Content-Encoding": struct{}{}, + "Content-Language": struct{}{}, + "Content-Md5": struct{}{}, + "Content-Type": struct{}{}, + "Expires": struct{}{}, + "If-Match": struct{}{}, + "If-Modified-Since": struct{}{}, + "If-None-Match": struct{}{}, + "If-Unmodified-Since": struct{}{}, + "Range": struct{}{}, + "X-Amz-Acl": struct{}{}, + "X-Amz-Copy-Source": struct{}{}, + "X-Amz-Copy-Source-If-Match": struct{}{}, + "X-Amz-Copy-Source-If-Modified-Since": struct{}{}, + "X-Amz-Copy-Source-If-None-Match": struct{}{}, + "X-Amz-Copy-Source-If-Unmodified-Since": struct{}{}, + "X-Amz-Copy-Source-Range": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": struct{}{}, + "X-Amz-Grant-Full-control": struct{}{}, + "X-Amz-Grant-Read": struct{}{}, + "X-Amz-Grant-Read-Acp": struct{}{}, + "X-Amz-Grant-Write": struct{}{}, + "X-Amz-Grant-Write-Acp": struct{}{}, + "X-Amz-Metadata-Directive": struct{}{}, + "X-Amz-Mfa": struct{}{}, + "X-Amz-Request-Payer": struct{}{}, + "X-Amz-Server-Side-Encryption": struct{}{}, + "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Algorithm": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Key": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Key-Md5": struct{}{}, + "X-Amz-Storage-Class": struct{}{}, + "X-Amz-Website-Redirect-Location": struct{}{}, + }, + }, + patterns{"X-Amz-Meta-"}, +} + +// allowedHoisting is a whitelist for build query headers. The boolean value +// represents whether or not it is a pattern. +var allowedQueryHoisting = inclusiveRules{ + blacklist{requiredSignedHeaders}, + patterns{"X-Amz-"}, +} + +type signer struct { + Request *http.Request + Time time.Time + ExpireTime time.Duration + ServiceName string + Region string + CredValues credentials.Value + Credentials *credentials.Credentials + Query url.Values + Body io.ReadSeeker + Debug aws.LogLevelType + Logger aws.Logger + + isPresign bool + formattedTime string + formattedShortTime string + + signedHeaders string + canonicalHeaders string + canonicalString string + credentialString string + stringToSign string + signature string + authorization string + notHoist bool + signedHeaderVals http.Header +} + +// Sign requests with signature version 4. +// +// Will sign the requests with the service config's Credentials object +// Signing is skipped if the credentials is the credentials.AnonymousCredentials +// object. +func Sign(req *request.Request) { + // If the request does not need to be signed ignore the signing of the + // request if the AnonymousCredentials object is used. + if req.Config.Credentials == credentials.AnonymousCredentials { + return + } + + region := req.ClientInfo.SigningRegion + if region == "" { + region = aws.StringValue(req.Config.Region) + } + + name := req.ClientInfo.SigningName + if name == "" { + name = req.ClientInfo.ServiceName + } + + s := signer{ + Request: req.HTTPRequest, + Time: req.Time, + ExpireTime: req.ExpireTime, + Query: req.HTTPRequest.URL.Query(), + Body: req.Body, + ServiceName: name, + Region: region, + Credentials: req.Config.Credentials, + Debug: req.Config.LogLevel.Value(), + Logger: req.Config.Logger, + notHoist: req.NotHoist, + } + + req.Error = s.sign() + req.SignedHeaderVals = s.signedHeaderVals +} + +func (v4 *signer) sign() error { + if v4.ExpireTime != 0 { + v4.isPresign = true + } + + if v4.isRequestSigned() { + if !v4.Credentials.IsExpired() { + // If the request is already signed, and the credentials have not + // expired yet ignore the signing request. + return nil + } + + // The credentials have expired for this request. The current signing + // is invalid, and needs to be request because the request will fail. + if v4.isPresign { + v4.removePresign() + // Update the request's query string to ensure the values stays in + // sync in the case retrieving the new credentials fails. + v4.Request.URL.RawQuery = v4.Query.Encode() + } + } + + var err error + v4.CredValues, err = v4.Credentials.Get() + if err != nil { + return err + } + + if v4.isPresign { + v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix) + if v4.CredValues.SessionToken != "" { + v4.Query.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) + } else { + v4.Query.Del("X-Amz-Security-Token") + } + } else if v4.CredValues.SessionToken != "" { + v4.Request.Header.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) + } + + v4.build() + + if v4.Debug.Matches(aws.LogDebugWithSigning) { + v4.logSigningInfo() + } + + return nil +} + +const logSignInfoMsg = `DEBUG: Request Signiture: +---[ CANONICAL STRING ]----------------------------- +%s +---[ STRING TO SIGN ]-------------------------------- +%s%s +-----------------------------------------------------` +const logSignedURLMsg = ` +---[ SIGNED URL ]------------------------------------ +%s` + +func (v4 *signer) logSigningInfo() { + signedURLMsg := "" + if v4.isPresign { + signedURLMsg = fmt.Sprintf(logSignedURLMsg, v4.Request.URL.String()) + } + msg := fmt.Sprintf(logSignInfoMsg, v4.canonicalString, v4.stringToSign, signedURLMsg) + v4.Logger.Log(msg) +} + +func (v4 *signer) build() { + + v4.buildTime() // no depends + v4.buildCredentialString() // no depends + + unsignedHeaders := v4.Request.Header + if v4.isPresign { + if !v4.notHoist { + urlValues := url.Values{} + urlValues, unsignedHeaders = buildQuery(allowedQueryHoisting, unsignedHeaders) // no depends + for k := range urlValues { + v4.Query[k] = urlValues[k] + } + } + } + + v4.buildCanonicalHeaders(ignoredHeaders, unsignedHeaders) + v4.buildCanonicalString() // depends on canon headers / signed headers + v4.buildStringToSign() // depends on canon string + v4.buildSignature() // depends on string to sign + + if v4.isPresign { + v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature + } else { + parts := []string{ + authHeaderPrefix + " Credential=" + v4.CredValues.AccessKeyID + "/" + v4.credentialString, + "SignedHeaders=" + v4.signedHeaders, + "Signature=" + v4.signature, + } + v4.Request.Header.Set("Authorization", strings.Join(parts, ", ")) + } +} + +func (v4 *signer) buildTime() { + v4.formattedTime = v4.Time.UTC().Format(timeFormat) + v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat) + + if v4.isPresign { + duration := int64(v4.ExpireTime / time.Second) + v4.Query.Set("X-Amz-Date", v4.formattedTime) + v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) + } else { + v4.Request.Header.Set("X-Amz-Date", v4.formattedTime) + } +} + +func (v4 *signer) buildCredentialString() { + v4.credentialString = strings.Join([]string{ + v4.formattedShortTime, + v4.Region, + v4.ServiceName, + "aws4_request", + }, "/") + + if v4.isPresign { + v4.Query.Set("X-Amz-Credential", v4.CredValues.AccessKeyID+"/"+v4.credentialString) + } +} + +func buildQuery(r rule, header http.Header) (url.Values, http.Header) { + query := url.Values{} + unsignedHeaders := http.Header{} + for k, h := range header { + if r.IsValid(k) { + query[k] = h + } else { + unsignedHeaders[k] = h + } + } + + return query, unsignedHeaders +} +func (v4 *signer) buildCanonicalHeaders(r rule, header http.Header) { + var headers []string + headers = append(headers, "host") + for k, v := range header { + canonicalKey := http.CanonicalHeaderKey(k) + if !r.IsValid(canonicalKey) { + continue // ignored header + } + + lowerCaseKey := strings.ToLower(k) + headers = append(headers, lowerCaseKey) + + if v4.signedHeaderVals == nil { + v4.signedHeaderVals = make(http.Header) + } + v4.signedHeaderVals[lowerCaseKey] = v + } + sort.Strings(headers) + + v4.signedHeaders = strings.Join(headers, ";") + + if v4.isPresign { + v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders) + } + + headerValues := make([]string, len(headers)) + for i, k := range headers { + if k == "host" { + headerValues[i] = "host:" + v4.Request.URL.Host + } else { + headerValues[i] = k + ":" + + strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",") + } + } + + v4.canonicalHeaders = strings.Join(headerValues, "\n") +} + +func (v4 *signer) buildCanonicalString() { + v4.Request.URL.RawQuery = strings.Replace(v4.Query.Encode(), "+", "%20", -1) + uri := v4.Request.URL.Opaque + if uri != "" { + uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/") + } else { + uri = v4.Request.URL.Path + } + if uri == "" { + uri = "/" + } + + if v4.ServiceName != "s3" { + uri = rest.EscapePath(uri, false) + } + + v4.canonicalString = strings.Join([]string{ + v4.Request.Method, + uri, + v4.Request.URL.RawQuery, + v4.canonicalHeaders + "\n", + v4.signedHeaders, + v4.bodyDigest(), + }, "\n") +} + +func (v4 *signer) buildStringToSign() { + v4.stringToSign = strings.Join([]string{ + authHeaderPrefix, + v4.formattedTime, + v4.credentialString, + hex.EncodeToString(makeSha256([]byte(v4.canonicalString))), + }, "\n") +} + +func (v4 *signer) buildSignature() { + secret := v4.CredValues.SecretAccessKey + date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime)) + region := makeHmac(date, []byte(v4.Region)) + service := makeHmac(region, []byte(v4.ServiceName)) + credentials := makeHmac(service, []byte("aws4_request")) + signature := makeHmac(credentials, []byte(v4.stringToSign)) + v4.signature = hex.EncodeToString(signature) +} + +func (v4 *signer) bodyDigest() string { + hash := v4.Request.Header.Get("X-Amz-Content-Sha256") + if hash == "" { + if v4.isPresign && v4.ServiceName == "s3" { + hash = "UNSIGNED-PAYLOAD" + } else if v4.Body == nil { + hash = hex.EncodeToString(makeSha256([]byte{})) + } else { + hash = hex.EncodeToString(makeSha256Reader(v4.Body)) + } + v4.Request.Header.Add("X-Amz-Content-Sha256", hash) + } + return hash +} + +// isRequestSigned returns if the request is currently signed or presigned +func (v4 *signer) isRequestSigned() bool { + if v4.isPresign && v4.Query.Get("X-Amz-Signature") != "" { + return true + } + if v4.Request.Header.Get("Authorization") != "" { + return true + } + + return false +} + +// unsign removes signing flags for both signed and presigned requests. +func (v4 *signer) removePresign() { + v4.Query.Del("X-Amz-Algorithm") + v4.Query.Del("X-Amz-Signature") + v4.Query.Del("X-Amz-Security-Token") + v4.Query.Del("X-Amz-Date") + v4.Query.Del("X-Amz-Expires") + v4.Query.Del("X-Amz-Credential") + v4.Query.Del("X-Amz-SignedHeaders") +} + +func makeHmac(key []byte, data []byte) []byte { + hash := hmac.New(sha256.New, key) + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256(data []byte) []byte { + hash := sha256.New() + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256Reader(reader io.ReadSeeker) []byte { + hash := sha256.New() + start, _ := reader.Seek(0, 1) + defer reader.Seek(start, 0) + + io.Copy(hash, reader) + return hash.Sum(nil) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/waiter/waiter.go b/vendor/github.com/aws/aws-sdk-go/private/waiter/waiter.go new file mode 100644 index 000000000..b51e9449c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/waiter/waiter.go @@ -0,0 +1,134 @@ +package waiter + +import ( + "fmt" + "reflect" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" +) + +// A Config provides a collection of configuration values to setup a generated +// waiter code with. +type Config struct { + Name string + Delay int + MaxAttempts int + Operation string + Acceptors []WaitAcceptor +} + +// A WaitAcceptor provides the information needed to wait for an API operation +// to complete. +type WaitAcceptor struct { + Expected interface{} + Matcher string + State string + Argument string +} + +// A Waiter provides waiting for an operation to complete. +type Waiter struct { + Config + Client interface{} + Input interface{} +} + +// Wait waits for an operation to complete, expire max attempts, or fail. Error +// is returned if the operation fails. +func (w *Waiter) Wait() error { + client := reflect.ValueOf(w.Client) + in := reflect.ValueOf(w.Input) + method := client.MethodByName(w.Config.Operation + "Request") + + for i := 0; i < w.MaxAttempts; i++ { + res := method.Call([]reflect.Value{in}) + req := res[0].Interface().(*request.Request) + req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter")) + + err := req.Send() + for _, a := range w.Acceptors { + result := false + var vals []interface{} + switch a.Matcher { + case "pathAll", "path": + // Require all matches to be equal for result to match + vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) + if len(vals) == 0 { + break + } + result = true + for _, val := range vals { + if !awsutil.DeepEqual(val, a.Expected) { + result = false + break + } + } + case "pathAny": + // Only a single match needs to equal for the result to match + vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) + for _, val := range vals { + if awsutil.DeepEqual(val, a.Expected) { + result = true + break + } + } + case "status": + s := a.Expected.(int) + result = s == req.HTTPResponse.StatusCode + case "error": + if aerr, ok := err.(awserr.Error); ok { + result = aerr.Code() == a.Expected.(string) + } + case "pathList": + // ignored matcher + default: + logf(client, "WARNING: Waiter for %s encountered unexpected matcher: %s", + w.Config.Operation, a.Matcher) + } + + if !result { + // If there was no matching result found there is nothing more to do + // for this response, retry the request. + continue + } + + switch a.State { + case "success": + // waiter completed + return nil + case "failure": + // Waiter failure state triggered + return awserr.New("ResourceNotReady", + fmt.Sprintf("failed waiting for successful resource state"), err) + case "retry": + // clear the error and retry the operation + err = nil + default: + logf(client, "WARNING: Waiter for %s encountered unexpected state: %s", + w.Config.Operation, a.State) + } + } + if err != nil { + return err + } + + time.Sleep(time.Second * time.Duration(w.Delay)) + } + + return awserr.New("ResourceNotReady", + fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil) +} + +func logf(client reflect.Value, msg string, args ...interface{}) { + cfgVal := client.FieldByName("Config") + if !cfgVal.IsValid() { + return + } + if cfg, ok := cfgVal.Interface().(*aws.Config); ok && cfg.Logger != nil { + cfg.Logger.Log(fmt.Sprintf(msg, args...)) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/ec2/api.go b/vendor/github.com/aws/aws-sdk-go/service/ec2/api.go new file mode 100644 index 000000000..f4c4fb46a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/ec2/api.go @@ -0,0 +1,25097 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package ec2 provides a client for Amazon Elastic Compute Cloud. +package ec2 + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/ec2query" +) + +const opAcceptVpcPeeringConnection = "AcceptVpcPeeringConnection" + +// AcceptVpcPeeringConnectionRequest generates a request for the AcceptVpcPeeringConnection operation. +func (c *EC2) AcceptVpcPeeringConnectionRequest(input *AcceptVpcPeeringConnectionInput) (req *request.Request, output *AcceptVpcPeeringConnectionOutput) { + op := &request.Operation{ + Name: opAcceptVpcPeeringConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AcceptVpcPeeringConnectionInput{} + } + + req = c.newRequest(op, input, output) + output = &AcceptVpcPeeringConnectionOutput{} + req.Data = output + return +} + +// Accept a VPC peering connection request. To accept a request, the VPC peering +// connection must be in the pending-acceptance state, and you must be the owner +// of the peer VPC. Use the DescribeVpcPeeringConnections request to view your +// outstanding VPC peering connection requests. +func (c *EC2) AcceptVpcPeeringConnection(input *AcceptVpcPeeringConnectionInput) (*AcceptVpcPeeringConnectionOutput, error) { + req, out := c.AcceptVpcPeeringConnectionRequest(input) + err := req.Send() + return out, err +} + +const opAllocateAddress = "AllocateAddress" + +// AllocateAddressRequest generates a request for the AllocateAddress operation. +func (c *EC2) AllocateAddressRequest(input *AllocateAddressInput) (req *request.Request, output *AllocateAddressOutput) { + op := &request.Operation{ + Name: opAllocateAddress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AllocateAddressInput{} + } + + req = c.newRequest(op, input, output) + output = &AllocateAddressOutput{} + req.Data = output + return +} + +// Acquires an Elastic IP address. +// +// An Elastic IP address is for use either in the EC2-Classic platform or in +// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) AllocateAddress(input *AllocateAddressInput) (*AllocateAddressOutput, error) { + req, out := c.AllocateAddressRequest(input) + err := req.Send() + return out, err +} + +const opAllocateHosts = "AllocateHosts" + +// AllocateHostsRequest generates a request for the AllocateHosts operation. +func (c *EC2) AllocateHostsRequest(input *AllocateHostsInput) (req *request.Request, output *AllocateHostsOutput) { + op := &request.Operation{ + Name: opAllocateHosts, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AllocateHostsInput{} + } + + req = c.newRequest(op, input, output) + output = &AllocateHostsOutput{} + req.Data = output + return +} + +// Allocates a Dedicated host to your account. At minimum you need to specify +// the instance size type, Availability Zone, and quantity of hosts you want +// to allocate. +func (c *EC2) AllocateHosts(input *AllocateHostsInput) (*AllocateHostsOutput, error) { + req, out := c.AllocateHostsRequest(input) + err := req.Send() + return out, err +} + +const opAssignPrivateIpAddresses = "AssignPrivateIpAddresses" + +// AssignPrivateIpAddressesRequest generates a request for the AssignPrivateIpAddresses operation. +func (c *EC2) AssignPrivateIpAddressesRequest(input *AssignPrivateIpAddressesInput) (req *request.Request, output *AssignPrivateIpAddressesOutput) { + op := &request.Operation{ + Name: opAssignPrivateIpAddresses, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssignPrivateIpAddressesInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &AssignPrivateIpAddressesOutput{} + req.Data = output + return +} + +// Assigns one or more secondary private IP addresses to the specified network +// interface. You can specify one or more specific secondary IP addresses, or +// you can specify the number of secondary IP addresses to be automatically +// assigned within the subnet's CIDR block range. The number of secondary IP +// addresses that you can assign to an instance varies by instance type. For +// information about instance types, see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) +// in the Amazon Elastic Compute Cloud User Guide. For more information about +// Elastic IP addresses, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// AssignPrivateIpAddresses is available only in EC2-VPC. +func (c *EC2) AssignPrivateIpAddresses(input *AssignPrivateIpAddressesInput) (*AssignPrivateIpAddressesOutput, error) { + req, out := c.AssignPrivateIpAddressesRequest(input) + err := req.Send() + return out, err +} + +const opAssociateAddress = "AssociateAddress" + +// AssociateAddressRequest generates a request for the AssociateAddress operation. +func (c *EC2) AssociateAddressRequest(input *AssociateAddressInput) (req *request.Request, output *AssociateAddressOutput) { + op := &request.Operation{ + Name: opAssociateAddress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssociateAddressInput{} + } + + req = c.newRequest(op, input, output) + output = &AssociateAddressOutput{} + req.Data = output + return +} + +// Associates an Elastic IP address with an instance or a network interface. +// +// An Elastic IP address is for use in either the EC2-Classic platform or in +// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// [EC2-Classic, VPC in an EC2-VPC-only account] If the Elastic IP address +// is already associated with a different instance, it is disassociated from +// that instance and associated with the specified instance. +// +// [VPC in an EC2-Classic account] If you don't specify a private IP address, +// the Elastic IP address is associated with the primary IP address. If the +// Elastic IP address is already associated with a different instance or a network +// interface, you get an error unless you allow reassociation. +// +// This is an idempotent operation. If you perform the operation more than +// once, Amazon EC2 doesn't return an error. +func (c *EC2) AssociateAddress(input *AssociateAddressInput) (*AssociateAddressOutput, error) { + req, out := c.AssociateAddressRequest(input) + err := req.Send() + return out, err +} + +const opAssociateDhcpOptions = "AssociateDhcpOptions" + +// AssociateDhcpOptionsRequest generates a request for the AssociateDhcpOptions operation. +func (c *EC2) AssociateDhcpOptionsRequest(input *AssociateDhcpOptionsInput) (req *request.Request, output *AssociateDhcpOptionsOutput) { + op := &request.Operation{ + Name: opAssociateDhcpOptions, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssociateDhcpOptionsInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &AssociateDhcpOptionsOutput{} + req.Data = output + return +} + +// Associates a set of DHCP options (that you've previously created) with the +// specified VPC, or associates no DHCP options with the VPC. +// +// After you associate the options with the VPC, any existing instances and +// all new instances that you launch in that VPC use the options. You don't +// need to restart or relaunch the instances. They automatically pick up the +// changes within a few hours, depending on how frequently the instance renews +// its DHCP lease. You can explicitly renew the lease using the operating system +// on the instance. +// +// For more information, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) AssociateDhcpOptions(input *AssociateDhcpOptionsInput) (*AssociateDhcpOptionsOutput, error) { + req, out := c.AssociateDhcpOptionsRequest(input) + err := req.Send() + return out, err +} + +const opAssociateRouteTable = "AssociateRouteTable" + +// AssociateRouteTableRequest generates a request for the AssociateRouteTable operation. +func (c *EC2) AssociateRouteTableRequest(input *AssociateRouteTableInput) (req *request.Request, output *AssociateRouteTableOutput) { + op := &request.Operation{ + Name: opAssociateRouteTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssociateRouteTableInput{} + } + + req = c.newRequest(op, input, output) + output = &AssociateRouteTableOutput{} + req.Data = output + return +} + +// Associates a subnet with a route table. The subnet and route table must be +// in the same VPC. This association causes traffic originating from the subnet +// to be routed according to the routes in the route table. The action returns +// an association ID, which you need in order to disassociate the route table +// from the subnet later. A route table can be associated with multiple subnets. +// +// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) AssociateRouteTable(input *AssociateRouteTableInput) (*AssociateRouteTableOutput, error) { + req, out := c.AssociateRouteTableRequest(input) + err := req.Send() + return out, err +} + +const opAttachClassicLinkVpc = "AttachClassicLinkVpc" + +// AttachClassicLinkVpcRequest generates a request for the AttachClassicLinkVpc operation. +func (c *EC2) AttachClassicLinkVpcRequest(input *AttachClassicLinkVpcInput) (req *request.Request, output *AttachClassicLinkVpcOutput) { + op := &request.Operation{ + Name: opAttachClassicLinkVpc, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AttachClassicLinkVpcInput{} + } + + req = c.newRequest(op, input, output) + output = &AttachClassicLinkVpcOutput{} + req.Data = output + return +} + +// Links an EC2-Classic instance to a ClassicLink-enabled VPC through one or +// more of the VPC's security groups. You cannot link an EC2-Classic instance +// to more than one VPC at a time. You can only link an instance that's in the +// running state. An instance is automatically unlinked from a VPC when it's +// stopped - you can link it to the VPC again when you restart it. +// +// After you've linked an instance, you cannot change the VPC security groups +// that are associated with it. To change the security groups, you must first +// unlink the instance, and then link it again. +// +// Linking your instance to a VPC is sometimes referred to as attaching your +// instance. +func (c *EC2) AttachClassicLinkVpc(input *AttachClassicLinkVpcInput) (*AttachClassicLinkVpcOutput, error) { + req, out := c.AttachClassicLinkVpcRequest(input) + err := req.Send() + return out, err +} + +const opAttachInternetGateway = "AttachInternetGateway" + +// AttachInternetGatewayRequest generates a request for the AttachInternetGateway operation. +func (c *EC2) AttachInternetGatewayRequest(input *AttachInternetGatewayInput) (req *request.Request, output *AttachInternetGatewayOutput) { + op := &request.Operation{ + Name: opAttachInternetGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AttachInternetGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &AttachInternetGatewayOutput{} + req.Data = output + return +} + +// Attaches an Internet gateway to a VPC, enabling connectivity between the +// Internet and the VPC. For more information about your VPC and Internet gateway, +// see the Amazon Virtual Private Cloud User Guide (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/). +func (c *EC2) AttachInternetGateway(input *AttachInternetGatewayInput) (*AttachInternetGatewayOutput, error) { + req, out := c.AttachInternetGatewayRequest(input) + err := req.Send() + return out, err +} + +const opAttachNetworkInterface = "AttachNetworkInterface" + +// AttachNetworkInterfaceRequest generates a request for the AttachNetworkInterface operation. +func (c *EC2) AttachNetworkInterfaceRequest(input *AttachNetworkInterfaceInput) (req *request.Request, output *AttachNetworkInterfaceOutput) { + op := &request.Operation{ + Name: opAttachNetworkInterface, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AttachNetworkInterfaceInput{} + } + + req = c.newRequest(op, input, output) + output = &AttachNetworkInterfaceOutput{} + req.Data = output + return +} + +// Attaches a network interface to an instance. +func (c *EC2) AttachNetworkInterface(input *AttachNetworkInterfaceInput) (*AttachNetworkInterfaceOutput, error) { + req, out := c.AttachNetworkInterfaceRequest(input) + err := req.Send() + return out, err +} + +const opAttachVolume = "AttachVolume" + +// AttachVolumeRequest generates a request for the AttachVolume operation. +func (c *EC2) AttachVolumeRequest(input *AttachVolumeInput) (req *request.Request, output *VolumeAttachment) { + op := &request.Operation{ + Name: opAttachVolume, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AttachVolumeInput{} + } + + req = c.newRequest(op, input, output) + output = &VolumeAttachment{} + req.Data = output + return +} + +// Attaches an EBS volume to a running or stopped instance and exposes it to +// the instance with the specified device name. +// +// Encrypted EBS volumes may only be attached to instances that support Amazon +// EBS encryption. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// For a list of supported device names, see Attaching an EBS Volume to an +// Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html). +// Any device names that aren't reserved for instance store volumes can be used +// for EBS volumes. For more information, see Amazon EC2 Instance Store (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// If a volume has an AWS Marketplace product code: +// +// The volume can be attached only to a stopped instance. AWS Marketplace +// product codes are copied from the volume to the instance. You must be subscribed +// to the product. The instance type and operating system of the instance must +// support the product. For example, you can't detach a volume from a Windows +// instance and attach it to a Linux instance. For an overview of the AWS Marketplace, +// see Introducing AWS Marketplace (https://aws.amazon.com/marketplace/help/200900000). +// +// For more information about EBS volumes, see Attaching Amazon EBS Volumes +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) AttachVolume(input *AttachVolumeInput) (*VolumeAttachment, error) { + req, out := c.AttachVolumeRequest(input) + err := req.Send() + return out, err +} + +const opAttachVpnGateway = "AttachVpnGateway" + +// AttachVpnGatewayRequest generates a request for the AttachVpnGateway operation. +func (c *EC2) AttachVpnGatewayRequest(input *AttachVpnGatewayInput) (req *request.Request, output *AttachVpnGatewayOutput) { + op := &request.Operation{ + Name: opAttachVpnGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AttachVpnGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &AttachVpnGatewayOutput{} + req.Data = output + return +} + +// Attaches a virtual private gateway to a VPC. For more information, see Adding +// a Hardware Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) AttachVpnGateway(input *AttachVpnGatewayInput) (*AttachVpnGatewayOutput, error) { + req, out := c.AttachVpnGatewayRequest(input) + err := req.Send() + return out, err +} + +const opAuthorizeSecurityGroupEgress = "AuthorizeSecurityGroupEgress" + +// AuthorizeSecurityGroupEgressRequest generates a request for the AuthorizeSecurityGroupEgress operation. +func (c *EC2) AuthorizeSecurityGroupEgressRequest(input *AuthorizeSecurityGroupEgressInput) (req *request.Request, output *AuthorizeSecurityGroupEgressOutput) { + op := &request.Operation{ + Name: opAuthorizeSecurityGroupEgress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AuthorizeSecurityGroupEgressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &AuthorizeSecurityGroupEgressOutput{} + req.Data = output + return +} + +// [EC2-VPC only] Adds one or more egress rules to a security group for use +// with a VPC. Specifically, this action permits instances to send traffic to +// one or more destination CIDR IP address ranges, or to one or more destination +// security groups for the same VPC. This action doesn't apply to security groups +// for use in EC2-Classic. For more information, see Security Groups for Your +// VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) +// in the Amazon Virtual Private Cloud User Guide. +// +// You can have up to 50 rules per security group (covering both ingress and +// egress rules). +// +// Each rule consists of the protocol (for example, TCP), plus either a CIDR +// range or a source group. For the TCP and UDP protocols, you must also specify +// the destination port or port range. For the ICMP protocol, you must also +// specify the ICMP type and code. You can use -1 for the type or code to mean +// all types or all codes. +// +// Rule changes are propagated to affected instances as quickly as possible. +// However, a small delay might occur. +func (c *EC2) AuthorizeSecurityGroupEgress(input *AuthorizeSecurityGroupEgressInput) (*AuthorizeSecurityGroupEgressOutput, error) { + req, out := c.AuthorizeSecurityGroupEgressRequest(input) + err := req.Send() + return out, err +} + +const opAuthorizeSecurityGroupIngress = "AuthorizeSecurityGroupIngress" + +// AuthorizeSecurityGroupIngressRequest generates a request for the AuthorizeSecurityGroupIngress operation. +func (c *EC2) AuthorizeSecurityGroupIngressRequest(input *AuthorizeSecurityGroupIngressInput) (req *request.Request, output *AuthorizeSecurityGroupIngressOutput) { + op := &request.Operation{ + Name: opAuthorizeSecurityGroupIngress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AuthorizeSecurityGroupIngressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &AuthorizeSecurityGroupIngressOutput{} + req.Data = output + return +} + +// Adds one or more ingress rules to a security group. +// +// EC2-Classic: You can have up to 100 rules per group. +// +// EC2-VPC: You can have up to 50 rules per group (covering both ingress and +// egress rules). +// +// Rule changes are propagated to instances within the security group as quickly +// as possible. However, a small delay might occur. +// +// [EC2-Classic] This action gives one or more CIDR IP address ranges permission +// to access a security group in your account, or gives one or more security +// groups (called the source groups) permission to access a security group for +// your account. A source group can be for your own AWS account, or another. +// +// [EC2-VPC] This action gives one or more CIDR IP address ranges permission +// to access a security group in your VPC, or gives one or more other security +// groups (called the source groups) permission to access a security group for +// your VPC. The security groups must all be for the same VPC. +func (c *EC2) AuthorizeSecurityGroupIngress(input *AuthorizeSecurityGroupIngressInput) (*AuthorizeSecurityGroupIngressOutput, error) { + req, out := c.AuthorizeSecurityGroupIngressRequest(input) + err := req.Send() + return out, err +} + +const opBundleInstance = "BundleInstance" + +// BundleInstanceRequest generates a request for the BundleInstance operation. +func (c *EC2) BundleInstanceRequest(input *BundleInstanceInput) (req *request.Request, output *BundleInstanceOutput) { + op := &request.Operation{ + Name: opBundleInstance, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &BundleInstanceInput{} + } + + req = c.newRequest(op, input, output) + output = &BundleInstanceOutput{} + req.Data = output + return +} + +// Bundles an Amazon instance store-backed Windows instance. +// +// During bundling, only the root device volume (C:\) is bundled. Data on other +// instance store volumes is not preserved. +// +// This action is not applicable for Linux/Unix instances or Windows instances +// that are backed by Amazon EBS. +// +// For more information, see Creating an Instance Store-Backed Windows AMI +// (http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Creating_InstanceStoreBacked_WinAMI.html). +func (c *EC2) BundleInstance(input *BundleInstanceInput) (*BundleInstanceOutput, error) { + req, out := c.BundleInstanceRequest(input) + err := req.Send() + return out, err +} + +const opCancelBundleTask = "CancelBundleTask" + +// CancelBundleTaskRequest generates a request for the CancelBundleTask operation. +func (c *EC2) CancelBundleTaskRequest(input *CancelBundleTaskInput) (req *request.Request, output *CancelBundleTaskOutput) { + op := &request.Operation{ + Name: opCancelBundleTask, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelBundleTaskInput{} + } + + req = c.newRequest(op, input, output) + output = &CancelBundleTaskOutput{} + req.Data = output + return +} + +// Cancels a bundling operation for an instance store-backed Windows instance. +func (c *EC2) CancelBundleTask(input *CancelBundleTaskInput) (*CancelBundleTaskOutput, error) { + req, out := c.CancelBundleTaskRequest(input) + err := req.Send() + return out, err +} + +const opCancelConversionTask = "CancelConversionTask" + +// CancelConversionTaskRequest generates a request for the CancelConversionTask operation. +func (c *EC2) CancelConversionTaskRequest(input *CancelConversionTaskInput) (req *request.Request, output *CancelConversionTaskOutput) { + op := &request.Operation{ + Name: opCancelConversionTask, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelConversionTaskInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CancelConversionTaskOutput{} + req.Data = output + return +} + +// Cancels an active conversion task. The task can be the import of an instance +// or volume. The action removes all artifacts of the conversion, including +// a partially uploaded volume or instance. If the conversion is complete or +// is in the process of transferring the final disk image, the command fails +// and returns an exception. +// +// For more information, see Using the Command Line Tools to Import Your Virtual +// Machine to Amazon EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CancelConversionTask(input *CancelConversionTaskInput) (*CancelConversionTaskOutput, error) { + req, out := c.CancelConversionTaskRequest(input) + err := req.Send() + return out, err +} + +const opCancelExportTask = "CancelExportTask" + +// CancelExportTaskRequest generates a request for the CancelExportTask operation. +func (c *EC2) CancelExportTaskRequest(input *CancelExportTaskInput) (req *request.Request, output *CancelExportTaskOutput) { + op := &request.Operation{ + Name: opCancelExportTask, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelExportTaskInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CancelExportTaskOutput{} + req.Data = output + return +} + +// Cancels an active export task. The request removes all artifacts of the export, +// including any partially-created Amazon S3 objects. If the export task is +// complete or is in the process of transferring the final disk image, the command +// fails and returns an error. +func (c *EC2) CancelExportTask(input *CancelExportTaskInput) (*CancelExportTaskOutput, error) { + req, out := c.CancelExportTaskRequest(input) + err := req.Send() + return out, err +} + +const opCancelImportTask = "CancelImportTask" + +// CancelImportTaskRequest generates a request for the CancelImportTask operation. +func (c *EC2) CancelImportTaskRequest(input *CancelImportTaskInput) (req *request.Request, output *CancelImportTaskOutput) { + op := &request.Operation{ + Name: opCancelImportTask, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelImportTaskInput{} + } + + req = c.newRequest(op, input, output) + output = &CancelImportTaskOutput{} + req.Data = output + return +} + +// Cancels an in-process import virtual machine or import snapshot task. +func (c *EC2) CancelImportTask(input *CancelImportTaskInput) (*CancelImportTaskOutput, error) { + req, out := c.CancelImportTaskRequest(input) + err := req.Send() + return out, err +} + +const opCancelReservedInstancesListing = "CancelReservedInstancesListing" + +// CancelReservedInstancesListingRequest generates a request for the CancelReservedInstancesListing operation. +func (c *EC2) CancelReservedInstancesListingRequest(input *CancelReservedInstancesListingInput) (req *request.Request, output *CancelReservedInstancesListingOutput) { + op := &request.Operation{ + Name: opCancelReservedInstancesListing, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelReservedInstancesListingInput{} + } + + req = c.newRequest(op, input, output) + output = &CancelReservedInstancesListingOutput{} + req.Data = output + return +} + +// Cancels the specified Reserved Instance listing in the Reserved Instance +// Marketplace. +// +// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CancelReservedInstancesListing(input *CancelReservedInstancesListingInput) (*CancelReservedInstancesListingOutput, error) { + req, out := c.CancelReservedInstancesListingRequest(input) + err := req.Send() + return out, err +} + +const opCancelSpotFleetRequests = "CancelSpotFleetRequests" + +// CancelSpotFleetRequestsRequest generates a request for the CancelSpotFleetRequests operation. +func (c *EC2) CancelSpotFleetRequestsRequest(input *CancelSpotFleetRequestsInput) (req *request.Request, output *CancelSpotFleetRequestsOutput) { + op := &request.Operation{ + Name: opCancelSpotFleetRequests, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelSpotFleetRequestsInput{} + } + + req = c.newRequest(op, input, output) + output = &CancelSpotFleetRequestsOutput{} + req.Data = output + return +} + +// Cancels the specified Spot fleet requests. +// +// After you cancel a Spot fleet request, the Spot fleet launches no new Spot +// instances. You must specify whether the Spot fleet should also terminate +// its Spot instances. If you terminate the instances, the Spot fleet request +// enters the cancelled_terminating state. Otherwise, the Spot fleet request +// enters the cancelled_running state and the instances continue to run until +// they are interrupted or you terminate them manually. +func (c *EC2) CancelSpotFleetRequests(input *CancelSpotFleetRequestsInput) (*CancelSpotFleetRequestsOutput, error) { + req, out := c.CancelSpotFleetRequestsRequest(input) + err := req.Send() + return out, err +} + +const opCancelSpotInstanceRequests = "CancelSpotInstanceRequests" + +// CancelSpotInstanceRequestsRequest generates a request for the CancelSpotInstanceRequests operation. +func (c *EC2) CancelSpotInstanceRequestsRequest(input *CancelSpotInstanceRequestsInput) (req *request.Request, output *CancelSpotInstanceRequestsOutput) { + op := &request.Operation{ + Name: opCancelSpotInstanceRequests, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CancelSpotInstanceRequestsInput{} + } + + req = c.newRequest(op, input, output) + output = &CancelSpotInstanceRequestsOutput{} + req.Data = output + return +} + +// Cancels one or more Spot instance requests. Spot instances are instances +// that Amazon EC2 starts on your behalf when the bid price that you specify +// exceeds the current Spot price. Amazon EC2 periodically sets the Spot price +// based on available Spot instance capacity and current Spot instance requests. +// For more information, see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// Canceling a Spot instance request does not terminate running Spot instances +// associated with the request. +func (c *EC2) CancelSpotInstanceRequests(input *CancelSpotInstanceRequestsInput) (*CancelSpotInstanceRequestsOutput, error) { + req, out := c.CancelSpotInstanceRequestsRequest(input) + err := req.Send() + return out, err +} + +const opConfirmProductInstance = "ConfirmProductInstance" + +// ConfirmProductInstanceRequest generates a request for the ConfirmProductInstance operation. +func (c *EC2) ConfirmProductInstanceRequest(input *ConfirmProductInstanceInput) (req *request.Request, output *ConfirmProductInstanceOutput) { + op := &request.Operation{ + Name: opConfirmProductInstance, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ConfirmProductInstanceInput{} + } + + req = c.newRequest(op, input, output) + output = &ConfirmProductInstanceOutput{} + req.Data = output + return +} + +// Determines whether a product code is associated with an instance. This action +// can only be used by the owner of the product code. It is useful when a product +// code owner needs to verify whether another user's instance is eligible for +// support. +func (c *EC2) ConfirmProductInstance(input *ConfirmProductInstanceInput) (*ConfirmProductInstanceOutput, error) { + req, out := c.ConfirmProductInstanceRequest(input) + err := req.Send() + return out, err +} + +const opCopyImage = "CopyImage" + +// CopyImageRequest generates a request for the CopyImage operation. +func (c *EC2) CopyImageRequest(input *CopyImageInput) (req *request.Request, output *CopyImageOutput) { + op := &request.Operation{ + Name: opCopyImage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CopyImageInput{} + } + + req = c.newRequest(op, input, output) + output = &CopyImageOutput{} + req.Data = output + return +} + +// Initiates the copy of an AMI from the specified source region to the current +// region. You specify the destination region by using its endpoint when making +// the request. +// +// For more information, see Copying AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CopyImage(input *CopyImageInput) (*CopyImageOutput, error) { + req, out := c.CopyImageRequest(input) + err := req.Send() + return out, err +} + +const opCopySnapshot = "CopySnapshot" + +// CopySnapshotRequest generates a request for the CopySnapshot operation. +func (c *EC2) CopySnapshotRequest(input *CopySnapshotInput) (req *request.Request, output *CopySnapshotOutput) { + op := &request.Operation{ + Name: opCopySnapshot, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CopySnapshotInput{} + } + + req = c.newRequest(op, input, output) + output = &CopySnapshotOutput{} + req.Data = output + return +} + +// Copies a point-in-time snapshot of an EBS volume and stores it in Amazon +// S3. You can copy the snapshot within the same region or from one region to +// another. You can use the snapshot to create EBS volumes or Amazon Machine +// Images (AMIs). The snapshot is copied to the regional endpoint that you send +// the HTTP request to. +// +// Copies of encrypted EBS snapshots remain encrypted. Copies of unencrypted +// snapshots remain unencrypted, unless the Encrypted flag is specified during +// the snapshot copy operation. By default, encrypted snapshot copies use the +// default AWS Key Management Service (AWS KMS) customer master key (CMK); however, +// you can specify a non-default CMK with the KmsKeyId parameter. +// +// For more information, see Copying an Amazon EBS Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-copy-snapshot.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CopySnapshot(input *CopySnapshotInput) (*CopySnapshotOutput, error) { + req, out := c.CopySnapshotRequest(input) + err := req.Send() + return out, err +} + +const opCreateCustomerGateway = "CreateCustomerGateway" + +// CreateCustomerGatewayRequest generates a request for the CreateCustomerGateway operation. +func (c *EC2) CreateCustomerGatewayRequest(input *CreateCustomerGatewayInput) (req *request.Request, output *CreateCustomerGatewayOutput) { + op := &request.Operation{ + Name: opCreateCustomerGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateCustomerGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateCustomerGatewayOutput{} + req.Data = output + return +} + +// Provides information to AWS about your VPN customer gateway device. The customer +// gateway is the appliance at your end of the VPN connection. (The device on +// the AWS side of the VPN connection is the virtual private gateway.) You must +// provide the Internet-routable IP address of the customer gateway's external +// interface. The IP address must be static and may be behind a device performing +// network address translation (NAT). +// +// For devices that use Border Gateway Protocol (BGP), you can also provide +// the device's BGP Autonomous System Number (ASN). You can use an existing +// ASN assigned to your network. If you don't have an ASN already, you can use +// a private ASN (in the 64512 - 65534 range). +// +// Amazon EC2 supports all 2-byte ASN numbers in the range of 1 - 65534, with +// the exception of 7224, which is reserved in the us-east-1 region, and 9059, +// which is reserved in the eu-west-1 region. +// +// For more information about VPN customer gateways, see Adding a Hardware +// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +// +// You cannot create more than one customer gateway with the same VPN type, +// IP address, and BGP ASN parameter values. If you run an identical request +// more than one time, the first request creates the customer gateway, and subsequent +// requests return information about the existing customer gateway. The subsequent +// requests do not create new customer gateway resources. +func (c *EC2) CreateCustomerGateway(input *CreateCustomerGatewayInput) (*CreateCustomerGatewayOutput, error) { + req, out := c.CreateCustomerGatewayRequest(input) + err := req.Send() + return out, err +} + +const opCreateDhcpOptions = "CreateDhcpOptions" + +// CreateDhcpOptionsRequest generates a request for the CreateDhcpOptions operation. +func (c *EC2) CreateDhcpOptionsRequest(input *CreateDhcpOptionsInput) (req *request.Request, output *CreateDhcpOptionsOutput) { + op := &request.Operation{ + Name: opCreateDhcpOptions, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateDhcpOptionsInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateDhcpOptionsOutput{} + req.Data = output + return +} + +// Creates a set of DHCP options for your VPC. After creating the set, you must +// associate it with the VPC, causing all existing and new instances that you +// launch in the VPC to use this set of DHCP options. The following are the +// individual DHCP options you can specify. For more information about the options, +// see RFC 2132 (http://www.ietf.org/rfc/rfc2132.txt). +// +// domain-name-servers - The IP addresses of up to four domain name servers, +// or AmazonProvidedDNS. The default DHCP option set specifies AmazonProvidedDNS. +// If specifying more than one domain name server, specify the IP addresses +// in a single parameter, separated by commas. domain-name - If you're using +// AmazonProvidedDNS in us-east-1, specify ec2.internal. If you're using AmazonProvidedDNS +// in another region, specify region.compute.internal (for example, ap-northeast-1.compute.internal). +// Otherwise, specify a domain name (for example, MyCompany.com). Important: +// Some Linux operating systems accept multiple domain names separated by spaces. +// However, Windows and other Linux operating systems treat the value as a single +// domain, which results in unexpected behavior. If your DHCP options set is +// associated with a VPC that has instances with multiple operating systems, +// specify only one domain name. ntp-servers - The IP addresses of up to four +// Network Time Protocol (NTP) servers. netbios-name-servers - The IP addresses +// of up to four NetBIOS name servers. netbios-node-type - The NetBIOS node +// type (1, 2, 4, or 8). We recommend that you specify 2 (broadcast and multicast +// are not currently supported). For more information about these node types, +// see RFC 2132 (http://www.ietf.org/rfc/rfc2132.txt). Your VPC automatically +// starts out with a set of DHCP options that includes only a DNS server that +// we provide (AmazonProvidedDNS). If you create a set of options, and if your +// VPC has an Internet gateway, make sure to set the domain-name-servers option +// either to AmazonProvidedDNS or to a domain name server of your choice. For +// more information about DHCP options, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateDhcpOptions(input *CreateDhcpOptionsInput) (*CreateDhcpOptionsOutput, error) { + req, out := c.CreateDhcpOptionsRequest(input) + err := req.Send() + return out, err +} + +const opCreateFlowLogs = "CreateFlowLogs" + +// CreateFlowLogsRequest generates a request for the CreateFlowLogs operation. +func (c *EC2) CreateFlowLogsRequest(input *CreateFlowLogsInput) (req *request.Request, output *CreateFlowLogsOutput) { + op := &request.Operation{ + Name: opCreateFlowLogs, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateFlowLogsInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateFlowLogsOutput{} + req.Data = output + return +} + +// Creates one or more flow logs to capture IP traffic for a specific network +// interface, subnet, or VPC. Flow logs are delivered to a specified log group +// in Amazon CloudWatch Logs. If you specify a VPC or subnet in the request, +// a log stream is created in CloudWatch Logs for each network interface in +// the subnet or VPC. Log streams can include information about accepted and +// rejected traffic to a network interface. You can view the data in your log +// streams using Amazon CloudWatch Logs. +// +// In your request, you must also specify an IAM role that has permission to +// publish logs to CloudWatch Logs. +func (c *EC2) CreateFlowLogs(input *CreateFlowLogsInput) (*CreateFlowLogsOutput, error) { + req, out := c.CreateFlowLogsRequest(input) + err := req.Send() + return out, err +} + +const opCreateImage = "CreateImage" + +// CreateImageRequest generates a request for the CreateImage operation. +func (c *EC2) CreateImageRequest(input *CreateImageInput) (req *request.Request, output *CreateImageOutput) { + op := &request.Operation{ + Name: opCreateImage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateImageInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateImageOutput{} + req.Data = output + return +} + +// Creates an Amazon EBS-backed AMI from an Amazon EBS-backed instance that +// is either running or stopped. +// +// If you customized your instance with instance store volumes or EBS volumes +// in addition to the root device volume, the new AMI contains block device +// mapping information for those volumes. When you launch an instance from this +// new AMI, the instance automatically launches with those additional volumes. +// +// For more information, see Creating Amazon EBS-Backed Linux AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateImage(input *CreateImageInput) (*CreateImageOutput, error) { + req, out := c.CreateImageRequest(input) + err := req.Send() + return out, err +} + +const opCreateInstanceExportTask = "CreateInstanceExportTask" + +// CreateInstanceExportTaskRequest generates a request for the CreateInstanceExportTask operation. +func (c *EC2) CreateInstanceExportTaskRequest(input *CreateInstanceExportTaskInput) (req *request.Request, output *CreateInstanceExportTaskOutput) { + op := &request.Operation{ + Name: opCreateInstanceExportTask, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateInstanceExportTaskInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateInstanceExportTaskOutput{} + req.Data = output + return +} + +// Exports a running or stopped instance to an S3 bucket. +// +// For information about the supported operating systems, image formats, and +// known limitations for the types of instances you can export, see Exporting +// EC2 Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ExportingEC2Instances.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateInstanceExportTask(input *CreateInstanceExportTaskInput) (*CreateInstanceExportTaskOutput, error) { + req, out := c.CreateInstanceExportTaskRequest(input) + err := req.Send() + return out, err +} + +const opCreateInternetGateway = "CreateInternetGateway" + +// CreateInternetGatewayRequest generates a request for the CreateInternetGateway operation. +func (c *EC2) CreateInternetGatewayRequest(input *CreateInternetGatewayInput) (req *request.Request, output *CreateInternetGatewayOutput) { + op := &request.Operation{ + Name: opCreateInternetGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateInternetGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateInternetGatewayOutput{} + req.Data = output + return +} + +// Creates an Internet gateway for use with a VPC. After creating the Internet +// gateway, you attach it to a VPC using AttachInternetGateway. +// +// For more information about your VPC and Internet gateway, see the Amazon +// Virtual Private Cloud User Guide (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/). +func (c *EC2) CreateInternetGateway(input *CreateInternetGatewayInput) (*CreateInternetGatewayOutput, error) { + req, out := c.CreateInternetGatewayRequest(input) + err := req.Send() + return out, err +} + +const opCreateKeyPair = "CreateKeyPair" + +// CreateKeyPairRequest generates a request for the CreateKeyPair operation. +func (c *EC2) CreateKeyPairRequest(input *CreateKeyPairInput) (req *request.Request, output *CreateKeyPairOutput) { + op := &request.Operation{ + Name: opCreateKeyPair, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateKeyPairInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateKeyPairOutput{} + req.Data = output + return +} + +// Creates a 2048-bit RSA key pair with the specified name. Amazon EC2 stores +// the public key and displays the private key for you to save to a file. The +// private key is returned as an unencrypted PEM encoded PKCS#8 private key. +// If a key with the specified name already exists, Amazon EC2 returns an error. +// +// You can have up to five thousand key pairs per region. +// +// The key pair returned to you is available only in the region in which you +// create it. To create a key pair that is available in all regions, use ImportKeyPair. +// +// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateKeyPair(input *CreateKeyPairInput) (*CreateKeyPairOutput, error) { + req, out := c.CreateKeyPairRequest(input) + err := req.Send() + return out, err +} + +const opCreateNatGateway = "CreateNatGateway" + +// CreateNatGatewayRequest generates a request for the CreateNatGateway operation. +func (c *EC2) CreateNatGatewayRequest(input *CreateNatGatewayInput) (req *request.Request, output *CreateNatGatewayOutput) { + op := &request.Operation{ + Name: opCreateNatGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateNatGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateNatGatewayOutput{} + req.Data = output + return +} + +// Creates a NAT gateway in the specified subnet. A NAT gateway can be used +// to enable instances in a private subnet to connect to the Internet. This +// action creates a network interface in the specified subnet with a private +// IP address from the IP address range of the subnet. For more information, +// see NAT Gateways (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-nat-gateway.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateNatGateway(input *CreateNatGatewayInput) (*CreateNatGatewayOutput, error) { + req, out := c.CreateNatGatewayRequest(input) + err := req.Send() + return out, err +} + +const opCreateNetworkAcl = "CreateNetworkAcl" + +// CreateNetworkAclRequest generates a request for the CreateNetworkAcl operation. +func (c *EC2) CreateNetworkAclRequest(input *CreateNetworkAclInput) (req *request.Request, output *CreateNetworkAclOutput) { + op := &request.Operation{ + Name: opCreateNetworkAcl, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateNetworkAclInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateNetworkAclOutput{} + req.Data = output + return +} + +// Creates a network ACL in a VPC. Network ACLs provide an optional layer of +// security (in addition to security groups) for the instances in your VPC. +// +// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateNetworkAcl(input *CreateNetworkAclInput) (*CreateNetworkAclOutput, error) { + req, out := c.CreateNetworkAclRequest(input) + err := req.Send() + return out, err +} + +const opCreateNetworkAclEntry = "CreateNetworkAclEntry" + +// CreateNetworkAclEntryRequest generates a request for the CreateNetworkAclEntry operation. +func (c *EC2) CreateNetworkAclEntryRequest(input *CreateNetworkAclEntryInput) (req *request.Request, output *CreateNetworkAclEntryOutput) { + op := &request.Operation{ + Name: opCreateNetworkAclEntry, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateNetworkAclEntryInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CreateNetworkAclEntryOutput{} + req.Data = output + return +} + +// Creates an entry (a rule) in a network ACL with the specified rule number. +// Each network ACL has a set of numbered ingress rules and a separate set of +// numbered egress rules. When determining whether a packet should be allowed +// in or out of a subnet associated with the ACL, we process the entries in +// the ACL according to the rule numbers, in ascending order. Each network ACL +// has a set of ingress rules and a separate set of egress rules. +// +// We recommend that you leave room between the rule numbers (for example, +// 100, 110, 120, ...), and not number them one right after the other (for example, +// 101, 102, 103, ...). This makes it easier to add a rule between existing +// ones without having to renumber the rules. +// +// After you add an entry, you can't modify it; you must either replace it, +// or create an entry and delete the old one. +// +// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateNetworkAclEntry(input *CreateNetworkAclEntryInput) (*CreateNetworkAclEntryOutput, error) { + req, out := c.CreateNetworkAclEntryRequest(input) + err := req.Send() + return out, err +} + +const opCreateNetworkInterface = "CreateNetworkInterface" + +// CreateNetworkInterfaceRequest generates a request for the CreateNetworkInterface operation. +func (c *EC2) CreateNetworkInterfaceRequest(input *CreateNetworkInterfaceInput) (req *request.Request, output *CreateNetworkInterfaceOutput) { + op := &request.Operation{ + Name: opCreateNetworkInterface, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateNetworkInterfaceInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateNetworkInterfaceOutput{} + req.Data = output + return +} + +// Creates a network interface in the specified subnet. +// +// For more information about network interfaces, see Elastic Network Interfaces +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) in the +// Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateNetworkInterface(input *CreateNetworkInterfaceInput) (*CreateNetworkInterfaceOutput, error) { + req, out := c.CreateNetworkInterfaceRequest(input) + err := req.Send() + return out, err +} + +const opCreatePlacementGroup = "CreatePlacementGroup" + +// CreatePlacementGroupRequest generates a request for the CreatePlacementGroup operation. +func (c *EC2) CreatePlacementGroupRequest(input *CreatePlacementGroupInput) (req *request.Request, output *CreatePlacementGroupOutput) { + op := &request.Operation{ + Name: opCreatePlacementGroup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreatePlacementGroupInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CreatePlacementGroupOutput{} + req.Data = output + return +} + +// Creates a placement group that you launch cluster instances into. You must +// give the group a name that's unique within the scope of your account. +// +// For more information about placement groups and cluster instances, see Cluster +// Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreatePlacementGroup(input *CreatePlacementGroupInput) (*CreatePlacementGroupOutput, error) { + req, out := c.CreatePlacementGroupRequest(input) + err := req.Send() + return out, err +} + +const opCreateReservedInstancesListing = "CreateReservedInstancesListing" + +// CreateReservedInstancesListingRequest generates a request for the CreateReservedInstancesListing operation. +func (c *EC2) CreateReservedInstancesListingRequest(input *CreateReservedInstancesListingInput) (req *request.Request, output *CreateReservedInstancesListingOutput) { + op := &request.Operation{ + Name: opCreateReservedInstancesListing, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateReservedInstancesListingInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateReservedInstancesListingOutput{} + req.Data = output + return +} + +// Creates a listing for Amazon EC2 Reserved Instances to be sold in the Reserved +// Instance Marketplace. You can submit one Reserved Instance listing at a time. +// To get a list of your Reserved Instances, you can use the DescribeReservedInstances +// operation. +// +// The Reserved Instance Marketplace matches sellers who want to resell Reserved +// Instance capacity that they no longer need with buyers who want to purchase +// additional capacity. Reserved Instances bought and sold through the Reserved +// Instance Marketplace work like any other Reserved Instances. +// +// To sell your Reserved Instances, you must first register as a seller in +// the Reserved Instance Marketplace. After completing the registration process, +// you can create a Reserved Instance Marketplace listing of some or all of +// your Reserved Instances, and specify the upfront price to receive for them. +// Your Reserved Instance listings then become available for purchase. To view +// the details of your Reserved Instance listing, you can use the DescribeReservedInstancesListings +// operation. +// +// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateReservedInstancesListing(input *CreateReservedInstancesListingInput) (*CreateReservedInstancesListingOutput, error) { + req, out := c.CreateReservedInstancesListingRequest(input) + err := req.Send() + return out, err +} + +const opCreateRoute = "CreateRoute" + +// CreateRouteRequest generates a request for the CreateRoute operation. +func (c *EC2) CreateRouteRequest(input *CreateRouteInput) (req *request.Request, output *CreateRouteOutput) { + op := &request.Operation{ + Name: opCreateRoute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateRouteInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateRouteOutput{} + req.Data = output + return +} + +// Creates a route in a route table within a VPC. +// +// You must specify one of the following targets: Internet gateway or virtual +// private gateway, NAT instance, NAT gateway, VPC peering connection, or network +// interface. +// +// When determining how to route traffic, we use the route with the most specific +// match. For example, let's say the traffic is destined for 192.0.2.3, and +// the route table includes the following two routes: +// +// 192.0.2.0/24 (goes to some target A) +// +// 192.0.2.0/28 (goes to some target B) +// +// Both routes apply to the traffic destined for 192.0.2.3. However, the +// second route in the list covers a smaller number of IP addresses and is therefore +// more specific, so we use that route to determine where to target the traffic. +// +// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateRoute(input *CreateRouteInput) (*CreateRouteOutput, error) { + req, out := c.CreateRouteRequest(input) + err := req.Send() + return out, err +} + +const opCreateRouteTable = "CreateRouteTable" + +// CreateRouteTableRequest generates a request for the CreateRouteTable operation. +func (c *EC2) CreateRouteTableRequest(input *CreateRouteTableInput) (req *request.Request, output *CreateRouteTableOutput) { + op := &request.Operation{ + Name: opCreateRouteTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateRouteTableInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateRouteTableOutput{} + req.Data = output + return +} + +// Creates a route table for the specified VPC. After you create a route table, +// you can add routes and associate the table with a subnet. +// +// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateRouteTable(input *CreateRouteTableInput) (*CreateRouteTableOutput, error) { + req, out := c.CreateRouteTableRequest(input) + err := req.Send() + return out, err +} + +const opCreateSecurityGroup = "CreateSecurityGroup" + +// CreateSecurityGroupRequest generates a request for the CreateSecurityGroup operation. +func (c *EC2) CreateSecurityGroupRequest(input *CreateSecurityGroupInput) (req *request.Request, output *CreateSecurityGroupOutput) { + op := &request.Operation{ + Name: opCreateSecurityGroup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateSecurityGroupInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateSecurityGroupOutput{} + req.Data = output + return +} + +// Creates a security group. +// +// A security group is for use with instances either in the EC2-Classic platform +// or in a specific VPC. For more information, see Amazon EC2 Security Groups +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) +// in the Amazon Elastic Compute Cloud User Guide and Security Groups for Your +// VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) +// in the Amazon Virtual Private Cloud User Guide. +// +// EC2-Classic: You can have up to 500 security groups. +// +// EC2-VPC: You can create up to 500 security groups per VPC. +// +// When you create a security group, you specify a friendly name of your choice. +// You can have a security group for use in EC2-Classic with the same name as +// a security group for use in a VPC. However, you can't have two security groups +// for use in EC2-Classic with the same name or two security groups for use +// in a VPC with the same name. +// +// You have a default security group for use in EC2-Classic and a default security +// group for use in your VPC. If you don't specify a security group when you +// launch an instance, the instance is launched into the appropriate default +// security group. A default security group includes a default rule that grants +// instances unrestricted network access to each other. +// +// You can add or remove rules from your security groups using AuthorizeSecurityGroupIngress, +// AuthorizeSecurityGroupEgress, RevokeSecurityGroupIngress, and RevokeSecurityGroupEgress. +func (c *EC2) CreateSecurityGroup(input *CreateSecurityGroupInput) (*CreateSecurityGroupOutput, error) { + req, out := c.CreateSecurityGroupRequest(input) + err := req.Send() + return out, err +} + +const opCreateSnapshot = "CreateSnapshot" + +// CreateSnapshotRequest generates a request for the CreateSnapshot operation. +func (c *EC2) CreateSnapshotRequest(input *CreateSnapshotInput) (req *request.Request, output *Snapshot) { + op := &request.Operation{ + Name: opCreateSnapshot, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateSnapshotInput{} + } + + req = c.newRequest(op, input, output) + output = &Snapshot{} + req.Data = output + return +} + +// Creates a snapshot of an EBS volume and stores it in Amazon S3. You can use +// snapshots for backups, to make copies of EBS volumes, and to save data before +// shutting down an instance. +// +// When a snapshot is created, any AWS Marketplace product codes that are associated +// with the source volume are propagated to the snapshot. +// +// You can take a snapshot of an attached volume that is in use. However, snapshots +// only capture data that has been written to your EBS volume at the time the +// snapshot command is issued; this may exclude any data that has been cached +// by any applications or the operating system. If you can pause any file systems +// on the volume long enough to take a snapshot, your snapshot should be complete. +// However, if you cannot pause all file writes to the volume, you should unmount +// the volume from within the instance, issue the snapshot command, and then +// remount the volume to ensure a consistent and complete snapshot. You may +// remount and use your volume while the snapshot status is pending. +// +// To create a snapshot for EBS volumes that serve as root devices, you should +// stop the instance before taking the snapshot. +// +// Snapshots that are taken from encrypted volumes are automatically encrypted. +// Volumes that are created from encrypted snapshots are also automatically +// encrypted. Your encrypted volumes and any associated snapshots always remain +// protected. +// +// For more information, see Amazon Elastic Block Store (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) +// and Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateSnapshot(input *CreateSnapshotInput) (*Snapshot, error) { + req, out := c.CreateSnapshotRequest(input) + err := req.Send() + return out, err +} + +const opCreateSpotDatafeedSubscription = "CreateSpotDatafeedSubscription" + +// CreateSpotDatafeedSubscriptionRequest generates a request for the CreateSpotDatafeedSubscription operation. +func (c *EC2) CreateSpotDatafeedSubscriptionRequest(input *CreateSpotDatafeedSubscriptionInput) (req *request.Request, output *CreateSpotDatafeedSubscriptionOutput) { + op := &request.Operation{ + Name: opCreateSpotDatafeedSubscription, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateSpotDatafeedSubscriptionInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateSpotDatafeedSubscriptionOutput{} + req.Data = output + return +} + +// Creates a data feed for Spot instances, enabling you to view Spot instance +// usage logs. You can create one data feed per AWS account. For more information, +// see Spot Instance Data Feed (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateSpotDatafeedSubscription(input *CreateSpotDatafeedSubscriptionInput) (*CreateSpotDatafeedSubscriptionOutput, error) { + req, out := c.CreateSpotDatafeedSubscriptionRequest(input) + err := req.Send() + return out, err +} + +const opCreateSubnet = "CreateSubnet" + +// CreateSubnetRequest generates a request for the CreateSubnet operation. +func (c *EC2) CreateSubnetRequest(input *CreateSubnetInput) (req *request.Request, output *CreateSubnetOutput) { + op := &request.Operation{ + Name: opCreateSubnet, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateSubnetInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateSubnetOutput{} + req.Data = output + return +} + +// Creates a subnet in an existing VPC. +// +// When you create each subnet, you provide the VPC ID and the CIDR block you +// want for the subnet. After you create a subnet, you can't change its CIDR +// block. The subnet's CIDR block can be the same as the VPC's CIDR block (assuming +// you want only a single subnet in the VPC), or a subset of the VPC's CIDR +// block. If you create more than one subnet in a VPC, the subnets' CIDR blocks +// must not overlap. The smallest subnet (and VPC) you can create uses a /28 +// netmask (16 IP addresses), and the largest uses a /16 netmask (65,536 IP +// addresses). +// +// AWS reserves both the first four and the last IP address in each subnet's +// CIDR block. They're not available for use. +// +// If you add more than one subnet to a VPC, they're set up in a star topology +// with a logical router in the middle. +// +// If you launch an instance in a VPC using an Amazon EBS-backed AMI, the IP +// address doesn't change if you stop and restart the instance (unlike a similar +// instance launched outside a VPC, which gets a new IP address when restarted). +// It's therefore possible to have a subnet with no running instances (they're +// all stopped), but no remaining IP addresses available. +// +// For more information about subnets, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateSubnet(input *CreateSubnetInput) (*CreateSubnetOutput, error) { + req, out := c.CreateSubnetRequest(input) + err := req.Send() + return out, err +} + +const opCreateTags = "CreateTags" + +// CreateTagsRequest generates a request for the CreateTags operation. +func (c *EC2) CreateTagsRequest(input *CreateTagsInput) (req *request.Request, output *CreateTagsOutput) { + op := &request.Operation{ + Name: opCreateTags, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateTagsInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CreateTagsOutput{} + req.Data = output + return +} + +// Adds or overwrites one or more tags for the specified Amazon EC2 resource +// or resources. Each resource can have a maximum of 10 tags. Each tag consists +// of a key and optional value. Tag keys must be unique per resource. +// +// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) +// in the Amazon Elastic Compute Cloud User Guide. For more information about +// creating IAM policies that control users' access to resources based on tags, +// see Supported Resource-Level Permissions for Amazon EC2 API Actions (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-supported-iam-actions-resources.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateTags(input *CreateTagsInput) (*CreateTagsOutput, error) { + req, out := c.CreateTagsRequest(input) + err := req.Send() + return out, err +} + +const opCreateVolume = "CreateVolume" + +// CreateVolumeRequest generates a request for the CreateVolume operation. +func (c *EC2) CreateVolumeRequest(input *CreateVolumeInput) (req *request.Request, output *Volume) { + op := &request.Operation{ + Name: opCreateVolume, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVolumeInput{} + } + + req = c.newRequest(op, input, output) + output = &Volume{} + req.Data = output + return +} + +// Creates an EBS volume that can be attached to an instance in the same Availability +// Zone. The volume is created in the regional endpoint that you send the HTTP +// request to. For more information see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html). +// +// You can create a new empty volume or restore a volume from an EBS snapshot. +// Any AWS Marketplace product codes from the snapshot are propagated to the +// volume. +// +// You can create encrypted volumes with the Encrypted parameter. Encrypted +// volumes may only be attached to instances that support Amazon EBS encryption. +// Volumes that are created from encrypted snapshots are also automatically +// encrypted. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// For more information, see Creating or Restoring an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-volume.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) CreateVolume(input *CreateVolumeInput) (*Volume, error) { + req, out := c.CreateVolumeRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpc = "CreateVpc" + +// CreateVpcRequest generates a request for the CreateVpc operation. +func (c *EC2) CreateVpcRequest(input *CreateVpcInput) (req *request.Request, output *CreateVpcOutput) { + op := &request.Operation{ + Name: opCreateVpc, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpcInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateVpcOutput{} + req.Data = output + return +} + +// Creates a VPC with the specified CIDR block. +// +// The smallest VPC you can create uses a /28 netmask (16 IP addresses), and +// the largest uses a /16 netmask (65,536 IP addresses). To help you decide +// how big to make your VPC, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) +// in the Amazon Virtual Private Cloud User Guide. +// +// By default, each instance you launch in the VPC has the default DHCP options, +// which includes only a default DNS server that we provide (AmazonProvidedDNS). +// For more information about DHCP options, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateVpc(input *CreateVpcInput) (*CreateVpcOutput, error) { + req, out := c.CreateVpcRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpcEndpoint = "CreateVpcEndpoint" + +// CreateVpcEndpointRequest generates a request for the CreateVpcEndpoint operation. +func (c *EC2) CreateVpcEndpointRequest(input *CreateVpcEndpointInput) (req *request.Request, output *CreateVpcEndpointOutput) { + op := &request.Operation{ + Name: opCreateVpcEndpoint, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpcEndpointInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateVpcEndpointOutput{} + req.Data = output + return +} + +// Creates a VPC endpoint for a specified AWS service. An endpoint enables you +// to create a private connection between your VPC and another AWS service in +// your account. You can specify an endpoint policy to attach to the endpoint +// that will control access to the service from your VPC. You can also specify +// the VPC route tables that use the endpoint. +// +// Currently, only endpoints to Amazon S3 are supported. +func (c *EC2) CreateVpcEndpoint(input *CreateVpcEndpointInput) (*CreateVpcEndpointOutput, error) { + req, out := c.CreateVpcEndpointRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpcPeeringConnection = "CreateVpcPeeringConnection" + +// CreateVpcPeeringConnectionRequest generates a request for the CreateVpcPeeringConnection operation. +func (c *EC2) CreateVpcPeeringConnectionRequest(input *CreateVpcPeeringConnectionInput) (req *request.Request, output *CreateVpcPeeringConnectionOutput) { + op := &request.Operation{ + Name: opCreateVpcPeeringConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpcPeeringConnectionInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateVpcPeeringConnectionOutput{} + req.Data = output + return +} + +// Requests a VPC peering connection between two VPCs: a requester VPC that +// you own and a peer VPC with which to create the connection. The peer VPC +// can belong to another AWS account. The requester VPC and peer VPC cannot +// have overlapping CIDR blocks. +// +// The owner of the peer VPC must accept the peering request to activate the +// peering connection. The VPC peering connection request expires after 7 days, +// after which it cannot be accepted or rejected. +// +// A CreateVpcPeeringConnection request between VPCs with overlapping CIDR +// blocks results in the VPC peering connection having a status of failed. +func (c *EC2) CreateVpcPeeringConnection(input *CreateVpcPeeringConnectionInput) (*CreateVpcPeeringConnectionOutput, error) { + req, out := c.CreateVpcPeeringConnectionRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpnConnection = "CreateVpnConnection" + +// CreateVpnConnectionRequest generates a request for the CreateVpnConnection operation. +func (c *EC2) CreateVpnConnectionRequest(input *CreateVpnConnectionInput) (req *request.Request, output *CreateVpnConnectionOutput) { + op := &request.Operation{ + Name: opCreateVpnConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpnConnectionInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateVpnConnectionOutput{} + req.Data = output + return +} + +// Creates a VPN connection between an existing virtual private gateway and +// a VPN customer gateway. The only supported connection type is ipsec.1. +// +// The response includes information that you need to give to your network +// administrator to configure your customer gateway. +// +// We strongly recommend that you use HTTPS when calling this operation because +// the response contains sensitive cryptographic information for configuring +// your customer gateway. +// +// If you decide to shut down your VPN connection for any reason and later +// create a new VPN connection, you must reconfigure your customer gateway with +// the new information returned from this call. +// +// For more information about VPN connections, see Adding a Hardware Virtual +// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateVpnConnection(input *CreateVpnConnectionInput) (*CreateVpnConnectionOutput, error) { + req, out := c.CreateVpnConnectionRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpnConnectionRoute = "CreateVpnConnectionRoute" + +// CreateVpnConnectionRouteRequest generates a request for the CreateVpnConnectionRoute operation. +func (c *EC2) CreateVpnConnectionRouteRequest(input *CreateVpnConnectionRouteInput) (req *request.Request, output *CreateVpnConnectionRouteOutput) { + op := &request.Operation{ + Name: opCreateVpnConnectionRoute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpnConnectionRouteInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &CreateVpnConnectionRouteOutput{} + req.Data = output + return +} + +// Creates a static route associated with a VPN connection between an existing +// virtual private gateway and a VPN customer gateway. The static route allows +// traffic to be routed from the virtual private gateway to the VPN customer +// gateway. +// +// For more information about VPN connections, see Adding a Hardware Virtual +// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateVpnConnectionRoute(input *CreateVpnConnectionRouteInput) (*CreateVpnConnectionRouteOutput, error) { + req, out := c.CreateVpnConnectionRouteRequest(input) + err := req.Send() + return out, err +} + +const opCreateVpnGateway = "CreateVpnGateway" + +// CreateVpnGatewayRequest generates a request for the CreateVpnGateway operation. +func (c *EC2) CreateVpnGatewayRequest(input *CreateVpnGatewayInput) (req *request.Request, output *CreateVpnGatewayOutput) { + op := &request.Operation{ + Name: opCreateVpnGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateVpnGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &CreateVpnGatewayOutput{} + req.Data = output + return +} + +// Creates a virtual private gateway. A virtual private gateway is the endpoint +// on the VPC side of your VPN connection. You can create a virtual private +// gateway before creating the VPC itself. +// +// For more information about virtual private gateways, see Adding a Hardware +// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) CreateVpnGateway(input *CreateVpnGatewayInput) (*CreateVpnGatewayOutput, error) { + req, out := c.CreateVpnGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDeleteCustomerGateway = "DeleteCustomerGateway" + +// DeleteCustomerGatewayRequest generates a request for the DeleteCustomerGateway operation. +func (c *EC2) DeleteCustomerGatewayRequest(input *DeleteCustomerGatewayInput) (req *request.Request, output *DeleteCustomerGatewayOutput) { + op := &request.Operation{ + Name: opDeleteCustomerGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteCustomerGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteCustomerGatewayOutput{} + req.Data = output + return +} + +// Deletes the specified customer gateway. You must delete the VPN connection +// before you can delete the customer gateway. +func (c *EC2) DeleteCustomerGateway(input *DeleteCustomerGatewayInput) (*DeleteCustomerGatewayOutput, error) { + req, out := c.DeleteCustomerGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDeleteDhcpOptions = "DeleteDhcpOptions" + +// DeleteDhcpOptionsRequest generates a request for the DeleteDhcpOptions operation. +func (c *EC2) DeleteDhcpOptionsRequest(input *DeleteDhcpOptionsInput) (req *request.Request, output *DeleteDhcpOptionsOutput) { + op := &request.Operation{ + Name: opDeleteDhcpOptions, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteDhcpOptionsInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteDhcpOptionsOutput{} + req.Data = output + return +} + +// Deletes the specified set of DHCP options. You must disassociate the set +// of DHCP options before you can delete it. You can disassociate the set of +// DHCP options by associating either a new set of options or the default set +// of options with the VPC. +func (c *EC2) DeleteDhcpOptions(input *DeleteDhcpOptionsInput) (*DeleteDhcpOptionsOutput, error) { + req, out := c.DeleteDhcpOptionsRequest(input) + err := req.Send() + return out, err +} + +const opDeleteFlowLogs = "DeleteFlowLogs" + +// DeleteFlowLogsRequest generates a request for the DeleteFlowLogs operation. +func (c *EC2) DeleteFlowLogsRequest(input *DeleteFlowLogsInput) (req *request.Request, output *DeleteFlowLogsOutput) { + op := &request.Operation{ + Name: opDeleteFlowLogs, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteFlowLogsInput{} + } + + req = c.newRequest(op, input, output) + output = &DeleteFlowLogsOutput{} + req.Data = output + return +} + +// Deletes one or more flow logs. +func (c *EC2) DeleteFlowLogs(input *DeleteFlowLogsInput) (*DeleteFlowLogsOutput, error) { + req, out := c.DeleteFlowLogsRequest(input) + err := req.Send() + return out, err +} + +const opDeleteInternetGateway = "DeleteInternetGateway" + +// DeleteInternetGatewayRequest generates a request for the DeleteInternetGateway operation. +func (c *EC2) DeleteInternetGatewayRequest(input *DeleteInternetGatewayInput) (req *request.Request, output *DeleteInternetGatewayOutput) { + op := &request.Operation{ + Name: opDeleteInternetGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteInternetGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteInternetGatewayOutput{} + req.Data = output + return +} + +// Deletes the specified Internet gateway. You must detach the Internet gateway +// from the VPC before you can delete it. +func (c *EC2) DeleteInternetGateway(input *DeleteInternetGatewayInput) (*DeleteInternetGatewayOutput, error) { + req, out := c.DeleteInternetGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDeleteKeyPair = "DeleteKeyPair" + +// DeleteKeyPairRequest generates a request for the DeleteKeyPair operation. +func (c *EC2) DeleteKeyPairRequest(input *DeleteKeyPairInput) (req *request.Request, output *DeleteKeyPairOutput) { + op := &request.Operation{ + Name: opDeleteKeyPair, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteKeyPairInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteKeyPairOutput{} + req.Data = output + return +} + +// Deletes the specified key pair, by removing the public key from Amazon EC2. +func (c *EC2) DeleteKeyPair(input *DeleteKeyPairInput) (*DeleteKeyPairOutput, error) { + req, out := c.DeleteKeyPairRequest(input) + err := req.Send() + return out, err +} + +const opDeleteNatGateway = "DeleteNatGateway" + +// DeleteNatGatewayRequest generates a request for the DeleteNatGateway operation. +func (c *EC2) DeleteNatGatewayRequest(input *DeleteNatGatewayInput) (req *request.Request, output *DeleteNatGatewayOutput) { + op := &request.Operation{ + Name: opDeleteNatGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteNatGatewayInput{} + } + + req = c.newRequest(op, input, output) + output = &DeleteNatGatewayOutput{} + req.Data = output + return +} + +// Deletes the specified NAT gateway. Deleting a NAT gateway disassociates its +// Elastic IP address, but does not release the address from your account. Deleting +// a NAT gateway does not delete any NAT gateway routes in your route tables. +func (c *EC2) DeleteNatGateway(input *DeleteNatGatewayInput) (*DeleteNatGatewayOutput, error) { + req, out := c.DeleteNatGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDeleteNetworkAcl = "DeleteNetworkAcl" + +// DeleteNetworkAclRequest generates a request for the DeleteNetworkAcl operation. +func (c *EC2) DeleteNetworkAclRequest(input *DeleteNetworkAclInput) (req *request.Request, output *DeleteNetworkAclOutput) { + op := &request.Operation{ + Name: opDeleteNetworkAcl, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteNetworkAclInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteNetworkAclOutput{} + req.Data = output + return +} + +// Deletes the specified network ACL. You can't delete the ACL if it's associated +// with any subnets. You can't delete the default network ACL. +func (c *EC2) DeleteNetworkAcl(input *DeleteNetworkAclInput) (*DeleteNetworkAclOutput, error) { + req, out := c.DeleteNetworkAclRequest(input) + err := req.Send() + return out, err +} + +const opDeleteNetworkAclEntry = "DeleteNetworkAclEntry" + +// DeleteNetworkAclEntryRequest generates a request for the DeleteNetworkAclEntry operation. +func (c *EC2) DeleteNetworkAclEntryRequest(input *DeleteNetworkAclEntryInput) (req *request.Request, output *DeleteNetworkAclEntryOutput) { + op := &request.Operation{ + Name: opDeleteNetworkAclEntry, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteNetworkAclEntryInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteNetworkAclEntryOutput{} + req.Data = output + return +} + +// Deletes the specified ingress or egress entry (rule) from the specified network +// ACL. +func (c *EC2) DeleteNetworkAclEntry(input *DeleteNetworkAclEntryInput) (*DeleteNetworkAclEntryOutput, error) { + req, out := c.DeleteNetworkAclEntryRequest(input) + err := req.Send() + return out, err +} + +const opDeleteNetworkInterface = "DeleteNetworkInterface" + +// DeleteNetworkInterfaceRequest generates a request for the DeleteNetworkInterface operation. +func (c *EC2) DeleteNetworkInterfaceRequest(input *DeleteNetworkInterfaceInput) (req *request.Request, output *DeleteNetworkInterfaceOutput) { + op := &request.Operation{ + Name: opDeleteNetworkInterface, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteNetworkInterfaceInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteNetworkInterfaceOutput{} + req.Data = output + return +} + +// Deletes the specified network interface. You must detach the network interface +// before you can delete it. +func (c *EC2) DeleteNetworkInterface(input *DeleteNetworkInterfaceInput) (*DeleteNetworkInterfaceOutput, error) { + req, out := c.DeleteNetworkInterfaceRequest(input) + err := req.Send() + return out, err +} + +const opDeletePlacementGroup = "DeletePlacementGroup" + +// DeletePlacementGroupRequest generates a request for the DeletePlacementGroup operation. +func (c *EC2) DeletePlacementGroupRequest(input *DeletePlacementGroupInput) (req *request.Request, output *DeletePlacementGroupOutput) { + op := &request.Operation{ + Name: opDeletePlacementGroup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeletePlacementGroupInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeletePlacementGroupOutput{} + req.Data = output + return +} + +// Deletes the specified placement group. You must terminate all instances in +// the placement group before you can delete the placement group. For more information +// about placement groups and cluster instances, see Cluster Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DeletePlacementGroup(input *DeletePlacementGroupInput) (*DeletePlacementGroupOutput, error) { + req, out := c.DeletePlacementGroupRequest(input) + err := req.Send() + return out, err +} + +const opDeleteRoute = "DeleteRoute" + +// DeleteRouteRequest generates a request for the DeleteRoute operation. +func (c *EC2) DeleteRouteRequest(input *DeleteRouteInput) (req *request.Request, output *DeleteRouteOutput) { + op := &request.Operation{ + Name: opDeleteRoute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteRouteInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteRouteOutput{} + req.Data = output + return +} + +// Deletes the specified route from the specified route table. +func (c *EC2) DeleteRoute(input *DeleteRouteInput) (*DeleteRouteOutput, error) { + req, out := c.DeleteRouteRequest(input) + err := req.Send() + return out, err +} + +const opDeleteRouteTable = "DeleteRouteTable" + +// DeleteRouteTableRequest generates a request for the DeleteRouteTable operation. +func (c *EC2) DeleteRouteTableRequest(input *DeleteRouteTableInput) (req *request.Request, output *DeleteRouteTableOutput) { + op := &request.Operation{ + Name: opDeleteRouteTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteRouteTableInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteRouteTableOutput{} + req.Data = output + return +} + +// Deletes the specified route table. You must disassociate the route table +// from any subnets before you can delete it. You can't delete the main route +// table. +func (c *EC2) DeleteRouteTable(input *DeleteRouteTableInput) (*DeleteRouteTableOutput, error) { + req, out := c.DeleteRouteTableRequest(input) + err := req.Send() + return out, err +} + +const opDeleteSecurityGroup = "DeleteSecurityGroup" + +// DeleteSecurityGroupRequest generates a request for the DeleteSecurityGroup operation. +func (c *EC2) DeleteSecurityGroupRequest(input *DeleteSecurityGroupInput) (req *request.Request, output *DeleteSecurityGroupOutput) { + op := &request.Operation{ + Name: opDeleteSecurityGroup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteSecurityGroupInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteSecurityGroupOutput{} + req.Data = output + return +} + +// Deletes a security group. +// +// If you attempt to delete a security group that is associated with an instance, +// or is referenced by another security group, the operation fails with InvalidGroup.InUse +// in EC2-Classic or DependencyViolation in EC2-VPC. +func (c *EC2) DeleteSecurityGroup(input *DeleteSecurityGroupInput) (*DeleteSecurityGroupOutput, error) { + req, out := c.DeleteSecurityGroupRequest(input) + err := req.Send() + return out, err +} + +const opDeleteSnapshot = "DeleteSnapshot" + +// DeleteSnapshotRequest generates a request for the DeleteSnapshot operation. +func (c *EC2) DeleteSnapshotRequest(input *DeleteSnapshotInput) (req *request.Request, output *DeleteSnapshotOutput) { + op := &request.Operation{ + Name: opDeleteSnapshot, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteSnapshotInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteSnapshotOutput{} + req.Data = output + return +} + +// Deletes the specified snapshot. +// +// When you make periodic snapshots of a volume, the snapshots are incremental, +// and only the blocks on the device that have changed since your last snapshot +// are saved in the new snapshot. When you delete a snapshot, only the data +// not needed for any other snapshot is removed. So regardless of which prior +// snapshots have been deleted, all active snapshots will have access to all +// the information needed to restore the volume. +// +// You cannot delete a snapshot of the root device of an EBS volume used by +// a registered AMI. You must first de-register the AMI before you can delete +// the snapshot. +// +// For more information, see Deleting an Amazon EBS Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-deleting-snapshot.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DeleteSnapshot(input *DeleteSnapshotInput) (*DeleteSnapshotOutput, error) { + req, out := c.DeleteSnapshotRequest(input) + err := req.Send() + return out, err +} + +const opDeleteSpotDatafeedSubscription = "DeleteSpotDatafeedSubscription" + +// DeleteSpotDatafeedSubscriptionRequest generates a request for the DeleteSpotDatafeedSubscription operation. +func (c *EC2) DeleteSpotDatafeedSubscriptionRequest(input *DeleteSpotDatafeedSubscriptionInput) (req *request.Request, output *DeleteSpotDatafeedSubscriptionOutput) { + op := &request.Operation{ + Name: opDeleteSpotDatafeedSubscription, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteSpotDatafeedSubscriptionInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteSpotDatafeedSubscriptionOutput{} + req.Data = output + return +} + +// Deletes the data feed for Spot instances. +func (c *EC2) DeleteSpotDatafeedSubscription(input *DeleteSpotDatafeedSubscriptionInput) (*DeleteSpotDatafeedSubscriptionOutput, error) { + req, out := c.DeleteSpotDatafeedSubscriptionRequest(input) + err := req.Send() + return out, err +} + +const opDeleteSubnet = "DeleteSubnet" + +// DeleteSubnetRequest generates a request for the DeleteSubnet operation. +func (c *EC2) DeleteSubnetRequest(input *DeleteSubnetInput) (req *request.Request, output *DeleteSubnetOutput) { + op := &request.Operation{ + Name: opDeleteSubnet, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteSubnetInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteSubnetOutput{} + req.Data = output + return +} + +// Deletes the specified subnet. You must terminate all running instances in +// the subnet before you can delete the subnet. +func (c *EC2) DeleteSubnet(input *DeleteSubnetInput) (*DeleteSubnetOutput, error) { + req, out := c.DeleteSubnetRequest(input) + err := req.Send() + return out, err +} + +const opDeleteTags = "DeleteTags" + +// DeleteTagsRequest generates a request for the DeleteTags operation. +func (c *EC2) DeleteTagsRequest(input *DeleteTagsInput) (req *request.Request, output *DeleteTagsOutput) { + op := &request.Operation{ + Name: opDeleteTags, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteTagsInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteTagsOutput{} + req.Data = output + return +} + +// Deletes the specified set of tags from the specified set of resources. This +// call is designed to follow a DescribeTags request. +// +// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DeleteTags(input *DeleteTagsInput) (*DeleteTagsOutput, error) { + req, out := c.DeleteTagsRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVolume = "DeleteVolume" + +// DeleteVolumeRequest generates a request for the DeleteVolume operation. +func (c *EC2) DeleteVolumeRequest(input *DeleteVolumeInput) (req *request.Request, output *DeleteVolumeOutput) { + op := &request.Operation{ + Name: opDeleteVolume, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVolumeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteVolumeOutput{} + req.Data = output + return +} + +// Deletes the specified EBS volume. The volume must be in the available state +// (not attached to an instance). +// +// The volume may remain in the deleting state for several minutes. +// +// For more information, see Deleting an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-deleting-volume.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DeleteVolume(input *DeleteVolumeInput) (*DeleteVolumeOutput, error) { + req, out := c.DeleteVolumeRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpc = "DeleteVpc" + +// DeleteVpcRequest generates a request for the DeleteVpc operation. +func (c *EC2) DeleteVpcRequest(input *DeleteVpcInput) (req *request.Request, output *DeleteVpcOutput) { + op := &request.Operation{ + Name: opDeleteVpc, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpcInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteVpcOutput{} + req.Data = output + return +} + +// Deletes the specified VPC. You must detach or delete all gateways and resources +// that are associated with the VPC before you can delete it. For example, you +// must terminate all instances running in the VPC, delete all security groups +// associated with the VPC (except the default one), delete all route tables +// associated with the VPC (except the default one), and so on. +func (c *EC2) DeleteVpc(input *DeleteVpcInput) (*DeleteVpcOutput, error) { + req, out := c.DeleteVpcRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpcEndpoints = "DeleteVpcEndpoints" + +// DeleteVpcEndpointsRequest generates a request for the DeleteVpcEndpoints operation. +func (c *EC2) DeleteVpcEndpointsRequest(input *DeleteVpcEndpointsInput) (req *request.Request, output *DeleteVpcEndpointsOutput) { + op := &request.Operation{ + Name: opDeleteVpcEndpoints, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpcEndpointsInput{} + } + + req = c.newRequest(op, input, output) + output = &DeleteVpcEndpointsOutput{} + req.Data = output + return +} + +// Deletes one or more specified VPC endpoints. Deleting the endpoint also deletes +// the endpoint routes in the route tables that were associated with the endpoint. +func (c *EC2) DeleteVpcEndpoints(input *DeleteVpcEndpointsInput) (*DeleteVpcEndpointsOutput, error) { + req, out := c.DeleteVpcEndpointsRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpcPeeringConnection = "DeleteVpcPeeringConnection" + +// DeleteVpcPeeringConnectionRequest generates a request for the DeleteVpcPeeringConnection operation. +func (c *EC2) DeleteVpcPeeringConnectionRequest(input *DeleteVpcPeeringConnectionInput) (req *request.Request, output *DeleteVpcPeeringConnectionOutput) { + op := &request.Operation{ + Name: opDeleteVpcPeeringConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpcPeeringConnectionInput{} + } + + req = c.newRequest(op, input, output) + output = &DeleteVpcPeeringConnectionOutput{} + req.Data = output + return +} + +// Deletes a VPC peering connection. Either the owner of the requester VPC or +// the owner of the peer VPC can delete the VPC peering connection if it's in +// the active state. The owner of the requester VPC can delete a VPC peering +// connection in the pending-acceptance state. +func (c *EC2) DeleteVpcPeeringConnection(input *DeleteVpcPeeringConnectionInput) (*DeleteVpcPeeringConnectionOutput, error) { + req, out := c.DeleteVpcPeeringConnectionRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpnConnection = "DeleteVpnConnection" + +// DeleteVpnConnectionRequest generates a request for the DeleteVpnConnection operation. +func (c *EC2) DeleteVpnConnectionRequest(input *DeleteVpnConnectionInput) (req *request.Request, output *DeleteVpnConnectionOutput) { + op := &request.Operation{ + Name: opDeleteVpnConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpnConnectionInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteVpnConnectionOutput{} + req.Data = output + return +} + +// Deletes the specified VPN connection. +// +// If you're deleting the VPC and its associated components, we recommend that +// you detach the virtual private gateway from the VPC and delete the VPC before +// deleting the VPN connection. If you believe that the tunnel credentials for +// your VPN connection have been compromised, you can delete the VPN connection +// and create a new one that has new keys, without needing to delete the VPC +// or virtual private gateway. If you create a new VPN connection, you must +// reconfigure the customer gateway using the new configuration information +// returned with the new VPN connection ID. +func (c *EC2) DeleteVpnConnection(input *DeleteVpnConnectionInput) (*DeleteVpnConnectionOutput, error) { + req, out := c.DeleteVpnConnectionRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpnConnectionRoute = "DeleteVpnConnectionRoute" + +// DeleteVpnConnectionRouteRequest generates a request for the DeleteVpnConnectionRoute operation. +func (c *EC2) DeleteVpnConnectionRouteRequest(input *DeleteVpnConnectionRouteInput) (req *request.Request, output *DeleteVpnConnectionRouteOutput) { + op := &request.Operation{ + Name: opDeleteVpnConnectionRoute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpnConnectionRouteInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteVpnConnectionRouteOutput{} + req.Data = output + return +} + +// Deletes the specified static route associated with a VPN connection between +// an existing virtual private gateway and a VPN customer gateway. The static +// route allows traffic to be routed from the virtual private gateway to the +// VPN customer gateway. +func (c *EC2) DeleteVpnConnectionRoute(input *DeleteVpnConnectionRouteInput) (*DeleteVpnConnectionRouteOutput, error) { + req, out := c.DeleteVpnConnectionRouteRequest(input) + err := req.Send() + return out, err +} + +const opDeleteVpnGateway = "DeleteVpnGateway" + +// DeleteVpnGatewayRequest generates a request for the DeleteVpnGateway operation. +func (c *EC2) DeleteVpnGatewayRequest(input *DeleteVpnGatewayInput) (req *request.Request, output *DeleteVpnGatewayOutput) { + op := &request.Operation{ + Name: opDeleteVpnGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteVpnGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeleteVpnGatewayOutput{} + req.Data = output + return +} + +// Deletes the specified virtual private gateway. We recommend that before you +// delete a virtual private gateway, you detach it from the VPC and delete the +// VPN connection. Note that you don't need to delete the virtual private gateway +// if you plan to delete and recreate the VPN connection between your VPC and +// your network. +func (c *EC2) DeleteVpnGateway(input *DeleteVpnGatewayInput) (*DeleteVpnGatewayOutput, error) { + req, out := c.DeleteVpnGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDeregisterImage = "DeregisterImage" + +// DeregisterImageRequest generates a request for the DeregisterImage operation. +func (c *EC2) DeregisterImageRequest(input *DeregisterImageInput) (req *request.Request, output *DeregisterImageOutput) { + op := &request.Operation{ + Name: opDeregisterImage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeregisterImageInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DeregisterImageOutput{} + req.Data = output + return +} + +// Deregisters the specified AMI. After you deregister an AMI, it can't be used +// to launch new instances. +// +// This command does not delete the AMI. +func (c *EC2) DeregisterImage(input *DeregisterImageInput) (*DeregisterImageOutput, error) { + req, out := c.DeregisterImageRequest(input) + err := req.Send() + return out, err +} + +const opDescribeAccountAttributes = "DescribeAccountAttributes" + +// DescribeAccountAttributesRequest generates a request for the DescribeAccountAttributes operation. +func (c *EC2) DescribeAccountAttributesRequest(input *DescribeAccountAttributesInput) (req *request.Request, output *DescribeAccountAttributesOutput) { + op := &request.Operation{ + Name: opDescribeAccountAttributes, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeAccountAttributesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeAccountAttributesOutput{} + req.Data = output + return +} + +// Describes attributes of your AWS account. The following are the supported +// account attributes: +// +// supported-platforms: Indicates whether your account can launch instances +// into EC2-Classic and EC2-VPC, or only into EC2-VPC. +// +// default-vpc: The ID of the default VPC for your account, or none. +// +// max-instances: The maximum number of On-Demand instances that you can +// run. +// +// vpc-max-security-groups-per-interface: The maximum number of security +// groups that you can assign to a network interface. +// +// max-elastic-ips: The maximum number of Elastic IP addresses that you can +// allocate for use with EC2-Classic. +// +// vpc-max-elastic-ips: The maximum number of Elastic IP addresses that you +// can allocate for use with EC2-VPC. +func (c *EC2) DescribeAccountAttributes(input *DescribeAccountAttributesInput) (*DescribeAccountAttributesOutput, error) { + req, out := c.DescribeAccountAttributesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeAddresses = "DescribeAddresses" + +// DescribeAddressesRequest generates a request for the DescribeAddresses operation. +func (c *EC2) DescribeAddressesRequest(input *DescribeAddressesInput) (req *request.Request, output *DescribeAddressesOutput) { + op := &request.Operation{ + Name: opDescribeAddresses, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeAddressesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeAddressesOutput{} + req.Data = output + return +} + +// Describes one or more of your Elastic IP addresses. +// +// An Elastic IP address is for use in either the EC2-Classic platform or in +// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeAddresses(input *DescribeAddressesInput) (*DescribeAddressesOutput, error) { + req, out := c.DescribeAddressesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeAvailabilityZones = "DescribeAvailabilityZones" + +// DescribeAvailabilityZonesRequest generates a request for the DescribeAvailabilityZones operation. +func (c *EC2) DescribeAvailabilityZonesRequest(input *DescribeAvailabilityZonesInput) (req *request.Request, output *DescribeAvailabilityZonesOutput) { + op := &request.Operation{ + Name: opDescribeAvailabilityZones, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeAvailabilityZonesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeAvailabilityZonesOutput{} + req.Data = output + return +} + +// Describes one or more of the Availability Zones that are available to you. +// The results include zones only for the region you're currently using. If +// there is an event impacting an Availability Zone, you can use this request +// to view the state and any provided message for that Availability Zone. +// +// For more information, see Regions and Availability Zones (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeAvailabilityZones(input *DescribeAvailabilityZonesInput) (*DescribeAvailabilityZonesOutput, error) { + req, out := c.DescribeAvailabilityZonesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeBundleTasks = "DescribeBundleTasks" + +// DescribeBundleTasksRequest generates a request for the DescribeBundleTasks operation. +func (c *EC2) DescribeBundleTasksRequest(input *DescribeBundleTasksInput) (req *request.Request, output *DescribeBundleTasksOutput) { + op := &request.Operation{ + Name: opDescribeBundleTasks, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeBundleTasksInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeBundleTasksOutput{} + req.Data = output + return +} + +// Describes one or more of your bundling tasks. +// +// Completed bundle tasks are listed for only a limited time. If your bundle +// task is no longer in the list, you can still register an AMI from it. Just +// use RegisterImage with the Amazon S3 bucket name and image manifest name +// you provided to the bundle task. +func (c *EC2) DescribeBundleTasks(input *DescribeBundleTasksInput) (*DescribeBundleTasksOutput, error) { + req, out := c.DescribeBundleTasksRequest(input) + err := req.Send() + return out, err +} + +const opDescribeClassicLinkInstances = "DescribeClassicLinkInstances" + +// DescribeClassicLinkInstancesRequest generates a request for the DescribeClassicLinkInstances operation. +func (c *EC2) DescribeClassicLinkInstancesRequest(input *DescribeClassicLinkInstancesInput) (req *request.Request, output *DescribeClassicLinkInstancesOutput) { + op := &request.Operation{ + Name: opDescribeClassicLinkInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeClassicLinkInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeClassicLinkInstancesOutput{} + req.Data = output + return +} + +// Describes one or more of your linked EC2-Classic instances. This request +// only returns information about EC2-Classic instances linked to a VPC through +// ClassicLink; you cannot use this request to return information about other +// instances. +func (c *EC2) DescribeClassicLinkInstances(input *DescribeClassicLinkInstancesInput) (*DescribeClassicLinkInstancesOutput, error) { + req, out := c.DescribeClassicLinkInstancesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeConversionTasks = "DescribeConversionTasks" + +// DescribeConversionTasksRequest generates a request for the DescribeConversionTasks operation. +func (c *EC2) DescribeConversionTasksRequest(input *DescribeConversionTasksInput) (req *request.Request, output *DescribeConversionTasksOutput) { + op := &request.Operation{ + Name: opDescribeConversionTasks, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeConversionTasksInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeConversionTasksOutput{} + req.Data = output + return +} + +// Describes one or more of your conversion tasks. For more information, see +// Using the Command Line Tools to Import Your Virtual Machine to Amazon EC2 +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeConversionTasks(input *DescribeConversionTasksInput) (*DescribeConversionTasksOutput, error) { + req, out := c.DescribeConversionTasksRequest(input) + err := req.Send() + return out, err +} + +const opDescribeCustomerGateways = "DescribeCustomerGateways" + +// DescribeCustomerGatewaysRequest generates a request for the DescribeCustomerGateways operation. +func (c *EC2) DescribeCustomerGatewaysRequest(input *DescribeCustomerGatewaysInput) (req *request.Request, output *DescribeCustomerGatewaysOutput) { + op := &request.Operation{ + Name: opDescribeCustomerGateways, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeCustomerGatewaysInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeCustomerGatewaysOutput{} + req.Data = output + return +} + +// Describes one or more of your VPN customer gateways. +// +// For more information about VPN customer gateways, see Adding a Hardware +// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeCustomerGateways(input *DescribeCustomerGatewaysInput) (*DescribeCustomerGatewaysOutput, error) { + req, out := c.DescribeCustomerGatewaysRequest(input) + err := req.Send() + return out, err +} + +const opDescribeDhcpOptions = "DescribeDhcpOptions" + +// DescribeDhcpOptionsRequest generates a request for the DescribeDhcpOptions operation. +func (c *EC2) DescribeDhcpOptionsRequest(input *DescribeDhcpOptionsInput) (req *request.Request, output *DescribeDhcpOptionsOutput) { + op := &request.Operation{ + Name: opDescribeDhcpOptions, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeDhcpOptionsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeDhcpOptionsOutput{} + req.Data = output + return +} + +// Describes one or more of your DHCP options sets. +// +// For more information about DHCP options sets, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeDhcpOptions(input *DescribeDhcpOptionsInput) (*DescribeDhcpOptionsOutput, error) { + req, out := c.DescribeDhcpOptionsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeExportTasks = "DescribeExportTasks" + +// DescribeExportTasksRequest generates a request for the DescribeExportTasks operation. +func (c *EC2) DescribeExportTasksRequest(input *DescribeExportTasksInput) (req *request.Request, output *DescribeExportTasksOutput) { + op := &request.Operation{ + Name: opDescribeExportTasks, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeExportTasksInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeExportTasksOutput{} + req.Data = output + return +} + +// Describes one or more of your export tasks. +func (c *EC2) DescribeExportTasks(input *DescribeExportTasksInput) (*DescribeExportTasksOutput, error) { + req, out := c.DescribeExportTasksRequest(input) + err := req.Send() + return out, err +} + +const opDescribeFlowLogs = "DescribeFlowLogs" + +// DescribeFlowLogsRequest generates a request for the DescribeFlowLogs operation. +func (c *EC2) DescribeFlowLogsRequest(input *DescribeFlowLogsInput) (req *request.Request, output *DescribeFlowLogsOutput) { + op := &request.Operation{ + Name: opDescribeFlowLogs, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeFlowLogsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeFlowLogsOutput{} + req.Data = output + return +} + +// Describes one or more flow logs. To view the information in your flow logs +// (the log streams for the network interfaces), you must use the CloudWatch +// Logs console or the CloudWatch Logs API. +func (c *EC2) DescribeFlowLogs(input *DescribeFlowLogsInput) (*DescribeFlowLogsOutput, error) { + req, out := c.DescribeFlowLogsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeHosts = "DescribeHosts" + +// DescribeHostsRequest generates a request for the DescribeHosts operation. +func (c *EC2) DescribeHostsRequest(input *DescribeHostsInput) (req *request.Request, output *DescribeHostsOutput) { + op := &request.Operation{ + Name: opDescribeHosts, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeHostsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeHostsOutput{} + req.Data = output + return +} + +// Describes one or more of your Dedicated hosts. +// +// The results describe only the Dedicated hosts in the region you're currently +// using. All listed instances consume capacity on your Dedicated host. Dedicated +// hosts that have recently been released will be listed with the state released. +func (c *EC2) DescribeHosts(input *DescribeHostsInput) (*DescribeHostsOutput, error) { + req, out := c.DescribeHostsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeIdFormat = "DescribeIdFormat" + +// DescribeIdFormatRequest generates a request for the DescribeIdFormat operation. +func (c *EC2) DescribeIdFormatRequest(input *DescribeIdFormatInput) (req *request.Request, output *DescribeIdFormatOutput) { + op := &request.Operation{ + Name: opDescribeIdFormat, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeIdFormatInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeIdFormatOutput{} + req.Data = output + return +} + +// Describes the ID format settings for your resources on a per-region basis, +// for example, to view which resource types are enabled for longer IDs. This +// request only returns information about resource types whose ID formats can +// be modified; it does not return information about other resource types. +// +// The following resource types support longer IDs: instance | reservation. +// +// These settings apply to the IAM user who makes the request; they do not +// apply to the entire AWS account. By default, an IAM user defaults to the +// same settings as the root user, unless they explicitly override the settings +// by running the ModifyIdFormat command. Resources created with longer IDs +// are visible to all IAM users, regardless of these settings and provided that +// they have permission to use the relevant Describe command for the resource +// type. +func (c *EC2) DescribeIdFormat(input *DescribeIdFormatInput) (*DescribeIdFormatOutput, error) { + req, out := c.DescribeIdFormatRequest(input) + err := req.Send() + return out, err +} + +const opDescribeImageAttribute = "DescribeImageAttribute" + +// DescribeImageAttributeRequest generates a request for the DescribeImageAttribute operation. +func (c *EC2) DescribeImageAttributeRequest(input *DescribeImageAttributeInput) (req *request.Request, output *DescribeImageAttributeOutput) { + op := &request.Operation{ + Name: opDescribeImageAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeImageAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeImageAttributeOutput{} + req.Data = output + return +} + +// Describes the specified attribute of the specified AMI. You can specify only +// one attribute at a time. +func (c *EC2) DescribeImageAttribute(input *DescribeImageAttributeInput) (*DescribeImageAttributeOutput, error) { + req, out := c.DescribeImageAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeImages = "DescribeImages" + +// DescribeImagesRequest generates a request for the DescribeImages operation. +func (c *EC2) DescribeImagesRequest(input *DescribeImagesInput) (req *request.Request, output *DescribeImagesOutput) { + op := &request.Operation{ + Name: opDescribeImages, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeImagesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeImagesOutput{} + req.Data = output + return +} + +// Describes one or more of the images (AMIs, AKIs, and ARIs) available to you. +// Images available to you include public images, private images that you own, +// and private images owned by other AWS accounts but for which you have explicit +// launch permissions. +// +// Deregistered images are included in the returned results for an unspecified +// interval after deregistration. +func (c *EC2) DescribeImages(input *DescribeImagesInput) (*DescribeImagesOutput, error) { + req, out := c.DescribeImagesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeImportImageTasks = "DescribeImportImageTasks" + +// DescribeImportImageTasksRequest generates a request for the DescribeImportImageTasks operation. +func (c *EC2) DescribeImportImageTasksRequest(input *DescribeImportImageTasksInput) (req *request.Request, output *DescribeImportImageTasksOutput) { + op := &request.Operation{ + Name: opDescribeImportImageTasks, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeImportImageTasksInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeImportImageTasksOutput{} + req.Data = output + return +} + +// Displays details about an import virtual machine or import snapshot tasks +// that are already created. +func (c *EC2) DescribeImportImageTasks(input *DescribeImportImageTasksInput) (*DescribeImportImageTasksOutput, error) { + req, out := c.DescribeImportImageTasksRequest(input) + err := req.Send() + return out, err +} + +const opDescribeImportSnapshotTasks = "DescribeImportSnapshotTasks" + +// DescribeImportSnapshotTasksRequest generates a request for the DescribeImportSnapshotTasks operation. +func (c *EC2) DescribeImportSnapshotTasksRequest(input *DescribeImportSnapshotTasksInput) (req *request.Request, output *DescribeImportSnapshotTasksOutput) { + op := &request.Operation{ + Name: opDescribeImportSnapshotTasks, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeImportSnapshotTasksInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeImportSnapshotTasksOutput{} + req.Data = output + return +} + +// Describes your import snapshot tasks. +func (c *EC2) DescribeImportSnapshotTasks(input *DescribeImportSnapshotTasksInput) (*DescribeImportSnapshotTasksOutput, error) { + req, out := c.DescribeImportSnapshotTasksRequest(input) + err := req.Send() + return out, err +} + +const opDescribeInstanceAttribute = "DescribeInstanceAttribute" + +// DescribeInstanceAttributeRequest generates a request for the DescribeInstanceAttribute operation. +func (c *EC2) DescribeInstanceAttributeRequest(input *DescribeInstanceAttributeInput) (req *request.Request, output *DescribeInstanceAttributeOutput) { + op := &request.Operation{ + Name: opDescribeInstanceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeInstanceAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeInstanceAttributeOutput{} + req.Data = output + return +} + +// Describes the specified attribute of the specified instance. You can specify +// only one attribute at a time. Valid attribute values are: instanceType | +// kernel | ramdisk | userData | disableApiTermination | instanceInitiatedShutdownBehavior +// | rootDeviceName | blockDeviceMapping | productCodes | sourceDestCheck | +// groupSet | ebsOptimized | sriovNetSupport +func (c *EC2) DescribeInstanceAttribute(input *DescribeInstanceAttributeInput) (*DescribeInstanceAttributeOutput, error) { + req, out := c.DescribeInstanceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeInstanceStatus = "DescribeInstanceStatus" + +// DescribeInstanceStatusRequest generates a request for the DescribeInstanceStatus operation. +func (c *EC2) DescribeInstanceStatusRequest(input *DescribeInstanceStatusInput) (req *request.Request, output *DescribeInstanceStatusOutput) { + op := &request.Operation{ + Name: opDescribeInstanceStatus, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeInstanceStatusInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeInstanceStatusOutput{} + req.Data = output + return +} + +// Describes the status of one or more instances. +// +// Instance status includes the following components: +// +// Status checks - Amazon EC2 performs status checks on running EC2 instances +// to identify hardware and software issues. For more information, see Status +// Checks for Your Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html) +// and Troubleshooting Instances with Failed Status Checks (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstances.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// Scheduled events - Amazon EC2 can schedule events (such as reboot, stop, +// or terminate) for your instances related to hardware issues, software updates, +// or system maintenance. For more information, see Scheduled Events for Your +// Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// Instance state - You can manage your instances from the moment you launch +// them through their termination. For more information, see Instance Lifecycle +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeInstanceStatus(input *DescribeInstanceStatusInput) (*DescribeInstanceStatusOutput, error) { + req, out := c.DescribeInstanceStatusRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeInstanceStatusPages(input *DescribeInstanceStatusInput, fn func(p *DescribeInstanceStatusOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeInstanceStatusRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeInstanceStatusOutput), lastPage) + }) +} + +const opDescribeInstances = "DescribeInstances" + +// DescribeInstancesRequest generates a request for the DescribeInstances operation. +func (c *EC2) DescribeInstancesRequest(input *DescribeInstancesInput) (req *request.Request, output *DescribeInstancesOutput) { + op := &request.Operation{ + Name: opDescribeInstances, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeInstancesOutput{} + req.Data = output + return +} + +// Describes one or more of your instances. +// +// If you specify one or more instance IDs, Amazon EC2 returns information +// for those instances. If you do not specify instance IDs, Amazon EC2 returns +// information for all relevant instances. If you specify an instance ID that +// is not valid, an error is returned. If you specify an instance that you do +// not own, it is not included in the returned results. +// +// Recently terminated instances might appear in the returned results. This +// interval is usually less than one hour. +func (c *EC2) DescribeInstances(input *DescribeInstancesInput) (*DescribeInstancesOutput, error) { + req, out := c.DescribeInstancesRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeInstancesPages(input *DescribeInstancesInput, fn func(p *DescribeInstancesOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeInstancesRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeInstancesOutput), lastPage) + }) +} + +const opDescribeInternetGateways = "DescribeInternetGateways" + +// DescribeInternetGatewaysRequest generates a request for the DescribeInternetGateways operation. +func (c *EC2) DescribeInternetGatewaysRequest(input *DescribeInternetGatewaysInput) (req *request.Request, output *DescribeInternetGatewaysOutput) { + op := &request.Operation{ + Name: opDescribeInternetGateways, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeInternetGatewaysInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeInternetGatewaysOutput{} + req.Data = output + return +} + +// Describes one or more of your Internet gateways. +func (c *EC2) DescribeInternetGateways(input *DescribeInternetGatewaysInput) (*DescribeInternetGatewaysOutput, error) { + req, out := c.DescribeInternetGatewaysRequest(input) + err := req.Send() + return out, err +} + +const opDescribeKeyPairs = "DescribeKeyPairs" + +// DescribeKeyPairsRequest generates a request for the DescribeKeyPairs operation. +func (c *EC2) DescribeKeyPairsRequest(input *DescribeKeyPairsInput) (req *request.Request, output *DescribeKeyPairsOutput) { + op := &request.Operation{ + Name: opDescribeKeyPairs, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeKeyPairsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeKeyPairsOutput{} + req.Data = output + return +} + +// Describes one or more of your key pairs. +// +// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeKeyPairs(input *DescribeKeyPairsInput) (*DescribeKeyPairsOutput, error) { + req, out := c.DescribeKeyPairsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeMovingAddresses = "DescribeMovingAddresses" + +// DescribeMovingAddressesRequest generates a request for the DescribeMovingAddresses operation. +func (c *EC2) DescribeMovingAddressesRequest(input *DescribeMovingAddressesInput) (req *request.Request, output *DescribeMovingAddressesOutput) { + op := &request.Operation{ + Name: opDescribeMovingAddresses, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeMovingAddressesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeMovingAddressesOutput{} + req.Data = output + return +} + +// Describes your Elastic IP addresses that are being moved to the EC2-VPC platform, +// or that are being restored to the EC2-Classic platform. This request does +// not return information about any other Elastic IP addresses in your account. +func (c *EC2) DescribeMovingAddresses(input *DescribeMovingAddressesInput) (*DescribeMovingAddressesOutput, error) { + req, out := c.DescribeMovingAddressesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeNatGateways = "DescribeNatGateways" + +// DescribeNatGatewaysRequest generates a request for the DescribeNatGateways operation. +func (c *EC2) DescribeNatGatewaysRequest(input *DescribeNatGatewaysInput) (req *request.Request, output *DescribeNatGatewaysOutput) { + op := &request.Operation{ + Name: opDescribeNatGateways, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeNatGatewaysInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeNatGatewaysOutput{} + req.Data = output + return +} + +// Describes one or more of the your NAT gateways. +func (c *EC2) DescribeNatGateways(input *DescribeNatGatewaysInput) (*DescribeNatGatewaysOutput, error) { + req, out := c.DescribeNatGatewaysRequest(input) + err := req.Send() + return out, err +} + +const opDescribeNetworkAcls = "DescribeNetworkAcls" + +// DescribeNetworkAclsRequest generates a request for the DescribeNetworkAcls operation. +func (c *EC2) DescribeNetworkAclsRequest(input *DescribeNetworkAclsInput) (req *request.Request, output *DescribeNetworkAclsOutput) { + op := &request.Operation{ + Name: opDescribeNetworkAcls, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeNetworkAclsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeNetworkAclsOutput{} + req.Data = output + return +} + +// Describes one or more of your network ACLs. +// +// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeNetworkAcls(input *DescribeNetworkAclsInput) (*DescribeNetworkAclsOutput, error) { + req, out := c.DescribeNetworkAclsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeNetworkInterfaceAttribute = "DescribeNetworkInterfaceAttribute" + +// DescribeNetworkInterfaceAttributeRequest generates a request for the DescribeNetworkInterfaceAttribute operation. +func (c *EC2) DescribeNetworkInterfaceAttributeRequest(input *DescribeNetworkInterfaceAttributeInput) (req *request.Request, output *DescribeNetworkInterfaceAttributeOutput) { + op := &request.Operation{ + Name: opDescribeNetworkInterfaceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeNetworkInterfaceAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeNetworkInterfaceAttributeOutput{} + req.Data = output + return +} + +// Describes a network interface attribute. You can specify only one attribute +// at a time. +func (c *EC2) DescribeNetworkInterfaceAttribute(input *DescribeNetworkInterfaceAttributeInput) (*DescribeNetworkInterfaceAttributeOutput, error) { + req, out := c.DescribeNetworkInterfaceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeNetworkInterfaces = "DescribeNetworkInterfaces" + +// DescribeNetworkInterfacesRequest generates a request for the DescribeNetworkInterfaces operation. +func (c *EC2) DescribeNetworkInterfacesRequest(input *DescribeNetworkInterfacesInput) (req *request.Request, output *DescribeNetworkInterfacesOutput) { + op := &request.Operation{ + Name: opDescribeNetworkInterfaces, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeNetworkInterfacesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeNetworkInterfacesOutput{} + req.Data = output + return +} + +// Describes one or more of your network interfaces. +func (c *EC2) DescribeNetworkInterfaces(input *DescribeNetworkInterfacesInput) (*DescribeNetworkInterfacesOutput, error) { + req, out := c.DescribeNetworkInterfacesRequest(input) + err := req.Send() + return out, err +} + +const opDescribePlacementGroups = "DescribePlacementGroups" + +// DescribePlacementGroupsRequest generates a request for the DescribePlacementGroups operation. +func (c *EC2) DescribePlacementGroupsRequest(input *DescribePlacementGroupsInput) (req *request.Request, output *DescribePlacementGroupsOutput) { + op := &request.Operation{ + Name: opDescribePlacementGroups, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribePlacementGroupsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribePlacementGroupsOutput{} + req.Data = output + return +} + +// Describes one or more of your placement groups. For more information about +// placement groups and cluster instances, see Cluster Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribePlacementGroups(input *DescribePlacementGroupsInput) (*DescribePlacementGroupsOutput, error) { + req, out := c.DescribePlacementGroupsRequest(input) + err := req.Send() + return out, err +} + +const opDescribePrefixLists = "DescribePrefixLists" + +// DescribePrefixListsRequest generates a request for the DescribePrefixLists operation. +func (c *EC2) DescribePrefixListsRequest(input *DescribePrefixListsInput) (req *request.Request, output *DescribePrefixListsOutput) { + op := &request.Operation{ + Name: opDescribePrefixLists, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribePrefixListsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribePrefixListsOutput{} + req.Data = output + return +} + +// Describes available AWS services in a prefix list format, which includes +// the prefix list name and prefix list ID of the service and the IP address +// range for the service. A prefix list ID is required for creating an outbound +// security group rule that allows traffic from a VPC to access an AWS service +// through a VPC endpoint. +func (c *EC2) DescribePrefixLists(input *DescribePrefixListsInput) (*DescribePrefixListsOutput, error) { + req, out := c.DescribePrefixListsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeRegions = "DescribeRegions" + +// DescribeRegionsRequest generates a request for the DescribeRegions operation. +func (c *EC2) DescribeRegionsRequest(input *DescribeRegionsInput) (req *request.Request, output *DescribeRegionsOutput) { + op := &request.Operation{ + Name: opDescribeRegions, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeRegionsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeRegionsOutput{} + req.Data = output + return +} + +// Describes one or more regions that are currently available to you. +// +// For a list of the regions supported by Amazon EC2, see Regions and Endpoints +// (http://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region). +func (c *EC2) DescribeRegions(input *DescribeRegionsInput) (*DescribeRegionsOutput, error) { + req, out := c.DescribeRegionsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeReservedInstances = "DescribeReservedInstances" + +// DescribeReservedInstancesRequest generates a request for the DescribeReservedInstances operation. +func (c *EC2) DescribeReservedInstancesRequest(input *DescribeReservedInstancesInput) (req *request.Request, output *DescribeReservedInstancesOutput) { + op := &request.Operation{ + Name: opDescribeReservedInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeReservedInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeReservedInstancesOutput{} + req.Data = output + return +} + +// Describes one or more of the Reserved Instances that you purchased. +// +// For more information about Reserved Instances, see Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-on-demand-reserved-instances.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeReservedInstances(input *DescribeReservedInstancesInput) (*DescribeReservedInstancesOutput, error) { + req, out := c.DescribeReservedInstancesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeReservedInstancesListings = "DescribeReservedInstancesListings" + +// DescribeReservedInstancesListingsRequest generates a request for the DescribeReservedInstancesListings operation. +func (c *EC2) DescribeReservedInstancesListingsRequest(input *DescribeReservedInstancesListingsInput) (req *request.Request, output *DescribeReservedInstancesListingsOutput) { + op := &request.Operation{ + Name: opDescribeReservedInstancesListings, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeReservedInstancesListingsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeReservedInstancesListingsOutput{} + req.Data = output + return +} + +// Describes your account's Reserved Instance listings in the Reserved Instance +// Marketplace. +// +// The Reserved Instance Marketplace matches sellers who want to resell Reserved +// Instance capacity that they no longer need with buyers who want to purchase +// additional capacity. Reserved Instances bought and sold through the Reserved +// Instance Marketplace work like any other Reserved Instances. +// +// As a seller, you choose to list some or all of your Reserved Instances, +// and you specify the upfront price to receive for them. Your Reserved Instances +// are then listed in the Reserved Instance Marketplace and are available for +// purchase. +// +// As a buyer, you specify the configuration of the Reserved Instance to purchase, +// and the Marketplace matches what you're searching for with what's available. +// The Marketplace first sells the lowest priced Reserved Instances to you, +// and continues to sell available Reserved Instance listings to you until your +// demand is met. You are charged based on the total price of all of the listings +// that you purchase. +// +// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeReservedInstancesListings(input *DescribeReservedInstancesListingsInput) (*DescribeReservedInstancesListingsOutput, error) { + req, out := c.DescribeReservedInstancesListingsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeReservedInstancesModifications = "DescribeReservedInstancesModifications" + +// DescribeReservedInstancesModificationsRequest generates a request for the DescribeReservedInstancesModifications operation. +func (c *EC2) DescribeReservedInstancesModificationsRequest(input *DescribeReservedInstancesModificationsInput) (req *request.Request, output *DescribeReservedInstancesModificationsOutput) { + op := &request.Operation{ + Name: opDescribeReservedInstancesModifications, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeReservedInstancesModificationsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeReservedInstancesModificationsOutput{} + req.Data = output + return +} + +// Describes the modifications made to your Reserved Instances. If no parameter +// is specified, information about all your Reserved Instances modification +// requests is returned. If a modification ID is specified, only information +// about the specific modification is returned. +// +// For more information, see Modifying Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeReservedInstancesModifications(input *DescribeReservedInstancesModificationsInput) (*DescribeReservedInstancesModificationsOutput, error) { + req, out := c.DescribeReservedInstancesModificationsRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeReservedInstancesModificationsPages(input *DescribeReservedInstancesModificationsInput, fn func(p *DescribeReservedInstancesModificationsOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeReservedInstancesModificationsRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeReservedInstancesModificationsOutput), lastPage) + }) +} + +const opDescribeReservedInstancesOfferings = "DescribeReservedInstancesOfferings" + +// DescribeReservedInstancesOfferingsRequest generates a request for the DescribeReservedInstancesOfferings operation. +func (c *EC2) DescribeReservedInstancesOfferingsRequest(input *DescribeReservedInstancesOfferingsInput) (req *request.Request, output *DescribeReservedInstancesOfferingsOutput) { + op := &request.Operation{ + Name: opDescribeReservedInstancesOfferings, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeReservedInstancesOfferingsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeReservedInstancesOfferingsOutput{} + req.Data = output + return +} + +// Describes Reserved Instance offerings that are available for purchase. With +// Reserved Instances, you purchase the right to launch instances for a period +// of time. During that time period, you do not receive insufficient capacity +// errors, and you pay a lower usage rate than the rate charged for On-Demand +// instances for the actual time used. +// +// If you have listed your own Reserved Instances for sale in the Reserved +// Instance Marketplace, they will be excluded from these results. This is to +// ensure that you do not purchase your own Reserved Instances. +// +// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeReservedInstancesOfferings(input *DescribeReservedInstancesOfferingsInput) (*DescribeReservedInstancesOfferingsOutput, error) { + req, out := c.DescribeReservedInstancesOfferingsRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeReservedInstancesOfferingsPages(input *DescribeReservedInstancesOfferingsInput, fn func(p *DescribeReservedInstancesOfferingsOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeReservedInstancesOfferingsRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeReservedInstancesOfferingsOutput), lastPage) + }) +} + +const opDescribeRouteTables = "DescribeRouteTables" + +// DescribeRouteTablesRequest generates a request for the DescribeRouteTables operation. +func (c *EC2) DescribeRouteTablesRequest(input *DescribeRouteTablesInput) (req *request.Request, output *DescribeRouteTablesOutput) { + op := &request.Operation{ + Name: opDescribeRouteTables, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeRouteTablesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeRouteTablesOutput{} + req.Data = output + return +} + +// Describes one or more of your route tables. +// +// Each subnet in your VPC must be associated with a route table. If a subnet +// is not explicitly associated with any route table, it is implicitly associated +// with the main route table. This command does not return the subnet ID for +// implicit associations. +// +// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeRouteTables(input *DescribeRouteTablesInput) (*DescribeRouteTablesOutput, error) { + req, out := c.DescribeRouteTablesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeScheduledInstanceAvailability = "DescribeScheduledInstanceAvailability" + +// DescribeScheduledInstanceAvailabilityRequest generates a request for the DescribeScheduledInstanceAvailability operation. +func (c *EC2) DescribeScheduledInstanceAvailabilityRequest(input *DescribeScheduledInstanceAvailabilityInput) (req *request.Request, output *DescribeScheduledInstanceAvailabilityOutput) { + op := &request.Operation{ + Name: opDescribeScheduledInstanceAvailability, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeScheduledInstanceAvailabilityInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeScheduledInstanceAvailabilityOutput{} + req.Data = output + return +} + +// Finds available schedules that meet the specified criteria. +// +// You can search for an available schedule no more than 3 months in advance. +// You must meet the minimum required duration of 1,200 hours per year. For +// example, the minimum daily schedule is 4 hours, the minimum weekly schedule +// is 24 hours, and the minimum monthly schedule is 100 hours. +// +// After you find a schedule that meets your needs, call PurchaseScheduledInstances +// to purchase Scheduled Instances with that schedule. +func (c *EC2) DescribeScheduledInstanceAvailability(input *DescribeScheduledInstanceAvailabilityInput) (*DescribeScheduledInstanceAvailabilityOutput, error) { + req, out := c.DescribeScheduledInstanceAvailabilityRequest(input) + err := req.Send() + return out, err +} + +const opDescribeScheduledInstances = "DescribeScheduledInstances" + +// DescribeScheduledInstancesRequest generates a request for the DescribeScheduledInstances operation. +func (c *EC2) DescribeScheduledInstancesRequest(input *DescribeScheduledInstancesInput) (req *request.Request, output *DescribeScheduledInstancesOutput) { + op := &request.Operation{ + Name: opDescribeScheduledInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeScheduledInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeScheduledInstancesOutput{} + req.Data = output + return +} + +// Describes one or more of your Scheduled Instances. +func (c *EC2) DescribeScheduledInstances(input *DescribeScheduledInstancesInput) (*DescribeScheduledInstancesOutput, error) { + req, out := c.DescribeScheduledInstancesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSecurityGroups = "DescribeSecurityGroups" + +// DescribeSecurityGroupsRequest generates a request for the DescribeSecurityGroups operation. +func (c *EC2) DescribeSecurityGroupsRequest(input *DescribeSecurityGroupsInput) (req *request.Request, output *DescribeSecurityGroupsOutput) { + op := &request.Operation{ + Name: opDescribeSecurityGroups, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSecurityGroupsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSecurityGroupsOutput{} + req.Data = output + return +} + +// Describes one or more of your security groups. +// +// A security group is for use with instances either in the EC2-Classic platform +// or in a specific VPC. For more information, see Amazon EC2 Security Groups +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) +// in the Amazon Elastic Compute Cloud User Guide and Security Groups for Your +// VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeSecurityGroups(input *DescribeSecurityGroupsInput) (*DescribeSecurityGroupsOutput, error) { + req, out := c.DescribeSecurityGroupsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSnapshotAttribute = "DescribeSnapshotAttribute" + +// DescribeSnapshotAttributeRequest generates a request for the DescribeSnapshotAttribute operation. +func (c *EC2) DescribeSnapshotAttributeRequest(input *DescribeSnapshotAttributeInput) (req *request.Request, output *DescribeSnapshotAttributeOutput) { + op := &request.Operation{ + Name: opDescribeSnapshotAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSnapshotAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSnapshotAttributeOutput{} + req.Data = output + return +} + +// Describes the specified attribute of the specified snapshot. You can specify +// only one attribute at a time. +// +// For more information about EBS snapshots, see Amazon EBS Snapshots in the +// Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeSnapshotAttribute(input *DescribeSnapshotAttributeInput) (*DescribeSnapshotAttributeOutput, error) { + req, out := c.DescribeSnapshotAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSnapshots = "DescribeSnapshots" + +// DescribeSnapshotsRequest generates a request for the DescribeSnapshots operation. +func (c *EC2) DescribeSnapshotsRequest(input *DescribeSnapshotsInput) (req *request.Request, output *DescribeSnapshotsOutput) { + op := &request.Operation{ + Name: opDescribeSnapshots, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeSnapshotsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSnapshotsOutput{} + req.Data = output + return +} + +// Describes one or more of the EBS snapshots available to you. Available snapshots +// include public snapshots available for any AWS account to launch, private +// snapshots that you own, and private snapshots owned by another AWS account +// but for which you've been given explicit create volume permissions. +// +// The create volume permissions fall into the following categories: +// +// public: The owner of the snapshot granted create volume permissions for +// the snapshot to the all group. All AWS accounts have create volume permissions +// for these snapshots. explicit: The owner of the snapshot granted create volume +// permissions to a specific AWS account. implicit: An AWS account has implicit +// create volume permissions for all snapshots it owns. The list of snapshots +// returned can be modified by specifying snapshot IDs, snapshot owners, or +// AWS accounts with create volume permissions. If no options are specified, +// Amazon EC2 returns all snapshots for which you have create volume permissions. +// +// If you specify one or more snapshot IDs, only snapshots that have the specified +// IDs are returned. If you specify an invalid snapshot ID, an error is returned. +// If you specify a snapshot ID for which you do not have access, it is not +// included in the returned results. +// +// If you specify one or more snapshot owners, only snapshots from the specified +// owners and for which you have access are returned. The results can include +// the AWS account IDs of the specified owners, amazon for snapshots owned by +// Amazon, or self for snapshots that you own. +// +// If you specify a list of restorable users, only snapshots with create snapshot +// permissions for those users are returned. You can specify AWS account IDs +// (if you own the snapshots), self for snapshots for which you own or have +// explicit permissions, or all for public snapshots. +// +// If you are describing a long list of snapshots, you can paginate the output +// to make the list more manageable. The MaxResults parameter sets the maximum +// number of results returned in a single page. If the list of results exceeds +// your MaxResults value, then that number of results is returned along with +// a NextToken value that can be passed to a subsequent DescribeSnapshots request +// to retrieve the remaining results. +// +// For more information about EBS snapshots, see Amazon EBS Snapshots in the +// Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeSnapshots(input *DescribeSnapshotsInput) (*DescribeSnapshotsOutput, error) { + req, out := c.DescribeSnapshotsRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeSnapshotsPages(input *DescribeSnapshotsInput, fn func(p *DescribeSnapshotsOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeSnapshotsRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeSnapshotsOutput), lastPage) + }) +} + +const opDescribeSpotDatafeedSubscription = "DescribeSpotDatafeedSubscription" + +// DescribeSpotDatafeedSubscriptionRequest generates a request for the DescribeSpotDatafeedSubscription operation. +func (c *EC2) DescribeSpotDatafeedSubscriptionRequest(input *DescribeSpotDatafeedSubscriptionInput) (req *request.Request, output *DescribeSpotDatafeedSubscriptionOutput) { + op := &request.Operation{ + Name: opDescribeSpotDatafeedSubscription, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSpotDatafeedSubscriptionInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotDatafeedSubscriptionOutput{} + req.Data = output + return +} + +// Describes the data feed for Spot instances. For more information, see Spot +// Instance Data Feed (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeSpotDatafeedSubscription(input *DescribeSpotDatafeedSubscriptionInput) (*DescribeSpotDatafeedSubscriptionOutput, error) { + req, out := c.DescribeSpotDatafeedSubscriptionRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSpotFleetInstances = "DescribeSpotFleetInstances" + +// DescribeSpotFleetInstancesRequest generates a request for the DescribeSpotFleetInstances operation. +func (c *EC2) DescribeSpotFleetInstancesRequest(input *DescribeSpotFleetInstancesInput) (req *request.Request, output *DescribeSpotFleetInstancesOutput) { + op := &request.Operation{ + Name: opDescribeSpotFleetInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSpotFleetInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotFleetInstancesOutput{} + req.Data = output + return +} + +// Describes the running instances for the specified Spot fleet. +func (c *EC2) DescribeSpotFleetInstances(input *DescribeSpotFleetInstancesInput) (*DescribeSpotFleetInstancesOutput, error) { + req, out := c.DescribeSpotFleetInstancesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSpotFleetRequestHistory = "DescribeSpotFleetRequestHistory" + +// DescribeSpotFleetRequestHistoryRequest generates a request for the DescribeSpotFleetRequestHistory operation. +func (c *EC2) DescribeSpotFleetRequestHistoryRequest(input *DescribeSpotFleetRequestHistoryInput) (req *request.Request, output *DescribeSpotFleetRequestHistoryOutput) { + op := &request.Operation{ + Name: opDescribeSpotFleetRequestHistory, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSpotFleetRequestHistoryInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotFleetRequestHistoryOutput{} + req.Data = output + return +} + +// Describes the events for the specified Spot fleet request during the specified +// time. +// +// Spot fleet events are delayed by up to 30 seconds before they can be described. +// This ensures that you can query by the last evaluated time and not miss a +// recorded event. +func (c *EC2) DescribeSpotFleetRequestHistory(input *DescribeSpotFleetRequestHistoryInput) (*DescribeSpotFleetRequestHistoryOutput, error) { + req, out := c.DescribeSpotFleetRequestHistoryRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSpotFleetRequests = "DescribeSpotFleetRequests" + +// DescribeSpotFleetRequestsRequest generates a request for the DescribeSpotFleetRequests operation. +func (c *EC2) DescribeSpotFleetRequestsRequest(input *DescribeSpotFleetRequestsInput) (req *request.Request, output *DescribeSpotFleetRequestsOutput) { + op := &request.Operation{ + Name: opDescribeSpotFleetRequests, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSpotFleetRequestsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotFleetRequestsOutput{} + req.Data = output + return +} + +// Describes your Spot fleet requests. +func (c *EC2) DescribeSpotFleetRequests(input *DescribeSpotFleetRequestsInput) (*DescribeSpotFleetRequestsOutput, error) { + req, out := c.DescribeSpotFleetRequestsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSpotInstanceRequests = "DescribeSpotInstanceRequests" + +// DescribeSpotInstanceRequestsRequest generates a request for the DescribeSpotInstanceRequests operation. +func (c *EC2) DescribeSpotInstanceRequestsRequest(input *DescribeSpotInstanceRequestsInput) (req *request.Request, output *DescribeSpotInstanceRequestsOutput) { + op := &request.Operation{ + Name: opDescribeSpotInstanceRequests, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSpotInstanceRequestsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotInstanceRequestsOutput{} + req.Data = output + return +} + +// Describes the Spot instance requests that belong to your account. Spot instances +// are instances that Amazon EC2 launches when the bid price that you specify +// exceeds the current Spot price. Amazon EC2 periodically sets the Spot price +// based on available Spot instance capacity and current Spot instance requests. +// For more information, see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// You can use DescribeSpotInstanceRequests to find a running Spot instance +// by examining the response. If the status of the Spot instance is fulfilled, +// the instance ID appears in the response and contains the identifier of the +// instance. Alternatively, you can use DescribeInstances with a filter to look +// for instances where the instance lifecycle is spot. +func (c *EC2) DescribeSpotInstanceRequests(input *DescribeSpotInstanceRequestsInput) (*DescribeSpotInstanceRequestsOutput, error) { + req, out := c.DescribeSpotInstanceRequestsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeSpotPriceHistory = "DescribeSpotPriceHistory" + +// DescribeSpotPriceHistoryRequest generates a request for the DescribeSpotPriceHistory operation. +func (c *EC2) DescribeSpotPriceHistoryRequest(input *DescribeSpotPriceHistoryInput) (req *request.Request, output *DescribeSpotPriceHistoryOutput) { + op := &request.Operation{ + Name: opDescribeSpotPriceHistory, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeSpotPriceHistoryInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSpotPriceHistoryOutput{} + req.Data = output + return +} + +// Describes the Spot price history. The prices returned are listed in chronological +// order, from the oldest to the most recent, for up to the past 90 days. For +// more information, see Spot Instance Pricing History (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-history.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// When you specify a start and end time, this operation returns the prices +// of the instance types within the time range that you specified and the time +// when the price changed. The price is valid within the time period that you +// specified; the response merely indicates the last time that the price changed. +func (c *EC2) DescribeSpotPriceHistory(input *DescribeSpotPriceHistoryInput) (*DescribeSpotPriceHistoryOutput, error) { + req, out := c.DescribeSpotPriceHistoryRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeSpotPriceHistoryPages(input *DescribeSpotPriceHistoryInput, fn func(p *DescribeSpotPriceHistoryOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeSpotPriceHistoryRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeSpotPriceHistoryOutput), lastPage) + }) +} + +const opDescribeSubnets = "DescribeSubnets" + +// DescribeSubnetsRequest generates a request for the DescribeSubnets operation. +func (c *EC2) DescribeSubnetsRequest(input *DescribeSubnetsInput) (req *request.Request, output *DescribeSubnetsOutput) { + op := &request.Operation{ + Name: opDescribeSubnets, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeSubnetsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeSubnetsOutput{} + req.Data = output + return +} + +// Describes one or more of your subnets. +// +// For more information about subnets, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeSubnets(input *DescribeSubnetsInput) (*DescribeSubnetsOutput, error) { + req, out := c.DescribeSubnetsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeTags = "DescribeTags" + +// DescribeTagsRequest generates a request for the DescribeTags operation. +func (c *EC2) DescribeTagsRequest(input *DescribeTagsInput) (req *request.Request, output *DescribeTagsOutput) { + op := &request.Operation{ + Name: opDescribeTags, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeTagsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeTagsOutput{} + req.Data = output + return +} + +// Describes one or more of the tags for your EC2 resources. +// +// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeTags(input *DescribeTagsInput) (*DescribeTagsOutput, error) { + req, out := c.DescribeTagsRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeTagsPages(input *DescribeTagsInput, fn func(p *DescribeTagsOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeTagsRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeTagsOutput), lastPage) + }) +} + +const opDescribeVolumeAttribute = "DescribeVolumeAttribute" + +// DescribeVolumeAttributeRequest generates a request for the DescribeVolumeAttribute operation. +func (c *EC2) DescribeVolumeAttributeRequest(input *DescribeVolumeAttributeInput) (req *request.Request, output *DescribeVolumeAttributeOutput) { + op := &request.Operation{ + Name: opDescribeVolumeAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVolumeAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVolumeAttributeOutput{} + req.Data = output + return +} + +// Describes the specified attribute of the specified volume. You can specify +// only one attribute at a time. +// +// For more information about EBS volumes, see Amazon EBS Volumes in the Amazon +// Elastic Compute Cloud User Guide. +func (c *EC2) DescribeVolumeAttribute(input *DescribeVolumeAttributeInput) (*DescribeVolumeAttributeOutput, error) { + req, out := c.DescribeVolumeAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVolumeStatus = "DescribeVolumeStatus" + +// DescribeVolumeStatusRequest generates a request for the DescribeVolumeStatus operation. +func (c *EC2) DescribeVolumeStatusRequest(input *DescribeVolumeStatusInput) (req *request.Request, output *DescribeVolumeStatusOutput) { + op := &request.Operation{ + Name: opDescribeVolumeStatus, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeVolumeStatusInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVolumeStatusOutput{} + req.Data = output + return +} + +// Describes the status of the specified volumes. Volume status provides the +// result of the checks performed on your volumes to determine events that can +// impair the performance of your volumes. The performance of a volume can be +// affected if an issue occurs on the volume's underlying host. If the volume's +// underlying host experiences a power outage or system issue, after the system +// is restored, there could be data inconsistencies on the volume. Volume events +// notify you if this occurs. Volume actions notify you if any action needs +// to be taken in response to the event. +// +// The DescribeVolumeStatus operation provides the following information about +// the specified volumes: +// +// Status: Reflects the current status of the volume. The possible values are +// ok, impaired , warning, or insufficient-data. If all checks pass, the overall +// status of the volume is ok. If the check fails, the overall status is impaired. +// If the status is insufficient-data, then the checks may still be taking place +// on your volume at the time. We recommend that you retry the request. For +// more information on volume status, see Monitoring the Status of Your Volumes +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-volume-status.html). +// +// Events: Reflect the cause of a volume status and may require you to take +// action. For example, if your volume returns an impaired status, then the +// volume event might be potential-data-inconsistency. This means that your +// volume has been affected by an issue with the underlying host, has all I/O +// operations disabled, and may have inconsistent data. +// +// Actions: Reflect the actions you may have to take in response to an event. +// For example, if the status of the volume is impaired and the volume event +// shows potential-data-inconsistency, then the action shows enable-volume-io. +// This means that you may want to enable the I/O operations for the volume +// by calling the EnableVolumeIO action and then check the volume for data consistency. +// +// Volume status is based on the volume status checks, and does not reflect +// the volume state. Therefore, volume status does not indicate volumes in the +// error state (for example, when a volume is incapable of accepting I/O.) +func (c *EC2) DescribeVolumeStatus(input *DescribeVolumeStatusInput) (*DescribeVolumeStatusOutput, error) { + req, out := c.DescribeVolumeStatusRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeVolumeStatusPages(input *DescribeVolumeStatusInput, fn func(p *DescribeVolumeStatusOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeVolumeStatusRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeVolumeStatusOutput), lastPage) + }) +} + +const opDescribeVolumes = "DescribeVolumes" + +// DescribeVolumesRequest generates a request for the DescribeVolumes operation. +func (c *EC2) DescribeVolumesRequest(input *DescribeVolumesInput) (req *request.Request, output *DescribeVolumesOutput) { + op := &request.Operation{ + Name: opDescribeVolumes, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + LimitToken: "MaxResults", + TruncationToken: "", + }, + } + + if input == nil { + input = &DescribeVolumesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVolumesOutput{} + req.Data = output + return +} + +// Describes the specified EBS volumes. +// +// If you are describing a long list of volumes, you can paginate the output +// to make the list more manageable. The MaxResults parameter sets the maximum +// number of results returned in a single page. If the list of results exceeds +// your MaxResults value, then that number of results is returned along with +// a NextToken value that can be passed to a subsequent DescribeVolumes request +// to retrieve the remaining results. +// +// For more information about EBS volumes, see Amazon EBS Volumes in the Amazon +// Elastic Compute Cloud User Guide. +func (c *EC2) DescribeVolumes(input *DescribeVolumesInput) (*DescribeVolumesOutput, error) { + req, out := c.DescribeVolumesRequest(input) + err := req.Send() + return out, err +} + +func (c *EC2) DescribeVolumesPages(input *DescribeVolumesInput, fn func(p *DescribeVolumesOutput, lastPage bool) (shouldContinue bool)) error { + page, _ := c.DescribeVolumesRequest(input) + page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) + return page.EachPage(func(p interface{}, lastPage bool) bool { + return fn(p.(*DescribeVolumesOutput), lastPage) + }) +} + +const opDescribeVpcAttribute = "DescribeVpcAttribute" + +// DescribeVpcAttributeRequest generates a request for the DescribeVpcAttribute operation. +func (c *EC2) DescribeVpcAttributeRequest(input *DescribeVpcAttributeInput) (req *request.Request, output *DescribeVpcAttributeOutput) { + op := &request.Operation{ + Name: opDescribeVpcAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcAttributeInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcAttributeOutput{} + req.Data = output + return +} + +// Describes the specified attribute of the specified VPC. You can specify only +// one attribute at a time. +func (c *EC2) DescribeVpcAttribute(input *DescribeVpcAttributeInput) (*DescribeVpcAttributeOutput, error) { + req, out := c.DescribeVpcAttributeRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcClassicLink = "DescribeVpcClassicLink" + +// DescribeVpcClassicLinkRequest generates a request for the DescribeVpcClassicLink operation. +func (c *EC2) DescribeVpcClassicLinkRequest(input *DescribeVpcClassicLinkInput) (req *request.Request, output *DescribeVpcClassicLinkOutput) { + op := &request.Operation{ + Name: opDescribeVpcClassicLink, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcClassicLinkInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcClassicLinkOutput{} + req.Data = output + return +} + +// Describes the ClassicLink status of one or more VPCs. +func (c *EC2) DescribeVpcClassicLink(input *DescribeVpcClassicLinkInput) (*DescribeVpcClassicLinkOutput, error) { + req, out := c.DescribeVpcClassicLinkRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcClassicLinkDnsSupport = "DescribeVpcClassicLinkDnsSupport" + +// DescribeVpcClassicLinkDnsSupportRequest generates a request for the DescribeVpcClassicLinkDnsSupport operation. +func (c *EC2) DescribeVpcClassicLinkDnsSupportRequest(input *DescribeVpcClassicLinkDnsSupportInput) (req *request.Request, output *DescribeVpcClassicLinkDnsSupportOutput) { + op := &request.Operation{ + Name: opDescribeVpcClassicLinkDnsSupport, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcClassicLinkDnsSupportInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcClassicLinkDnsSupportOutput{} + req.Data = output + return +} + +// Describes the ClassicLink DNS support status of one or more VPCs. If enabled, +// the DNS hostname of a linked EC2-Classic instance resolves to its private +// IP address when addressed from an instance in the VPC to which it's linked. +// Similarly, the DNS hostname of an instance in a VPC resolves to its private +// IP address when addressed from a linked EC2-Classic instance. For more information +// about ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DescribeVpcClassicLinkDnsSupport(input *DescribeVpcClassicLinkDnsSupportInput) (*DescribeVpcClassicLinkDnsSupportOutput, error) { + req, out := c.DescribeVpcClassicLinkDnsSupportRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcEndpointServices = "DescribeVpcEndpointServices" + +// DescribeVpcEndpointServicesRequest generates a request for the DescribeVpcEndpointServices operation. +func (c *EC2) DescribeVpcEndpointServicesRequest(input *DescribeVpcEndpointServicesInput) (req *request.Request, output *DescribeVpcEndpointServicesOutput) { + op := &request.Operation{ + Name: opDescribeVpcEndpointServices, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcEndpointServicesInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcEndpointServicesOutput{} + req.Data = output + return +} + +// Describes all supported AWS services that can be specified when creating +// a VPC endpoint. +func (c *EC2) DescribeVpcEndpointServices(input *DescribeVpcEndpointServicesInput) (*DescribeVpcEndpointServicesOutput, error) { + req, out := c.DescribeVpcEndpointServicesRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcEndpoints = "DescribeVpcEndpoints" + +// DescribeVpcEndpointsRequest generates a request for the DescribeVpcEndpoints operation. +func (c *EC2) DescribeVpcEndpointsRequest(input *DescribeVpcEndpointsInput) (req *request.Request, output *DescribeVpcEndpointsOutput) { + op := &request.Operation{ + Name: opDescribeVpcEndpoints, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcEndpointsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcEndpointsOutput{} + req.Data = output + return +} + +// Describes one or more of your VPC endpoints. +func (c *EC2) DescribeVpcEndpoints(input *DescribeVpcEndpointsInput) (*DescribeVpcEndpointsOutput, error) { + req, out := c.DescribeVpcEndpointsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcPeeringConnections = "DescribeVpcPeeringConnections" + +// DescribeVpcPeeringConnectionsRequest generates a request for the DescribeVpcPeeringConnections operation. +func (c *EC2) DescribeVpcPeeringConnectionsRequest(input *DescribeVpcPeeringConnectionsInput) (req *request.Request, output *DescribeVpcPeeringConnectionsOutput) { + op := &request.Operation{ + Name: opDescribeVpcPeeringConnections, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcPeeringConnectionsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcPeeringConnectionsOutput{} + req.Data = output + return +} + +// Describes one or more of your VPC peering connections. +func (c *EC2) DescribeVpcPeeringConnections(input *DescribeVpcPeeringConnectionsInput) (*DescribeVpcPeeringConnectionsOutput, error) { + req, out := c.DescribeVpcPeeringConnectionsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpcs = "DescribeVpcs" + +// DescribeVpcsRequest generates a request for the DescribeVpcs operation. +func (c *EC2) DescribeVpcsRequest(input *DescribeVpcsInput) (req *request.Request, output *DescribeVpcsOutput) { + op := &request.Operation{ + Name: opDescribeVpcs, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpcsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpcsOutput{} + req.Data = output + return +} + +// Describes one or more of your VPCs. +func (c *EC2) DescribeVpcs(input *DescribeVpcsInput) (*DescribeVpcsOutput, error) { + req, out := c.DescribeVpcsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpnConnections = "DescribeVpnConnections" + +// DescribeVpnConnectionsRequest generates a request for the DescribeVpnConnections operation. +func (c *EC2) DescribeVpnConnectionsRequest(input *DescribeVpnConnectionsInput) (req *request.Request, output *DescribeVpnConnectionsOutput) { + op := &request.Operation{ + Name: opDescribeVpnConnections, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpnConnectionsInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpnConnectionsOutput{} + req.Data = output + return +} + +// Describes one or more of your VPN connections. +// +// For more information about VPN connections, see Adding a Hardware Virtual +// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeVpnConnections(input *DescribeVpnConnectionsInput) (*DescribeVpnConnectionsOutput, error) { + req, out := c.DescribeVpnConnectionsRequest(input) + err := req.Send() + return out, err +} + +const opDescribeVpnGateways = "DescribeVpnGateways" + +// DescribeVpnGatewaysRequest generates a request for the DescribeVpnGateways operation. +func (c *EC2) DescribeVpnGatewaysRequest(input *DescribeVpnGatewaysInput) (req *request.Request, output *DescribeVpnGatewaysOutput) { + op := &request.Operation{ + Name: opDescribeVpnGateways, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeVpnGatewaysInput{} + } + + req = c.newRequest(op, input, output) + output = &DescribeVpnGatewaysOutput{} + req.Data = output + return +} + +// Describes one or more of your virtual private gateways. +// +// For more information about virtual private gateways, see Adding an IPsec +// Hardware VPN to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DescribeVpnGateways(input *DescribeVpnGatewaysInput) (*DescribeVpnGatewaysOutput, error) { + req, out := c.DescribeVpnGatewaysRequest(input) + err := req.Send() + return out, err +} + +const opDetachClassicLinkVpc = "DetachClassicLinkVpc" + +// DetachClassicLinkVpcRequest generates a request for the DetachClassicLinkVpc operation. +func (c *EC2) DetachClassicLinkVpcRequest(input *DetachClassicLinkVpcInput) (req *request.Request, output *DetachClassicLinkVpcOutput) { + op := &request.Operation{ + Name: opDetachClassicLinkVpc, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DetachClassicLinkVpcInput{} + } + + req = c.newRequest(op, input, output) + output = &DetachClassicLinkVpcOutput{} + req.Data = output + return +} + +// Unlinks (detaches) a linked EC2-Classic instance from a VPC. After the instance +// has been unlinked, the VPC security groups are no longer associated with +// it. An instance is automatically unlinked from a VPC when it's stopped. +func (c *EC2) DetachClassicLinkVpc(input *DetachClassicLinkVpcInput) (*DetachClassicLinkVpcOutput, error) { + req, out := c.DetachClassicLinkVpcRequest(input) + err := req.Send() + return out, err +} + +const opDetachInternetGateway = "DetachInternetGateway" + +// DetachInternetGatewayRequest generates a request for the DetachInternetGateway operation. +func (c *EC2) DetachInternetGatewayRequest(input *DetachInternetGatewayInput) (req *request.Request, output *DetachInternetGatewayOutput) { + op := &request.Operation{ + Name: opDetachInternetGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DetachInternetGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DetachInternetGatewayOutput{} + req.Data = output + return +} + +// Detaches an Internet gateway from a VPC, disabling connectivity between the +// Internet and the VPC. The VPC must not contain any running instances with +// Elastic IP addresses. +func (c *EC2) DetachInternetGateway(input *DetachInternetGatewayInput) (*DetachInternetGatewayOutput, error) { + req, out := c.DetachInternetGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDetachNetworkInterface = "DetachNetworkInterface" + +// DetachNetworkInterfaceRequest generates a request for the DetachNetworkInterface operation. +func (c *EC2) DetachNetworkInterfaceRequest(input *DetachNetworkInterfaceInput) (req *request.Request, output *DetachNetworkInterfaceOutput) { + op := &request.Operation{ + Name: opDetachNetworkInterface, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DetachNetworkInterfaceInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DetachNetworkInterfaceOutput{} + req.Data = output + return +} + +// Detaches a network interface from an instance. +func (c *EC2) DetachNetworkInterface(input *DetachNetworkInterfaceInput) (*DetachNetworkInterfaceOutput, error) { + req, out := c.DetachNetworkInterfaceRequest(input) + err := req.Send() + return out, err +} + +const opDetachVolume = "DetachVolume" + +// DetachVolumeRequest generates a request for the DetachVolume operation. +func (c *EC2) DetachVolumeRequest(input *DetachVolumeInput) (req *request.Request, output *VolumeAttachment) { + op := &request.Operation{ + Name: opDetachVolume, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DetachVolumeInput{} + } + + req = c.newRequest(op, input, output) + output = &VolumeAttachment{} + req.Data = output + return +} + +// Detaches an EBS volume from an instance. Make sure to unmount any file systems +// on the device within your operating system before detaching the volume. Failure +// to do so results in the volume being stuck in a busy state while detaching. +// +// If an Amazon EBS volume is the root device of an instance, it can't be detached +// while the instance is running. To detach the root volume, stop the instance +// first. +// +// When a volume with an AWS Marketplace product code is detached from an instance, +// the product code is no longer associated with the instance. +// +// For more information, see Detaching an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-detaching-volume.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DetachVolume(input *DetachVolumeInput) (*VolumeAttachment, error) { + req, out := c.DetachVolumeRequest(input) + err := req.Send() + return out, err +} + +const opDetachVpnGateway = "DetachVpnGateway" + +// DetachVpnGatewayRequest generates a request for the DetachVpnGateway operation. +func (c *EC2) DetachVpnGatewayRequest(input *DetachVpnGatewayInput) (req *request.Request, output *DetachVpnGatewayOutput) { + op := &request.Operation{ + Name: opDetachVpnGateway, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DetachVpnGatewayInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DetachVpnGatewayOutput{} + req.Data = output + return +} + +// Detaches a virtual private gateway from a VPC. You do this if you're planning +// to turn off the VPC and not use it anymore. You can confirm a virtual private +// gateway has been completely detached from a VPC by describing the virtual +// private gateway (any attachments to the virtual private gateway are also +// described). +// +// You must wait for the attachment's state to switch to detached before you +// can delete the VPC or attach a different VPC to the virtual private gateway. +func (c *EC2) DetachVpnGateway(input *DetachVpnGatewayInput) (*DetachVpnGatewayOutput, error) { + req, out := c.DetachVpnGatewayRequest(input) + err := req.Send() + return out, err +} + +const opDisableVgwRoutePropagation = "DisableVgwRoutePropagation" + +// DisableVgwRoutePropagationRequest generates a request for the DisableVgwRoutePropagation operation. +func (c *EC2) DisableVgwRoutePropagationRequest(input *DisableVgwRoutePropagationInput) (req *request.Request, output *DisableVgwRoutePropagationOutput) { + op := &request.Operation{ + Name: opDisableVgwRoutePropagation, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DisableVgwRoutePropagationInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DisableVgwRoutePropagationOutput{} + req.Data = output + return +} + +// Disables a virtual private gateway (VGW) from propagating routes to a specified +// route table of a VPC. +func (c *EC2) DisableVgwRoutePropagation(input *DisableVgwRoutePropagationInput) (*DisableVgwRoutePropagationOutput, error) { + req, out := c.DisableVgwRoutePropagationRequest(input) + err := req.Send() + return out, err +} + +const opDisableVpcClassicLink = "DisableVpcClassicLink" + +// DisableVpcClassicLinkRequest generates a request for the DisableVpcClassicLink operation. +func (c *EC2) DisableVpcClassicLinkRequest(input *DisableVpcClassicLinkInput) (req *request.Request, output *DisableVpcClassicLinkOutput) { + op := &request.Operation{ + Name: opDisableVpcClassicLink, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DisableVpcClassicLinkInput{} + } + + req = c.newRequest(op, input, output) + output = &DisableVpcClassicLinkOutput{} + req.Data = output + return +} + +// Disables ClassicLink for a VPC. You cannot disable ClassicLink for a VPC +// that has EC2-Classic instances linked to it. +func (c *EC2) DisableVpcClassicLink(input *DisableVpcClassicLinkInput) (*DisableVpcClassicLinkOutput, error) { + req, out := c.DisableVpcClassicLinkRequest(input) + err := req.Send() + return out, err +} + +const opDisableVpcClassicLinkDnsSupport = "DisableVpcClassicLinkDnsSupport" + +// DisableVpcClassicLinkDnsSupportRequest generates a request for the DisableVpcClassicLinkDnsSupport operation. +func (c *EC2) DisableVpcClassicLinkDnsSupportRequest(input *DisableVpcClassicLinkDnsSupportInput) (req *request.Request, output *DisableVpcClassicLinkDnsSupportOutput) { + op := &request.Operation{ + Name: opDisableVpcClassicLinkDnsSupport, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DisableVpcClassicLinkDnsSupportInput{} + } + + req = c.newRequest(op, input, output) + output = &DisableVpcClassicLinkDnsSupportOutput{} + req.Data = output + return +} + +// Disables ClassicLink DNS support for a VPC. If disabled, DNS hostnames resolve +// to public IP addresses when addressed between a linked EC2-Classic instance +// and instances in the VPC to which it's linked. For more information about +// ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) DisableVpcClassicLinkDnsSupport(input *DisableVpcClassicLinkDnsSupportInput) (*DisableVpcClassicLinkDnsSupportOutput, error) { + req, out := c.DisableVpcClassicLinkDnsSupportRequest(input) + err := req.Send() + return out, err +} + +const opDisassociateAddress = "DisassociateAddress" + +// DisassociateAddressRequest generates a request for the DisassociateAddress operation. +func (c *EC2) DisassociateAddressRequest(input *DisassociateAddressInput) (req *request.Request, output *DisassociateAddressOutput) { + op := &request.Operation{ + Name: opDisassociateAddress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DisassociateAddressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DisassociateAddressOutput{} + req.Data = output + return +} + +// Disassociates an Elastic IP address from the instance or network interface +// it's associated with. +// +// An Elastic IP address is for use in either the EC2-Classic platform or in +// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// This is an idempotent operation. If you perform the operation more than +// once, Amazon EC2 doesn't return an error. +func (c *EC2) DisassociateAddress(input *DisassociateAddressInput) (*DisassociateAddressOutput, error) { + req, out := c.DisassociateAddressRequest(input) + err := req.Send() + return out, err +} + +const opDisassociateRouteTable = "DisassociateRouteTable" + +// DisassociateRouteTableRequest generates a request for the DisassociateRouteTable operation. +func (c *EC2) DisassociateRouteTableRequest(input *DisassociateRouteTableInput) (req *request.Request, output *DisassociateRouteTableOutput) { + op := &request.Operation{ + Name: opDisassociateRouteTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DisassociateRouteTableInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &DisassociateRouteTableOutput{} + req.Data = output + return +} + +// Disassociates a subnet from a route table. +// +// After you perform this action, the subnet no longer uses the routes in the +// route table. Instead, it uses the routes in the VPC's main route table. For +// more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) DisassociateRouteTable(input *DisassociateRouteTableInput) (*DisassociateRouteTableOutput, error) { + req, out := c.DisassociateRouteTableRequest(input) + err := req.Send() + return out, err +} + +const opEnableVgwRoutePropagation = "EnableVgwRoutePropagation" + +// EnableVgwRoutePropagationRequest generates a request for the EnableVgwRoutePropagation operation. +func (c *EC2) EnableVgwRoutePropagationRequest(input *EnableVgwRoutePropagationInput) (req *request.Request, output *EnableVgwRoutePropagationOutput) { + op := &request.Operation{ + Name: opEnableVgwRoutePropagation, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &EnableVgwRoutePropagationInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &EnableVgwRoutePropagationOutput{} + req.Data = output + return +} + +// Enables a virtual private gateway (VGW) to propagate routes to the specified +// route table of a VPC. +func (c *EC2) EnableVgwRoutePropagation(input *EnableVgwRoutePropagationInput) (*EnableVgwRoutePropagationOutput, error) { + req, out := c.EnableVgwRoutePropagationRequest(input) + err := req.Send() + return out, err +} + +const opEnableVolumeIO = "EnableVolumeIO" + +// EnableVolumeIORequest generates a request for the EnableVolumeIO operation. +func (c *EC2) EnableVolumeIORequest(input *EnableVolumeIOInput) (req *request.Request, output *EnableVolumeIOOutput) { + op := &request.Operation{ + Name: opEnableVolumeIO, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &EnableVolumeIOInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &EnableVolumeIOOutput{} + req.Data = output + return +} + +// Enables I/O operations for a volume that had I/O operations disabled because +// the data on the volume was potentially inconsistent. +func (c *EC2) EnableVolumeIO(input *EnableVolumeIOInput) (*EnableVolumeIOOutput, error) { + req, out := c.EnableVolumeIORequest(input) + err := req.Send() + return out, err +} + +const opEnableVpcClassicLink = "EnableVpcClassicLink" + +// EnableVpcClassicLinkRequest generates a request for the EnableVpcClassicLink operation. +func (c *EC2) EnableVpcClassicLinkRequest(input *EnableVpcClassicLinkInput) (req *request.Request, output *EnableVpcClassicLinkOutput) { + op := &request.Operation{ + Name: opEnableVpcClassicLink, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &EnableVpcClassicLinkInput{} + } + + req = c.newRequest(op, input, output) + output = &EnableVpcClassicLinkOutput{} + req.Data = output + return +} + +// Enables a VPC for ClassicLink. You can then link EC2-Classic instances to +// your ClassicLink-enabled VPC to allow communication over private IP addresses. +// You cannot enable your VPC for ClassicLink if any of your VPC's route tables +// have existing routes for address ranges within the 10.0.0.0/8 IP address +// range, excluding local routes for VPCs in the 10.0.0.0/16 and 10.1.0.0/16 +// IP address ranges. For more information, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) EnableVpcClassicLink(input *EnableVpcClassicLinkInput) (*EnableVpcClassicLinkOutput, error) { + req, out := c.EnableVpcClassicLinkRequest(input) + err := req.Send() + return out, err +} + +const opEnableVpcClassicLinkDnsSupport = "EnableVpcClassicLinkDnsSupport" + +// EnableVpcClassicLinkDnsSupportRequest generates a request for the EnableVpcClassicLinkDnsSupport operation. +func (c *EC2) EnableVpcClassicLinkDnsSupportRequest(input *EnableVpcClassicLinkDnsSupportInput) (req *request.Request, output *EnableVpcClassicLinkDnsSupportOutput) { + op := &request.Operation{ + Name: opEnableVpcClassicLinkDnsSupport, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &EnableVpcClassicLinkDnsSupportInput{} + } + + req = c.newRequest(op, input, output) + output = &EnableVpcClassicLinkDnsSupportOutput{} + req.Data = output + return +} + +// Enables a VPC to support DNS hostname resolution for ClassicLink. If enabled, +// the DNS hostname of a linked EC2-Classic instance resolves to its private +// IP address when addressed from an instance in the VPC to which it's linked. +// Similarly, the DNS hostname of an instance in a VPC resolves to its private +// IP address when addressed from a linked EC2-Classic instance. For more information +// about ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) EnableVpcClassicLinkDnsSupport(input *EnableVpcClassicLinkDnsSupportInput) (*EnableVpcClassicLinkDnsSupportOutput, error) { + req, out := c.EnableVpcClassicLinkDnsSupportRequest(input) + err := req.Send() + return out, err +} + +const opGetConsoleOutput = "GetConsoleOutput" + +// GetConsoleOutputRequest generates a request for the GetConsoleOutput operation. +func (c *EC2) GetConsoleOutputRequest(input *GetConsoleOutputInput) (req *request.Request, output *GetConsoleOutputOutput) { + op := &request.Operation{ + Name: opGetConsoleOutput, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetConsoleOutputInput{} + } + + req = c.newRequest(op, input, output) + output = &GetConsoleOutputOutput{} + req.Data = output + return +} + +// Gets the console output for the specified instance. +// +// Instances do not have a physical monitor through which you can view their +// console output. They also lack physical controls that allow you to power +// up, reboot, or shut them down. To allow these actions, we provide them through +// the Amazon EC2 API and command line interface. +// +// Instance console output is buffered and posted shortly after instance boot, +// reboot, and termination. Amazon EC2 preserves the most recent 64 KB output +// which is available for at least one hour after the most recent post. +// +// For Linux instances, the instance console output displays the exact console +// output that would normally be displayed on a physical monitor attached to +// a computer. This output is buffered because the instance produces it and +// then posts it to a store where the instance's owner can retrieve it. +// +// For Windows instances, the instance console output includes output from +// the EC2Config service. +func (c *EC2) GetConsoleOutput(input *GetConsoleOutputInput) (*GetConsoleOutputOutput, error) { + req, out := c.GetConsoleOutputRequest(input) + err := req.Send() + return out, err +} + +const opGetPasswordData = "GetPasswordData" + +// GetPasswordDataRequest generates a request for the GetPasswordData operation. +func (c *EC2) GetPasswordDataRequest(input *GetPasswordDataInput) (req *request.Request, output *GetPasswordDataOutput) { + op := &request.Operation{ + Name: opGetPasswordData, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetPasswordDataInput{} + } + + req = c.newRequest(op, input, output) + output = &GetPasswordDataOutput{} + req.Data = output + return +} + +// Retrieves the encrypted administrator password for an instance running Windows. +// +// The Windows password is generated at boot if the EC2Config service plugin, +// Ec2SetPassword, is enabled. This usually only happens the first time an AMI +// is launched, and then Ec2SetPassword is automatically disabled. The password +// is not generated for rebundled AMIs unless Ec2SetPassword is enabled before +// bundling. +// +// The password is encrypted using the key pair that you specified when you +// launched the instance. You must provide the corresponding key pair file. +// +// Password generation and encryption takes a few moments. We recommend that +// you wait up to 15 minutes after launching an instance before trying to retrieve +// the generated password. +func (c *EC2) GetPasswordData(input *GetPasswordDataInput) (*GetPasswordDataOutput, error) { + req, out := c.GetPasswordDataRequest(input) + err := req.Send() + return out, err +} + +const opImportImage = "ImportImage" + +// ImportImageRequest generates a request for the ImportImage operation. +func (c *EC2) ImportImageRequest(input *ImportImageInput) (req *request.Request, output *ImportImageOutput) { + op := &request.Operation{ + Name: opImportImage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ImportImageInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportImageOutput{} + req.Data = output + return +} + +// Import single or multi-volume disk images or EBS snapshots into an Amazon +// Machine Image (AMI). +func (c *EC2) ImportImage(input *ImportImageInput) (*ImportImageOutput, error) { + req, out := c.ImportImageRequest(input) + err := req.Send() + return out, err +} + +const opImportInstance = "ImportInstance" + +// ImportInstanceRequest generates a request for the ImportInstance operation. +func (c *EC2) ImportInstanceRequest(input *ImportInstanceInput) (req *request.Request, output *ImportInstanceOutput) { + op := &request.Operation{ + Name: opImportInstance, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ImportInstanceInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportInstanceOutput{} + req.Data = output + return +} + +// Creates an import instance task using metadata from the specified disk image. +// ImportInstance only supports single-volume VMs. To import multi-volume VMs, +// use ImportImage. After importing the image, you then upload it using the +// ec2-import-volume command in the EC2 command line tools. For more information, +// see Using the Command Line Tools to Import Your Virtual Machine to Amazon +// EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ImportInstance(input *ImportInstanceInput) (*ImportInstanceOutput, error) { + req, out := c.ImportInstanceRequest(input) + err := req.Send() + return out, err +} + +const opImportKeyPair = "ImportKeyPair" + +// ImportKeyPairRequest generates a request for the ImportKeyPair operation. +func (c *EC2) ImportKeyPairRequest(input *ImportKeyPairInput) (req *request.Request, output *ImportKeyPairOutput) { + op := &request.Operation{ + Name: opImportKeyPair, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ImportKeyPairInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportKeyPairOutput{} + req.Data = output + return +} + +// Imports the public key from an RSA key pair that you created with a third-party +// tool. Compare this with CreateKeyPair, in which AWS creates the key pair +// and gives the keys to you (AWS keeps a copy of the public key). With ImportKeyPair, +// you create the key pair and give AWS just the public key. The private key +// is never transferred between you and AWS. +// +// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ImportKeyPair(input *ImportKeyPairInput) (*ImportKeyPairOutput, error) { + req, out := c.ImportKeyPairRequest(input) + err := req.Send() + return out, err +} + +const opImportSnapshot = "ImportSnapshot" + +// ImportSnapshotRequest generates a request for the ImportSnapshot operation. +func (c *EC2) ImportSnapshotRequest(input *ImportSnapshotInput) (req *request.Request, output *ImportSnapshotOutput) { + op := &request.Operation{ + Name: opImportSnapshot, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ImportSnapshotInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportSnapshotOutput{} + req.Data = output + return +} + +// Imports a disk into an EBS snapshot. +func (c *EC2) ImportSnapshot(input *ImportSnapshotInput) (*ImportSnapshotOutput, error) { + req, out := c.ImportSnapshotRequest(input) + err := req.Send() + return out, err +} + +const opImportVolume = "ImportVolume" + +// ImportVolumeRequest generates a request for the ImportVolume operation. +func (c *EC2) ImportVolumeRequest(input *ImportVolumeInput) (req *request.Request, output *ImportVolumeOutput) { + op := &request.Operation{ + Name: opImportVolume, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ImportVolumeInput{} + } + + req = c.newRequest(op, input, output) + output = &ImportVolumeOutput{} + req.Data = output + return +} + +// Creates an import volume task using metadata from the specified disk image. +// After importing the image, you then upload it using the ec2-import-volume +// command in the Amazon EC2 command-line interface (CLI) tools. For more information, +// see Using the Command Line Tools to Import Your Virtual Machine to Amazon +// EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ImportVolume(input *ImportVolumeInput) (*ImportVolumeOutput, error) { + req, out := c.ImportVolumeRequest(input) + err := req.Send() + return out, err +} + +const opModifyHosts = "ModifyHosts" + +// ModifyHostsRequest generates a request for the ModifyHosts operation. +func (c *EC2) ModifyHostsRequest(input *ModifyHostsInput) (req *request.Request, output *ModifyHostsOutput) { + op := &request.Operation{ + Name: opModifyHosts, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyHostsInput{} + } + + req = c.newRequest(op, input, output) + output = &ModifyHostsOutput{} + req.Data = output + return +} + +// Modify the auto-placement setting of a Dedicated host. When auto-placement +// is enabled, AWS will place instances that you launch with a tenancy of host, +// but without targeting a specific host ID, onto any available Dedicated host +// in your account which has auto-placement enabled. When auto-placement is +// disabled, you need to provide a host ID if you want the instance to launch +// onto a specific host. If no host ID is provided, the instance will be launched +// onto a suitable host which has auto-placement enabled. +func (c *EC2) ModifyHosts(input *ModifyHostsInput) (*ModifyHostsOutput, error) { + req, out := c.ModifyHostsRequest(input) + err := req.Send() + return out, err +} + +const opModifyIdFormat = "ModifyIdFormat" + +// ModifyIdFormatRequest generates a request for the ModifyIdFormat operation. +func (c *EC2) ModifyIdFormatRequest(input *ModifyIdFormatInput) (req *request.Request, output *ModifyIdFormatOutput) { + op := &request.Operation{ + Name: opModifyIdFormat, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyIdFormatInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyIdFormatOutput{} + req.Data = output + return +} + +// Modifies the ID format for the specified resource on a per-region basis. +// You can specify that resources should receive longer IDs (17-character IDs) +// when they are created. The following resource types support longer IDs: instance +// | reservation. +// +// This setting applies to the IAM user who makes the request; it does not +// apply to the entire AWS account. By default, an IAM user defaults to the +// same settings as the root user, unless they explicitly override the settings +// by running this request. Resources created with longer IDs are visible to +// all IAM users, regardless of these settings and provided that they have permission +// to use the relevant Describe command for the resource type. +func (c *EC2) ModifyIdFormat(input *ModifyIdFormatInput) (*ModifyIdFormatOutput, error) { + req, out := c.ModifyIdFormatRequest(input) + err := req.Send() + return out, err +} + +const opModifyImageAttribute = "ModifyImageAttribute" + +// ModifyImageAttributeRequest generates a request for the ModifyImageAttribute operation. +func (c *EC2) ModifyImageAttributeRequest(input *ModifyImageAttributeInput) (req *request.Request, output *ModifyImageAttributeOutput) { + op := &request.Operation{ + Name: opModifyImageAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyImageAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyImageAttributeOutput{} + req.Data = output + return +} + +// Modifies the specified attribute of the specified AMI. You can specify only +// one attribute at a time. +// +// AWS Marketplace product codes cannot be modified. Images with an AWS Marketplace +// product code cannot be made public. +func (c *EC2) ModifyImageAttribute(input *ModifyImageAttributeInput) (*ModifyImageAttributeOutput, error) { + req, out := c.ModifyImageAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyInstanceAttribute = "ModifyInstanceAttribute" + +// ModifyInstanceAttributeRequest generates a request for the ModifyInstanceAttribute operation. +func (c *EC2) ModifyInstanceAttributeRequest(input *ModifyInstanceAttributeInput) (req *request.Request, output *ModifyInstanceAttributeOutput) { + op := &request.Operation{ + Name: opModifyInstanceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyInstanceAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyInstanceAttributeOutput{} + req.Data = output + return +} + +// Modifies the specified attribute of the specified instance. You can specify +// only one attribute at a time. +// +// To modify some attributes, the instance must be stopped. For more information, +// see Modifying Attributes of a Stopped Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_ChangingAttributesWhileInstanceStopped.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ModifyInstanceAttribute(input *ModifyInstanceAttributeInput) (*ModifyInstanceAttributeOutput, error) { + req, out := c.ModifyInstanceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyInstancePlacement = "ModifyInstancePlacement" + +// ModifyInstancePlacementRequest generates a request for the ModifyInstancePlacement operation. +func (c *EC2) ModifyInstancePlacementRequest(input *ModifyInstancePlacementInput) (req *request.Request, output *ModifyInstancePlacementOutput) { + op := &request.Operation{ + Name: opModifyInstancePlacement, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyInstancePlacementInput{} + } + + req = c.newRequest(op, input, output) + output = &ModifyInstancePlacementOutput{} + req.Data = output + return +} + +// Set the instance affinity value for a specific stopped instance and modify +// the instance tenancy setting. +// +// Instance affinity is disabled by default. When instance affinity is host +// and it is not associated with a specific Dedicated host, the next time it +// is launched it will automatically be associated with the host it lands on. +// This relationship will persist if the instance is stopped/started, or rebooted. +// +// You can modify the host ID associated with a stopped instance. If a stopped +// instance has a new host ID association, the instance will target that host +// when restarted. +// +// You can modify the tenancy of a stopped instance with a tenancy of host +// or dedicated. +// +// Affinity, hostID, and tenancy are not required parameters, but at least +// one of them must be specified in the request. Affinity and tenancy can be +// modified in the same request, but tenancy can only be modified on instances +// that are stopped. +func (c *EC2) ModifyInstancePlacement(input *ModifyInstancePlacementInput) (*ModifyInstancePlacementOutput, error) { + req, out := c.ModifyInstancePlacementRequest(input) + err := req.Send() + return out, err +} + +const opModifyNetworkInterfaceAttribute = "ModifyNetworkInterfaceAttribute" + +// ModifyNetworkInterfaceAttributeRequest generates a request for the ModifyNetworkInterfaceAttribute operation. +func (c *EC2) ModifyNetworkInterfaceAttributeRequest(input *ModifyNetworkInterfaceAttributeInput) (req *request.Request, output *ModifyNetworkInterfaceAttributeOutput) { + op := &request.Operation{ + Name: opModifyNetworkInterfaceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyNetworkInterfaceAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyNetworkInterfaceAttributeOutput{} + req.Data = output + return +} + +// Modifies the specified network interface attribute. You can specify only +// one attribute at a time. +func (c *EC2) ModifyNetworkInterfaceAttribute(input *ModifyNetworkInterfaceAttributeInput) (*ModifyNetworkInterfaceAttributeOutput, error) { + req, out := c.ModifyNetworkInterfaceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyReservedInstances = "ModifyReservedInstances" + +// ModifyReservedInstancesRequest generates a request for the ModifyReservedInstances operation. +func (c *EC2) ModifyReservedInstancesRequest(input *ModifyReservedInstancesInput) (req *request.Request, output *ModifyReservedInstancesOutput) { + op := &request.Operation{ + Name: opModifyReservedInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyReservedInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &ModifyReservedInstancesOutput{} + req.Data = output + return +} + +// Modifies the Availability Zone, instance count, instance type, or network +// platform (EC2-Classic or EC2-VPC) of your Reserved Instances. The Reserved +// Instances to be modified must be identical, except for Availability Zone, +// network platform, and instance type. +// +// For more information, see Modifying Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ModifyReservedInstances(input *ModifyReservedInstancesInput) (*ModifyReservedInstancesOutput, error) { + req, out := c.ModifyReservedInstancesRequest(input) + err := req.Send() + return out, err +} + +const opModifySnapshotAttribute = "ModifySnapshotAttribute" + +// ModifySnapshotAttributeRequest generates a request for the ModifySnapshotAttribute operation. +func (c *EC2) ModifySnapshotAttributeRequest(input *ModifySnapshotAttributeInput) (req *request.Request, output *ModifySnapshotAttributeOutput) { + op := &request.Operation{ + Name: opModifySnapshotAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifySnapshotAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifySnapshotAttributeOutput{} + req.Data = output + return +} + +// Adds or removes permission settings for the specified snapshot. You may add +// or remove specified AWS account IDs from a snapshot's list of create volume +// permissions, but you cannot do both in a single API call. If you need to +// both add and remove account IDs for a snapshot, you must use multiple API +// calls. +// +// For more information on modifying snapshot permissions, see Sharing Snapshots +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// Snapshots with AWS Marketplace product codes cannot be made public. +func (c *EC2) ModifySnapshotAttribute(input *ModifySnapshotAttributeInput) (*ModifySnapshotAttributeOutput, error) { + req, out := c.ModifySnapshotAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifySpotFleetRequest = "ModifySpotFleetRequest" + +// ModifySpotFleetRequestRequest generates a request for the ModifySpotFleetRequest operation. +func (c *EC2) ModifySpotFleetRequestRequest(input *ModifySpotFleetRequestInput) (req *request.Request, output *ModifySpotFleetRequestOutput) { + op := &request.Operation{ + Name: opModifySpotFleetRequest, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifySpotFleetRequestInput{} + } + + req = c.newRequest(op, input, output) + output = &ModifySpotFleetRequestOutput{} + req.Data = output + return +} + +// Modifies the specified Spot fleet request. +// +// While the Spot fleet request is being modified, it is in the modifying state. +// +// To scale up your Spot fleet, increase its target capacity. The Spot fleet +// launches the additional Spot instances according to the allocation strategy +// for the Spot fleet request. If the allocation strategy is lowestPrice, the +// Spot fleet launches instances using the Spot pool with the lowest price. +// If the allocation strategy is diversified, the Spot fleet distributes the +// instances across the Spot pools. +// +// To scale down your Spot fleet, decrease its target capacity. First, the +// Spot fleet cancels any open bids that exceed the new target capacity. You +// can request that the Spot fleet terminate Spot instances until the size of +// the fleet no longer exceeds the new target capacity. If the allocation strategy +// is lowestPrice, the Spot fleet terminates the instances with the highest +// price per unit. If the allocation strategy is diversified, the Spot fleet +// terminates instances across the Spot pools. Alternatively, you can request +// that the Spot fleet keep the fleet at its current size, but not replace any +// Spot instances that are interrupted or that you terminate manually. +func (c *EC2) ModifySpotFleetRequest(input *ModifySpotFleetRequestInput) (*ModifySpotFleetRequestOutput, error) { + req, out := c.ModifySpotFleetRequestRequest(input) + err := req.Send() + return out, err +} + +const opModifySubnetAttribute = "ModifySubnetAttribute" + +// ModifySubnetAttributeRequest generates a request for the ModifySubnetAttribute operation. +func (c *EC2) ModifySubnetAttributeRequest(input *ModifySubnetAttributeInput) (req *request.Request, output *ModifySubnetAttributeOutput) { + op := &request.Operation{ + Name: opModifySubnetAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifySubnetAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifySubnetAttributeOutput{} + req.Data = output + return +} + +// Modifies a subnet attribute. +func (c *EC2) ModifySubnetAttribute(input *ModifySubnetAttributeInput) (*ModifySubnetAttributeOutput, error) { + req, out := c.ModifySubnetAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyVolumeAttribute = "ModifyVolumeAttribute" + +// ModifyVolumeAttributeRequest generates a request for the ModifyVolumeAttribute operation. +func (c *EC2) ModifyVolumeAttributeRequest(input *ModifyVolumeAttributeInput) (req *request.Request, output *ModifyVolumeAttributeOutput) { + op := &request.Operation{ + Name: opModifyVolumeAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyVolumeAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyVolumeAttributeOutput{} + req.Data = output + return +} + +// Modifies a volume attribute. +// +// By default, all I/O operations for the volume are suspended when the data +// on the volume is determined to be potentially inconsistent, to prevent undetectable, +// latent data corruption. The I/O access to the volume can be resumed by first +// enabling I/O access and then checking the data consistency on your volume. +// +// You can change the default behavior to resume I/O operations. We recommend +// that you change this only for boot volumes or for volumes that are stateless +// or disposable. +func (c *EC2) ModifyVolumeAttribute(input *ModifyVolumeAttributeInput) (*ModifyVolumeAttributeOutput, error) { + req, out := c.ModifyVolumeAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyVpcAttribute = "ModifyVpcAttribute" + +// ModifyVpcAttributeRequest generates a request for the ModifyVpcAttribute operation. +func (c *EC2) ModifyVpcAttributeRequest(input *ModifyVpcAttributeInput) (req *request.Request, output *ModifyVpcAttributeOutput) { + op := &request.Operation{ + Name: opModifyVpcAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyVpcAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ModifyVpcAttributeOutput{} + req.Data = output + return +} + +// Modifies the specified attribute of the specified VPC. +func (c *EC2) ModifyVpcAttribute(input *ModifyVpcAttributeInput) (*ModifyVpcAttributeOutput, error) { + req, out := c.ModifyVpcAttributeRequest(input) + err := req.Send() + return out, err +} + +const opModifyVpcEndpoint = "ModifyVpcEndpoint" + +// ModifyVpcEndpointRequest generates a request for the ModifyVpcEndpoint operation. +func (c *EC2) ModifyVpcEndpointRequest(input *ModifyVpcEndpointInput) (req *request.Request, output *ModifyVpcEndpointOutput) { + op := &request.Operation{ + Name: opModifyVpcEndpoint, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyVpcEndpointInput{} + } + + req = c.newRequest(op, input, output) + output = &ModifyVpcEndpointOutput{} + req.Data = output + return +} + +// Modifies attributes of a specified VPC endpoint. You can modify the policy +// associated with the endpoint, and you can add and remove route tables associated +// with the endpoint. +func (c *EC2) ModifyVpcEndpoint(input *ModifyVpcEndpointInput) (*ModifyVpcEndpointOutput, error) { + req, out := c.ModifyVpcEndpointRequest(input) + err := req.Send() + return out, err +} + +const opMonitorInstances = "MonitorInstances" + +// MonitorInstancesRequest generates a request for the MonitorInstances operation. +func (c *EC2) MonitorInstancesRequest(input *MonitorInstancesInput) (req *request.Request, output *MonitorInstancesOutput) { + op := &request.Operation{ + Name: opMonitorInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &MonitorInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &MonitorInstancesOutput{} + req.Data = output + return +} + +// Enables monitoring for a running instance. For more information about monitoring +// instances, see Monitoring Your Instances and Volumes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) MonitorInstances(input *MonitorInstancesInput) (*MonitorInstancesOutput, error) { + req, out := c.MonitorInstancesRequest(input) + err := req.Send() + return out, err +} + +const opMoveAddressToVpc = "MoveAddressToVpc" + +// MoveAddressToVpcRequest generates a request for the MoveAddressToVpc operation. +func (c *EC2) MoveAddressToVpcRequest(input *MoveAddressToVpcInput) (req *request.Request, output *MoveAddressToVpcOutput) { + op := &request.Operation{ + Name: opMoveAddressToVpc, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &MoveAddressToVpcInput{} + } + + req = c.newRequest(op, input, output) + output = &MoveAddressToVpcOutput{} + req.Data = output + return +} + +// Moves an Elastic IP address from the EC2-Classic platform to the EC2-VPC +// platform. The Elastic IP address must be allocated to your account for more +// than 24 hours, and it must not be associated with an instance. After the +// Elastic IP address is moved, it is no longer available for use in the EC2-Classic +// platform, unless you move it back using the RestoreAddressToClassic request. +// You cannot move an Elastic IP address that's allocated for use in the EC2-VPC +// platform to the EC2-Classic platform. You cannot migrate an Elastic IP address +// that's associated with a reverse DNS record. Contact AWS account and billing +// support to remove the reverse DNS record. +func (c *EC2) MoveAddressToVpc(input *MoveAddressToVpcInput) (*MoveAddressToVpcOutput, error) { + req, out := c.MoveAddressToVpcRequest(input) + err := req.Send() + return out, err +} + +const opPurchaseReservedInstancesOffering = "PurchaseReservedInstancesOffering" + +// PurchaseReservedInstancesOfferingRequest generates a request for the PurchaseReservedInstancesOffering operation. +func (c *EC2) PurchaseReservedInstancesOfferingRequest(input *PurchaseReservedInstancesOfferingInput) (req *request.Request, output *PurchaseReservedInstancesOfferingOutput) { + op := &request.Operation{ + Name: opPurchaseReservedInstancesOffering, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &PurchaseReservedInstancesOfferingInput{} + } + + req = c.newRequest(op, input, output) + output = &PurchaseReservedInstancesOfferingOutput{} + req.Data = output + return +} + +// Purchases a Reserved Instance for use with your account. With Reserved Instances, +// you obtain a capacity reservation for a certain instance configuration over +// a specified period of time and pay a lower hourly rate compared to On-Demand +// instance pricing. +// +// Use DescribeReservedInstancesOfferings to get a list of Reserved Instance +// offerings that match your specifications. After you've purchased a Reserved +// Instance, you can check for your new Reserved Instance with DescribeReservedInstances. +// +// For more information, see Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-on-demand-reserved-instances.html) +// and Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) PurchaseReservedInstancesOffering(input *PurchaseReservedInstancesOfferingInput) (*PurchaseReservedInstancesOfferingOutput, error) { + req, out := c.PurchaseReservedInstancesOfferingRequest(input) + err := req.Send() + return out, err +} + +const opPurchaseScheduledInstances = "PurchaseScheduledInstances" + +// PurchaseScheduledInstancesRequest generates a request for the PurchaseScheduledInstances operation. +func (c *EC2) PurchaseScheduledInstancesRequest(input *PurchaseScheduledInstancesInput) (req *request.Request, output *PurchaseScheduledInstancesOutput) { + op := &request.Operation{ + Name: opPurchaseScheduledInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &PurchaseScheduledInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &PurchaseScheduledInstancesOutput{} + req.Data = output + return +} + +// Purchases one or more Scheduled Instances with the specified schedule. +// +// Scheduled Instances enable you to purchase Amazon EC2 compute capacity by +// the hour for a one-year term. Before you can purchase a Scheduled Instance, +// you must call DescribeScheduledInstanceAvailability to check for available +// schedules and obtain a purchase token. +func (c *EC2) PurchaseScheduledInstances(input *PurchaseScheduledInstancesInput) (*PurchaseScheduledInstancesOutput, error) { + req, out := c.PurchaseScheduledInstancesRequest(input) + err := req.Send() + return out, err +} + +const opRebootInstances = "RebootInstances" + +// RebootInstancesRequest generates a request for the RebootInstances operation. +func (c *EC2) RebootInstancesRequest(input *RebootInstancesInput) (req *request.Request, output *RebootInstancesOutput) { + op := &request.Operation{ + Name: opRebootInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RebootInstancesInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &RebootInstancesOutput{} + req.Data = output + return +} + +// Requests a reboot of one or more instances. This operation is asynchronous; +// it only queues a request to reboot the specified instances. The operation +// succeeds if the instances are valid and belong to you. Requests to reboot +// terminated instances are ignored. +// +// If a Linux/Unix instance does not cleanly shut down within four minutes, +// Amazon EC2 performs a hard reboot. +// +// For more information about troubleshooting, see Getting Console Output and +// Rebooting Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-console.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) RebootInstances(input *RebootInstancesInput) (*RebootInstancesOutput, error) { + req, out := c.RebootInstancesRequest(input) + err := req.Send() + return out, err +} + +const opRegisterImage = "RegisterImage" + +// RegisterImageRequest generates a request for the RegisterImage operation. +func (c *EC2) RegisterImageRequest(input *RegisterImageInput) (req *request.Request, output *RegisterImageOutput) { + op := &request.Operation{ + Name: opRegisterImage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RegisterImageInput{} + } + + req = c.newRequest(op, input, output) + output = &RegisterImageOutput{} + req.Data = output + return +} + +// Registers an AMI. When you're creating an AMI, this is the final step you +// must complete before you can launch an instance from the AMI. For more information +// about creating AMIs, see Creating Your Own AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// For Amazon EBS-backed instances, CreateImage creates and registers the AMI +// in a single request, so you don't have to register the AMI yourself. +// +// You can also use RegisterImage to create an Amazon EBS-backed Linux AMI +// from a snapshot of a root device volume. For more information, see Launching +// an Instance from a Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_LaunchingInstanceFromSnapshot.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// Some Linux distributions, such as Red Hat Enterprise Linux (RHEL) and SUSE +// Linux Enterprise Server (SLES), use the EC2 billingProduct code associated +// with an AMI to verify subscription status for package updates. Creating an +// AMI from an EBS snapshot does not maintain this billing code, and subsequent +// instances launched from such an AMI will not be able to connect to package +// update infrastructure. +// +// Similarly, although you can create a Windows AMI from a snapshot, you can't +// successfully launch an instance from the AMI. +// +// To create Windows AMIs or to create AMIs for Linux operating systems that +// must retain AMI billing codes to work properly, see CreateImage. +// +// If needed, you can deregister an AMI at any time. Any modifications you +// make to an AMI backed by an instance store volume invalidates its registration. +// If you make changes to an image, deregister the previous image and register +// the new image. +// +// You can't register an image where a secondary (non-root) snapshot has AWS +// Marketplace product codes. +func (c *EC2) RegisterImage(input *RegisterImageInput) (*RegisterImageOutput, error) { + req, out := c.RegisterImageRequest(input) + err := req.Send() + return out, err +} + +const opRejectVpcPeeringConnection = "RejectVpcPeeringConnection" + +// RejectVpcPeeringConnectionRequest generates a request for the RejectVpcPeeringConnection operation. +func (c *EC2) RejectVpcPeeringConnectionRequest(input *RejectVpcPeeringConnectionInput) (req *request.Request, output *RejectVpcPeeringConnectionOutput) { + op := &request.Operation{ + Name: opRejectVpcPeeringConnection, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RejectVpcPeeringConnectionInput{} + } + + req = c.newRequest(op, input, output) + output = &RejectVpcPeeringConnectionOutput{} + req.Data = output + return +} + +// Rejects a VPC peering connection request. The VPC peering connection must +// be in the pending-acceptance state. Use the DescribeVpcPeeringConnections +// request to view your outstanding VPC peering connection requests. To delete +// an active VPC peering connection, or to delete a VPC peering connection request +// that you initiated, use DeleteVpcPeeringConnection. +func (c *EC2) RejectVpcPeeringConnection(input *RejectVpcPeeringConnectionInput) (*RejectVpcPeeringConnectionOutput, error) { + req, out := c.RejectVpcPeeringConnectionRequest(input) + err := req.Send() + return out, err +} + +const opReleaseAddress = "ReleaseAddress" + +// ReleaseAddressRequest generates a request for the ReleaseAddress operation. +func (c *EC2) ReleaseAddressRequest(input *ReleaseAddressInput) (req *request.Request, output *ReleaseAddressOutput) { + op := &request.Operation{ + Name: opReleaseAddress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReleaseAddressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ReleaseAddressOutput{} + req.Data = output + return +} + +// Releases the specified Elastic IP address. +// +// After releasing an Elastic IP address, it is released to the IP address +// pool and might be unavailable to you. Be sure to update your DNS records +// and any servers or devices that communicate with the address. If you attempt +// to release an Elastic IP address that you already released, you'll get an +// AuthFailure error if the address is already allocated to another AWS account. +// +// [EC2-Classic, default VPC] Releasing an Elastic IP address automatically +// disassociates it from any instance that it's associated with. To disassociate +// an Elastic IP address without releasing it, use DisassociateAddress. +// +// [Nondefault VPC] You must use DisassociateAddress to disassociate the Elastic +// IP address before you try to release it. Otherwise, Amazon EC2 returns an +// error (InvalidIPAddress.InUse). +func (c *EC2) ReleaseAddress(input *ReleaseAddressInput) (*ReleaseAddressOutput, error) { + req, out := c.ReleaseAddressRequest(input) + err := req.Send() + return out, err +} + +const opReleaseHosts = "ReleaseHosts" + +// ReleaseHostsRequest generates a request for the ReleaseHosts operation. +func (c *EC2) ReleaseHostsRequest(input *ReleaseHostsInput) (req *request.Request, output *ReleaseHostsOutput) { + op := &request.Operation{ + Name: opReleaseHosts, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReleaseHostsInput{} + } + + req = c.newRequest(op, input, output) + output = &ReleaseHostsOutput{} + req.Data = output + return +} + +// When you no longer want to use a Dedicated host it can be released. On-Demand +// billing is stopped and the host goes into released state. The host ID of +// Dedicated hosts that have been released can no longer be specified in another +// request, e.g., ModifyHosts. You must stop or terminate all instances on a +// host before it can be released. +// +// When Dedicated hosts are released, it make take some time for them to stop +// counting toward your limit and you may receive capacity errors when trying +// to allocate new Dedicated hosts. Try waiting a few minutes, and then try +// again. +// +// Released hosts will still appear in a DescribeHosts response. +func (c *EC2) ReleaseHosts(input *ReleaseHostsInput) (*ReleaseHostsOutput, error) { + req, out := c.ReleaseHostsRequest(input) + err := req.Send() + return out, err +} + +const opReplaceNetworkAclAssociation = "ReplaceNetworkAclAssociation" + +// ReplaceNetworkAclAssociationRequest generates a request for the ReplaceNetworkAclAssociation operation. +func (c *EC2) ReplaceNetworkAclAssociationRequest(input *ReplaceNetworkAclAssociationInput) (req *request.Request, output *ReplaceNetworkAclAssociationOutput) { + op := &request.Operation{ + Name: opReplaceNetworkAclAssociation, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReplaceNetworkAclAssociationInput{} + } + + req = c.newRequest(op, input, output) + output = &ReplaceNetworkAclAssociationOutput{} + req.Data = output + return +} + +// Changes which network ACL a subnet is associated with. By default when you +// create a subnet, it's automatically associated with the default network ACL. +// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) ReplaceNetworkAclAssociation(input *ReplaceNetworkAclAssociationInput) (*ReplaceNetworkAclAssociationOutput, error) { + req, out := c.ReplaceNetworkAclAssociationRequest(input) + err := req.Send() + return out, err +} + +const opReplaceNetworkAclEntry = "ReplaceNetworkAclEntry" + +// ReplaceNetworkAclEntryRequest generates a request for the ReplaceNetworkAclEntry operation. +func (c *EC2) ReplaceNetworkAclEntryRequest(input *ReplaceNetworkAclEntryInput) (req *request.Request, output *ReplaceNetworkAclEntryOutput) { + op := &request.Operation{ + Name: opReplaceNetworkAclEntry, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReplaceNetworkAclEntryInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ReplaceNetworkAclEntryOutput{} + req.Data = output + return +} + +// Replaces an entry (rule) in a network ACL. For more information about network +// ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) ReplaceNetworkAclEntry(input *ReplaceNetworkAclEntryInput) (*ReplaceNetworkAclEntryOutput, error) { + req, out := c.ReplaceNetworkAclEntryRequest(input) + err := req.Send() + return out, err +} + +const opReplaceRoute = "ReplaceRoute" + +// ReplaceRouteRequest generates a request for the ReplaceRoute operation. +func (c *EC2) ReplaceRouteRequest(input *ReplaceRouteInput) (req *request.Request, output *ReplaceRouteOutput) { + op := &request.Operation{ + Name: opReplaceRoute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReplaceRouteInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ReplaceRouteOutput{} + req.Data = output + return +} + +// Replaces an existing route within a route table in a VPC. You must provide +// only one of the following: Internet gateway or virtual private gateway, NAT +// instance, NAT gateway, VPC peering connection, or network interface. +// +// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) ReplaceRoute(input *ReplaceRouteInput) (*ReplaceRouteOutput, error) { + req, out := c.ReplaceRouteRequest(input) + err := req.Send() + return out, err +} + +const opReplaceRouteTableAssociation = "ReplaceRouteTableAssociation" + +// ReplaceRouteTableAssociationRequest generates a request for the ReplaceRouteTableAssociation operation. +func (c *EC2) ReplaceRouteTableAssociationRequest(input *ReplaceRouteTableAssociationInput) (req *request.Request, output *ReplaceRouteTableAssociationOutput) { + op := &request.Operation{ + Name: opReplaceRouteTableAssociation, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReplaceRouteTableAssociationInput{} + } + + req = c.newRequest(op, input, output) + output = &ReplaceRouteTableAssociationOutput{} + req.Data = output + return +} + +// Changes the route table associated with a given subnet in a VPC. After the +// operation completes, the subnet uses the routes in the new route table it's +// associated with. For more information about route tables, see Route Tables +// (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) +// in the Amazon Virtual Private Cloud User Guide. +// +// You can also use ReplaceRouteTableAssociation to change which table is the +// main route table in the VPC. You just specify the main route table's association +// ID and the route table to be the new main route table. +func (c *EC2) ReplaceRouteTableAssociation(input *ReplaceRouteTableAssociationInput) (*ReplaceRouteTableAssociationOutput, error) { + req, out := c.ReplaceRouteTableAssociationRequest(input) + err := req.Send() + return out, err +} + +const opReportInstanceStatus = "ReportInstanceStatus" + +// ReportInstanceStatusRequest generates a request for the ReportInstanceStatus operation. +func (c *EC2) ReportInstanceStatusRequest(input *ReportInstanceStatusInput) (req *request.Request, output *ReportInstanceStatusOutput) { + op := &request.Operation{ + Name: opReportInstanceStatus, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ReportInstanceStatusInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ReportInstanceStatusOutput{} + req.Data = output + return +} + +// Submits feedback about the status of an instance. The instance must be in +// the running state. If your experience with the instance differs from the +// instance status returned by DescribeInstanceStatus, use ReportInstanceStatus +// to report your experience with the instance. Amazon EC2 collects this information +// to improve the accuracy of status checks. +// +// Use of this action does not change the value returned by DescribeInstanceStatus. +func (c *EC2) ReportInstanceStatus(input *ReportInstanceStatusInput) (*ReportInstanceStatusOutput, error) { + req, out := c.ReportInstanceStatusRequest(input) + err := req.Send() + return out, err +} + +const opRequestSpotFleet = "RequestSpotFleet" + +// RequestSpotFleetRequest generates a request for the RequestSpotFleet operation. +func (c *EC2) RequestSpotFleetRequest(input *RequestSpotFleetInput) (req *request.Request, output *RequestSpotFleetOutput) { + op := &request.Operation{ + Name: opRequestSpotFleet, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RequestSpotFleetInput{} + } + + req = c.newRequest(op, input, output) + output = &RequestSpotFleetOutput{} + req.Data = output + return +} + +// Creates a Spot fleet request. +// +// You can submit a single request that includes multiple launch specifications +// that vary by instance type, AMI, Availability Zone, or subnet. +// +// By default, the Spot fleet requests Spot instances in the Spot pool where +// the price per unit is the lowest. Each launch specification can include its +// own instance weighting that reflects the value of the instance type to your +// application workload. +// +// Alternatively, you can specify that the Spot fleet distribute the target +// capacity across the Spot pools included in its launch specifications. By +// ensuring that the Spot instances in your Spot fleet are in different Spot +// pools, you can improve the availability of your fleet. +// +// For more information, see Spot Fleet Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-requests.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) RequestSpotFleet(input *RequestSpotFleetInput) (*RequestSpotFleetOutput, error) { + req, out := c.RequestSpotFleetRequest(input) + err := req.Send() + return out, err +} + +const opRequestSpotInstances = "RequestSpotInstances" + +// RequestSpotInstancesRequest generates a request for the RequestSpotInstances operation. +func (c *EC2) RequestSpotInstancesRequest(input *RequestSpotInstancesInput) (req *request.Request, output *RequestSpotInstancesOutput) { + op := &request.Operation{ + Name: opRequestSpotInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RequestSpotInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &RequestSpotInstancesOutput{} + req.Data = output + return +} + +// Creates a Spot instance request. Spot instances are instances that Amazon +// EC2 launches when the bid price that you specify exceeds the current Spot +// price. Amazon EC2 periodically sets the Spot price based on available Spot +// Instance capacity and current Spot instance requests. For more information, +// see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) RequestSpotInstances(input *RequestSpotInstancesInput) (*RequestSpotInstancesOutput, error) { + req, out := c.RequestSpotInstancesRequest(input) + err := req.Send() + return out, err +} + +const opResetImageAttribute = "ResetImageAttribute" + +// ResetImageAttributeRequest generates a request for the ResetImageAttribute operation. +func (c *EC2) ResetImageAttributeRequest(input *ResetImageAttributeInput) (req *request.Request, output *ResetImageAttributeOutput) { + op := &request.Operation{ + Name: opResetImageAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ResetImageAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ResetImageAttributeOutput{} + req.Data = output + return +} + +// Resets an attribute of an AMI to its default value. +// +// The productCodes attribute can't be reset. +func (c *EC2) ResetImageAttribute(input *ResetImageAttributeInput) (*ResetImageAttributeOutput, error) { + req, out := c.ResetImageAttributeRequest(input) + err := req.Send() + return out, err +} + +const opResetInstanceAttribute = "ResetInstanceAttribute" + +// ResetInstanceAttributeRequest generates a request for the ResetInstanceAttribute operation. +func (c *EC2) ResetInstanceAttributeRequest(input *ResetInstanceAttributeInput) (req *request.Request, output *ResetInstanceAttributeOutput) { + op := &request.Operation{ + Name: opResetInstanceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ResetInstanceAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ResetInstanceAttributeOutput{} + req.Data = output + return +} + +// Resets an attribute of an instance to its default value. To reset the kernel +// or ramdisk, the instance must be in a stopped state. To reset the SourceDestCheck, +// the instance can be either running or stopped. +// +// The SourceDestCheck attribute controls whether source/destination checking +// is enabled. The default value is true, which means checking is enabled. This +// value must be false for a NAT instance to perform NAT. For more information, +// see NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) +// in the Amazon Virtual Private Cloud User Guide. +func (c *EC2) ResetInstanceAttribute(input *ResetInstanceAttributeInput) (*ResetInstanceAttributeOutput, error) { + req, out := c.ResetInstanceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opResetNetworkInterfaceAttribute = "ResetNetworkInterfaceAttribute" + +// ResetNetworkInterfaceAttributeRequest generates a request for the ResetNetworkInterfaceAttribute operation. +func (c *EC2) ResetNetworkInterfaceAttributeRequest(input *ResetNetworkInterfaceAttributeInput) (req *request.Request, output *ResetNetworkInterfaceAttributeOutput) { + op := &request.Operation{ + Name: opResetNetworkInterfaceAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ResetNetworkInterfaceAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ResetNetworkInterfaceAttributeOutput{} + req.Data = output + return +} + +// Resets a network interface attribute. You can specify only one attribute +// at a time. +func (c *EC2) ResetNetworkInterfaceAttribute(input *ResetNetworkInterfaceAttributeInput) (*ResetNetworkInterfaceAttributeOutput, error) { + req, out := c.ResetNetworkInterfaceAttributeRequest(input) + err := req.Send() + return out, err +} + +const opResetSnapshotAttribute = "ResetSnapshotAttribute" + +// ResetSnapshotAttributeRequest generates a request for the ResetSnapshotAttribute operation. +func (c *EC2) ResetSnapshotAttributeRequest(input *ResetSnapshotAttributeInput) (req *request.Request, output *ResetSnapshotAttributeOutput) { + op := &request.Operation{ + Name: opResetSnapshotAttribute, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ResetSnapshotAttributeInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &ResetSnapshotAttributeOutput{} + req.Data = output + return +} + +// Resets permission settings for the specified snapshot. +// +// For more information on modifying snapshot permissions, see Sharing Snapshots +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) ResetSnapshotAttribute(input *ResetSnapshotAttributeInput) (*ResetSnapshotAttributeOutput, error) { + req, out := c.ResetSnapshotAttributeRequest(input) + err := req.Send() + return out, err +} + +const opRestoreAddressToClassic = "RestoreAddressToClassic" + +// RestoreAddressToClassicRequest generates a request for the RestoreAddressToClassic operation. +func (c *EC2) RestoreAddressToClassicRequest(input *RestoreAddressToClassicInput) (req *request.Request, output *RestoreAddressToClassicOutput) { + op := &request.Operation{ + Name: opRestoreAddressToClassic, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RestoreAddressToClassicInput{} + } + + req = c.newRequest(op, input, output) + output = &RestoreAddressToClassicOutput{} + req.Data = output + return +} + +// Restores an Elastic IP address that was previously moved to the EC2-VPC platform +// back to the EC2-Classic platform. You cannot move an Elastic IP address that +// was originally allocated for use in EC2-VPC. The Elastic IP address must +// not be associated with an instance or network interface. You cannot restore +// an Elastic IP address that's associated with a reverse DNS record. Contact +// AWS account and billing support to remove the reverse DNS record. +func (c *EC2) RestoreAddressToClassic(input *RestoreAddressToClassicInput) (*RestoreAddressToClassicOutput, error) { + req, out := c.RestoreAddressToClassicRequest(input) + err := req.Send() + return out, err +} + +const opRevokeSecurityGroupEgress = "RevokeSecurityGroupEgress" + +// RevokeSecurityGroupEgressRequest generates a request for the RevokeSecurityGroupEgress operation. +func (c *EC2) RevokeSecurityGroupEgressRequest(input *RevokeSecurityGroupEgressInput) (req *request.Request, output *RevokeSecurityGroupEgressOutput) { + op := &request.Operation{ + Name: opRevokeSecurityGroupEgress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RevokeSecurityGroupEgressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &RevokeSecurityGroupEgressOutput{} + req.Data = output + return +} + +// [EC2-VPC only] Removes one or more egress rules from a security group for +// EC2-VPC. This action doesn't apply to security groups for use in EC2-Classic. +// The values that you specify in the revoke request (for example, ports) must +// match the existing rule's values for the rule to be revoked. +// +// Each rule consists of the protocol and the CIDR range or source security +// group. For the TCP and UDP protocols, you must also specify the destination +// port or range of ports. For the ICMP protocol, you must also specify the +// ICMP type and code. +// +// Rule changes are propagated to instances within the security group as quickly +// as possible. However, a small delay might occur. +func (c *EC2) RevokeSecurityGroupEgress(input *RevokeSecurityGroupEgressInput) (*RevokeSecurityGroupEgressOutput, error) { + req, out := c.RevokeSecurityGroupEgressRequest(input) + err := req.Send() + return out, err +} + +const opRevokeSecurityGroupIngress = "RevokeSecurityGroupIngress" + +// RevokeSecurityGroupIngressRequest generates a request for the RevokeSecurityGroupIngress operation. +func (c *EC2) RevokeSecurityGroupIngressRequest(input *RevokeSecurityGroupIngressInput) (req *request.Request, output *RevokeSecurityGroupIngressOutput) { + op := &request.Operation{ + Name: opRevokeSecurityGroupIngress, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RevokeSecurityGroupIngressInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &RevokeSecurityGroupIngressOutput{} + req.Data = output + return +} + +// Removes one or more ingress rules from a security group. The values that +// you specify in the revoke request (for example, ports) must match the existing +// rule's values for the rule to be removed. +// +// Each rule consists of the protocol and the CIDR range or source security +// group. For the TCP and UDP protocols, you must also specify the destination +// port or range of ports. For the ICMP protocol, you must also specify the +// ICMP type and code. +// +// Rule changes are propagated to instances within the security group as quickly +// as possible. However, a small delay might occur. +func (c *EC2) RevokeSecurityGroupIngress(input *RevokeSecurityGroupIngressInput) (*RevokeSecurityGroupIngressOutput, error) { + req, out := c.RevokeSecurityGroupIngressRequest(input) + err := req.Send() + return out, err +} + +const opRunInstances = "RunInstances" + +// RunInstancesRequest generates a request for the RunInstances operation. +func (c *EC2) RunInstancesRequest(input *RunInstancesInput) (req *request.Request, output *Reservation) { + op := &request.Operation{ + Name: opRunInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RunInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &Reservation{} + req.Data = output + return +} + +// Launches the specified number of instances using an AMI for which you have +// permissions. +// +// When you launch an instance, it enters the pending state. After the instance +// is ready for you, it enters the running state. To check the state of your +// instance, call DescribeInstances. +// +// If you don't specify a security group when launching an instance, Amazon +// EC2 uses the default security group. For more information, see Security Groups +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// [EC2-VPC only accounts] If you don't specify a subnet in the request, we +// choose a default subnet from your default VPC for you. +// +// [EC2-Classic accounts] If you're launching into EC2-Classic and you don't +// specify an Availability Zone, we choose one for you. +// +// Linux instances have access to the public key of the key pair at boot. You +// can use this key to provide secure access to the instance. Amazon EC2 public +// images use this feature to provide secure access without passwords. For more +// information, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// You can provide optional user data when launching an instance. For more +// information, see Instance Metadata (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// If any of the AMIs have a product code attached for which the user has not +// subscribed, RunInstances fails. +// +// T2 instance types can only be launched into a VPC. If you do not have a +// default VPC, or if you do not specify a subnet ID in the request, RunInstances +// fails. +// +// For more information about troubleshooting, see What To Do If An Instance +// Immediately Terminates (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_InstanceStraightToTerminated.html), +// and Troubleshooting Connecting to Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) RunInstances(input *RunInstancesInput) (*Reservation, error) { + req, out := c.RunInstancesRequest(input) + err := req.Send() + return out, err +} + +const opRunScheduledInstances = "RunScheduledInstances" + +// RunScheduledInstancesRequest generates a request for the RunScheduledInstances operation. +func (c *EC2) RunScheduledInstancesRequest(input *RunScheduledInstancesInput) (req *request.Request, output *RunScheduledInstancesOutput) { + op := &request.Operation{ + Name: opRunScheduledInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RunScheduledInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &RunScheduledInstancesOutput{} + req.Data = output + return +} + +// Launches the specified Scheduled Instances. +// +// Before you can launch a Scheduled Instance, you must purchase it and obtain +// an identifier using PurchaseScheduledInstances. +// +// You must launch a Scheduled Instance during its scheduled time period. You +// can't stop or reboot a Scheduled Instance, but you can terminate it as needed. +// If you terminate a Scheduled Instance before the current scheduled time period +// ends, you can launch it again after a few minutes. +func (c *EC2) RunScheduledInstances(input *RunScheduledInstancesInput) (*RunScheduledInstancesOutput, error) { + req, out := c.RunScheduledInstancesRequest(input) + err := req.Send() + return out, err +} + +const opStartInstances = "StartInstances" + +// StartInstancesRequest generates a request for the StartInstances operation. +func (c *EC2) StartInstancesRequest(input *StartInstancesInput) (req *request.Request, output *StartInstancesOutput) { + op := &request.Operation{ + Name: opStartInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &StartInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &StartInstancesOutput{} + req.Data = output + return +} + +// Starts an Amazon EBS-backed AMI that you've previously stopped. +// +// Instances that use Amazon EBS volumes as their root devices can be quickly +// stopped and started. When an instance is stopped, the compute resources are +// released and you are not billed for hourly instance usage. However, your +// root partition Amazon EBS volume remains, continues to persist your data, +// and you are charged for Amazon EBS volume usage. You can restart your instance +// at any time. Each time you transition an instance from stopped to started, +// Amazon EC2 charges a full instance hour, even if transitions happen multiple +// times within a single hour. +// +// Before stopping an instance, make sure it is in a state from which it can +// be restarted. Stopping an instance does not preserve data stored in RAM. +// +// Performing this operation on an instance that uses an instance store as +// its root device returns an error. +// +// For more information, see Stopping Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Stop_Start.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) StartInstances(input *StartInstancesInput) (*StartInstancesOutput, error) { + req, out := c.StartInstancesRequest(input) + err := req.Send() + return out, err +} + +const opStopInstances = "StopInstances" + +// StopInstancesRequest generates a request for the StopInstances operation. +func (c *EC2) StopInstancesRequest(input *StopInstancesInput) (req *request.Request, output *StopInstancesOutput) { + op := &request.Operation{ + Name: opStopInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &StopInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &StopInstancesOutput{} + req.Data = output + return +} + +// Stops an Amazon EBS-backed instance. Each time you transition an instance +// from stopped to started, Amazon EC2 charges a full instance hour, even if +// transitions happen multiple times within a single hour. +// +// You can't start or stop Spot instances. +// +// Instances that use Amazon EBS volumes as their root devices can be quickly +// stopped and started. When an instance is stopped, the compute resources are +// released and you are not billed for hourly instance usage. However, your +// root partition Amazon EBS volume remains, continues to persist your data, +// and you are charged for Amazon EBS volume usage. You can restart your instance +// at any time. +// +// Before stopping an instance, make sure it is in a state from which it can +// be restarted. Stopping an instance does not preserve data stored in RAM. +// +// Performing this operation on an instance that uses an instance store as +// its root device returns an error. +// +// You can stop, start, and terminate EBS-backed instances. You can only terminate +// instance store-backed instances. What happens to an instance differs if you +// stop it or terminate it. For example, when you stop an instance, the root +// device and any other devices attached to the instance persist. When you terminate +// an instance, the root device and any other devices attached during the instance +// launch are automatically deleted. For more information about the differences +// between stopping and terminating instances, see Instance Lifecycle (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// For more information about troubleshooting, see Troubleshooting Stopping +// Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesStopping.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) StopInstances(input *StopInstancesInput) (*StopInstancesOutput, error) { + req, out := c.StopInstancesRequest(input) + err := req.Send() + return out, err +} + +const opTerminateInstances = "TerminateInstances" + +// TerminateInstancesRequest generates a request for the TerminateInstances operation. +func (c *EC2) TerminateInstancesRequest(input *TerminateInstancesInput) (req *request.Request, output *TerminateInstancesOutput) { + op := &request.Operation{ + Name: opTerminateInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &TerminateInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &TerminateInstancesOutput{} + req.Data = output + return +} + +// Shuts down one or more instances. This operation is idempotent; if you terminate +// an instance more than once, each call succeeds. +// +// Terminated instances remain visible after termination (for approximately +// one hour). +// +// By default, Amazon EC2 deletes all EBS volumes that were attached when the +// instance launched. Volumes attached after instance launch continue running. +// +// You can stop, start, and terminate EBS-backed instances. You can only terminate +// instance store-backed instances. What happens to an instance differs if you +// stop it or terminate it. For example, when you stop an instance, the root +// device and any other devices attached to the instance persist. When you terminate +// an instance, any attached EBS volumes with the DeleteOnTermination block +// device mapping parameter set to true are automatically deleted. For more +// information about the differences between stopping and terminating instances, +// see Instance Lifecycle (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) +// in the Amazon Elastic Compute Cloud User Guide. +// +// For more information about troubleshooting, see Troubleshooting Terminating +// Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesShuttingDown.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) TerminateInstances(input *TerminateInstancesInput) (*TerminateInstancesOutput, error) { + req, out := c.TerminateInstancesRequest(input) + err := req.Send() + return out, err +} + +const opUnassignPrivateIpAddresses = "UnassignPrivateIpAddresses" + +// UnassignPrivateIpAddressesRequest generates a request for the UnassignPrivateIpAddresses operation. +func (c *EC2) UnassignPrivateIpAddressesRequest(input *UnassignPrivateIpAddressesInput) (req *request.Request, output *UnassignPrivateIpAddressesOutput) { + op := &request.Operation{ + Name: opUnassignPrivateIpAddresses, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UnassignPrivateIpAddressesInput{} + } + + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(ec2query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + output = &UnassignPrivateIpAddressesOutput{} + req.Data = output + return +} + +// Unassigns one or more secondary private IP addresses from a network interface. +func (c *EC2) UnassignPrivateIpAddresses(input *UnassignPrivateIpAddressesInput) (*UnassignPrivateIpAddressesOutput, error) { + req, out := c.UnassignPrivateIpAddressesRequest(input) + err := req.Send() + return out, err +} + +const opUnmonitorInstances = "UnmonitorInstances" + +// UnmonitorInstancesRequest generates a request for the UnmonitorInstances operation. +func (c *EC2) UnmonitorInstancesRequest(input *UnmonitorInstancesInput) (req *request.Request, output *UnmonitorInstancesOutput) { + op := &request.Operation{ + Name: opUnmonitorInstances, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UnmonitorInstancesInput{} + } + + req = c.newRequest(op, input, output) + output = &UnmonitorInstancesOutput{} + req.Data = output + return +} + +// Disables monitoring for a running instance. For more information about monitoring +// instances, see Monitoring Your Instances and Volumes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch.html) +// in the Amazon Elastic Compute Cloud User Guide. +func (c *EC2) UnmonitorInstances(input *UnmonitorInstancesInput) (*UnmonitorInstancesOutput, error) { + req, out := c.UnmonitorInstancesRequest(input) + err := req.Send() + return out, err +} + +type AcceptVpcPeeringConnectionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` +} + +// String returns the string representation +func (s AcceptVpcPeeringConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AcceptVpcPeeringConnectionInput) GoString() string { + return s.String() +} + +type AcceptVpcPeeringConnectionOutput struct { + _ struct{} `type:"structure"` + + // Information about the VPC peering connection. + VpcPeeringConnection *VpcPeeringConnection `locationName:"vpcPeeringConnection" type:"structure"` +} + +// String returns the string representation +func (s AcceptVpcPeeringConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AcceptVpcPeeringConnectionOutput) GoString() string { + return s.String() +} + +// Describes an account attribute. +type AccountAttribute struct { + _ struct{} `type:"structure"` + + // The name of the account attribute. + AttributeName *string `locationName:"attributeName" type:"string"` + + // One or more values for the account attribute. + AttributeValues []*AccountAttributeValue `locationName:"attributeValueSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s AccountAttribute) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AccountAttribute) GoString() string { + return s.String() +} + +// Describes a value of an account attribute. +type AccountAttributeValue struct { + _ struct{} `type:"structure"` + + // The value of the attribute. + AttributeValue *string `locationName:"attributeValue" type:"string"` +} + +// String returns the string representation +func (s AccountAttributeValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AccountAttributeValue) GoString() string { + return s.String() +} + +// Describes a running instance in a Spot fleet. +type ActiveInstance struct { + _ struct{} `type:"structure"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string"` + + // The ID of the Spot instance request. + SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` +} + +// String returns the string representation +func (s ActiveInstance) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ActiveInstance) GoString() string { + return s.String() +} + +// Describes an Elastic IP address. +type Address struct { + _ struct{} `type:"structure"` + + // The ID representing the allocation of the address for use with EC2-VPC. + AllocationId *string `locationName:"allocationId" type:"string"` + + // The ID representing the association of the address with an instance in a + // VPC. + AssociationId *string `locationName:"associationId" type:"string"` + + // Indicates whether this Elastic IP address is for use with instances in EC2-Classic + // (standard) or instances in a VPC (vpc). + Domain *string `locationName:"domain" type:"string" enum:"DomainType"` + + // The ID of the instance that the address is associated with (if any). + InstanceId *string `locationName:"instanceId" type:"string"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The ID of the AWS account that owns the network interface. + NetworkInterfaceOwnerId *string `locationName:"networkInterfaceOwnerId" type:"string"` + + // The private IP address associated with the Elastic IP address. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s Address) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Address) GoString() string { + return s.String() +} + +type AllocateAddressInput struct { + _ struct{} `type:"structure"` + + // Set to vpc to allocate the address for use with instances in a VPC. + // + // Default: The address is for use with instances in EC2-Classic. + Domain *string `type:"string" enum:"DomainType"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s AllocateAddressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AllocateAddressInput) GoString() string { + return s.String() +} + +type AllocateAddressOutput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] The ID that AWS assigns to represent the allocation of the Elastic + // IP address for use with instances in a VPC. + AllocationId *string `locationName:"allocationId" type:"string"` + + // Indicates whether this Elastic IP address is for use with instances in EC2-Classic + // (standard) or instances in a VPC (vpc). + Domain *string `locationName:"domain" type:"string" enum:"DomainType"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s AllocateAddressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AllocateAddressOutput) GoString() string { + return s.String() +} + +type AllocateHostsInput struct { + _ struct{} `type:"structure"` + + // This is enabled by default. This property allows instances to be automatically + // placed onto available Dedicated hosts, when you are launching instances without + // specifying a host ID. + // + // Default: Enabled + AutoPlacement *string `locationName:"autoPlacement" type:"string" enum:"AutoPlacement"` + + // The Availability Zone for the Dedicated hosts. + AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` + + // Unique, case-sensitive identifier you provide to ensure idempotency of the + // request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) + // in the Amazon Elastic Compute Cloud User Guide. + ClientToken *string `locationName:"clientToken" type:"string"` + + // Specify the instance type that you want your Dedicated hosts to be configured + // for. When you specify the instance type, that is the only instance type that + // you can launch onto that host. + InstanceType *string `locationName:"instanceType" type:"string" required:"true"` + + // The number of Dedicated hosts you want to allocate to your account with these + // parameters. + Quantity *int64 `locationName:"quantity" type:"integer" required:"true"` +} + +// String returns the string representation +func (s AllocateHostsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AllocateHostsInput) GoString() string { + return s.String() +} + +type AllocateHostsOutput struct { + _ struct{} `type:"structure"` + + // The ID of the allocated Dedicated host. This is used when you want to launch + // an instance onto a specific host. + HostIds []*string `locationName:"hostIdSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s AllocateHostsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AllocateHostsOutput) GoString() string { + return s.String() +} + +type AssignPrivateIpAddressesInput struct { + _ struct{} `type:"structure"` + + // Indicates whether to allow an IP address that is already assigned to another + // network interface or instance to be reassigned to the specified network interface. + AllowReassignment *bool `locationName:"allowReassignment" type:"boolean"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` + + // One or more IP addresses to be assigned as a secondary private IP address + // to the network interface. You can't specify this parameter when also specifying + // a number of secondary IP addresses. + // + // If you don't specify an IP address, Amazon EC2 automatically selects an + // IP address within the subnet range. + PrivateIpAddresses []*string `locationName:"privateIpAddress" locationNameList:"PrivateIpAddress" type:"list"` + + // The number of secondary IP addresses to assign to the network interface. + // You can't specify this parameter when also specifying private IP addresses. + SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` +} + +// String returns the string representation +func (s AssignPrivateIpAddressesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssignPrivateIpAddressesInput) GoString() string { + return s.String() +} + +type AssignPrivateIpAddressesOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s AssignPrivateIpAddressesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssignPrivateIpAddressesOutput) GoString() string { + return s.String() +} + +type AssociateAddressInput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] The allocation ID. This is required for EC2-VPC. + AllocationId *string `type:"string"` + + // [EC2-VPC] For a VPC in an EC2-Classic account, specify true to allow an Elastic + // IP address that is already associated with an instance or network interface + // to be reassociated with the specified instance or network interface. Otherwise, + // the operation fails. In a VPC in an EC2-VPC-only account, reassociation is + // automatic, therefore you can specify false to ensure the operation fails + // if the Elastic IP address is already associated with another resource. + AllowReassociation *bool `locationName:"allowReassociation" type:"boolean"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. This is required for EC2-Classic. For EC2-VPC, you + // can specify either the instance ID or the network interface ID, but not both. + // The operation fails if you specify an instance ID unless exactly one network + // interface is attached. + InstanceId *string `type:"string"` + + // [EC2-VPC] The ID of the network interface. If the instance has more than + // one network interface, you must specify a network interface ID. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // [EC2-VPC] The primary or secondary private IP address to associate with the + // Elastic IP address. If no private IP address is specified, the Elastic IP + // address is associated with the primary private IP address. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The Elastic IP address. This is required for EC2-Classic. + PublicIp *string `type:"string"` +} + +// String returns the string representation +func (s AssociateAddressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateAddressInput) GoString() string { + return s.String() +} + +type AssociateAddressOutput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] The ID that represents the association of the Elastic IP address + // with an instance. + AssociationId *string `locationName:"associationId" type:"string"` +} + +// String returns the string representation +func (s AssociateAddressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateAddressOutput) GoString() string { + return s.String() +} + +type AssociateDhcpOptionsInput struct { + _ struct{} `type:"structure"` + + // The ID of the DHCP options set, or default to associate no DHCP options with + // the VPC. + DhcpOptionsId *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s AssociateDhcpOptionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateDhcpOptionsInput) GoString() string { + return s.String() +} + +type AssociateDhcpOptionsOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s AssociateDhcpOptionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateDhcpOptionsOutput) GoString() string { + return s.String() +} + +type AssociateRouteTableInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssociateRouteTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateRouteTableInput) GoString() string { + return s.String() +} + +type AssociateRouteTableOutput struct { + _ struct{} `type:"structure"` + + // The route table association ID (needed to disassociate the route table). + AssociationId *string `locationName:"associationId" type:"string"` +} + +// String returns the string representation +func (s AssociateRouteTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssociateRouteTableOutput) GoString() string { + return s.String() +} + +type AttachClassicLinkVpcInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of one or more of the VPC's security groups. You cannot specify security + // groups from a different VPC. + Groups []*string `locationName:"SecurityGroupId" locationNameList:"groupId" type:"list" required:"true"` + + // The ID of an EC2-Classic instance to link to the ClassicLink-enabled VPC. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // The ID of a ClassicLink-enabled VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s AttachClassicLinkVpcInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachClassicLinkVpcInput) GoString() string { + return s.String() +} + +type AttachClassicLinkVpcOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s AttachClassicLinkVpcOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachClassicLinkVpcOutput) GoString() string { + return s.String() +} + +type AttachInternetGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the Internet gateway. + InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s AttachInternetGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachInternetGatewayInput) GoString() string { + return s.String() +} + +type AttachInternetGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s AttachInternetGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachInternetGatewayOutput) GoString() string { + return s.String() +} + +type AttachNetworkInterfaceInput struct { + _ struct{} `type:"structure"` + + // The index of the device for the network interface attachment. + DeviceIndex *int64 `locationName:"deviceIndex" type:"integer" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` +} + +// String returns the string representation +func (s AttachNetworkInterfaceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachNetworkInterfaceInput) GoString() string { + return s.String() +} + +type AttachNetworkInterfaceOutput struct { + _ struct{} `type:"structure"` + + // The ID of the network interface attachment. + AttachmentId *string `locationName:"attachmentId" type:"string"` +} + +// String returns the string representation +func (s AttachNetworkInterfaceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachNetworkInterfaceOutput) GoString() string { + return s.String() +} + +type AttachVolumeInput struct { + _ struct{} `type:"structure"` + + // The device name to expose to the instance (for example, /dev/sdh or xvdh). + Device *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `type:"string" required:"true"` + + // The ID of the EBS volume. The volume and instance must be within the same + // Availability Zone. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s AttachVolumeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachVolumeInput) GoString() string { + return s.String() +} + +type AttachVpnGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` + + // The ID of the virtual private gateway. + VpnGatewayId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s AttachVpnGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachVpnGatewayInput) GoString() string { + return s.String() +} + +type AttachVpnGatewayOutput struct { + _ struct{} `type:"structure"` + + // Information about the attachment. + VpcAttachment *VpcAttachment `locationName:"attachment" type:"structure"` +} + +// String returns the string representation +func (s AttachVpnGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttachVpnGatewayOutput) GoString() string { + return s.String() +} + +// The value to use when a resource attribute accepts a Boolean value. +type AttributeBooleanValue struct { + _ struct{} `type:"structure"` + + // Valid values are true or false. + Value *bool `locationName:"value" type:"boolean"` +} + +// String returns the string representation +func (s AttributeBooleanValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttributeBooleanValue) GoString() string { + return s.String() +} + +// The value to use for a resource attribute. +type AttributeValue struct { + _ struct{} `type:"structure"` + + // Valid values are case-sensitive and vary by action. + Value *string `locationName:"value" type:"string"` +} + +// String returns the string representation +func (s AttributeValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttributeValue) GoString() string { + return s.String() +} + +type AuthorizeSecurityGroupEgressInput struct { + _ struct{} `type:"structure"` + + // The CIDR IP address range. We recommend that you specify the CIDR range in + // a set of IP permissions instead. + CidrIp *string `locationName:"cidrIp" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The start of port range for the TCP and UDP protocols, or an ICMP type number. + // We recommend that you specify the port range in a set of IP permissions instead. + FromPort *int64 `locationName:"fromPort" type:"integer"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string" required:"true"` + + // A set of IP permissions. You can't specify a destination security group and + // a CIDR IP address range. + IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` + + // The IP protocol name or number. We recommend that you specify the protocol + // in a set of IP permissions instead. + IpProtocol *string `locationName:"ipProtocol" type:"string"` + + // The name of a destination security group. To authorize outbound access to + // a destination security group, we recommend that you use a set of IP permissions + // instead. + SourceSecurityGroupName *string `locationName:"sourceSecurityGroupName" type:"string"` + + // The AWS account number for a destination security group. To authorize outbound + // access to a destination security group, we recommend that you use a set of + // IP permissions instead. + SourceSecurityGroupOwnerId *string `locationName:"sourceSecurityGroupOwnerId" type:"string"` + + // The end of port range for the TCP and UDP protocols, or an ICMP type number. + // We recommend that you specify the port range in a set of IP permissions instead. + ToPort *int64 `locationName:"toPort" type:"integer"` +} + +// String returns the string representation +func (s AuthorizeSecurityGroupEgressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AuthorizeSecurityGroupEgressInput) GoString() string { + return s.String() +} + +type AuthorizeSecurityGroupEgressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s AuthorizeSecurityGroupEgressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AuthorizeSecurityGroupEgressOutput) GoString() string { + return s.String() +} + +type AuthorizeSecurityGroupIngressInput struct { + _ struct{} `type:"structure"` + + // The CIDR IP address range. You can't specify this parameter when specifying + // a source security group. + CidrIp *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The start of port range for the TCP and UDP protocols, or an ICMP type number. + // For the ICMP type number, use -1 to specify all ICMP types. + FromPort *int64 `type:"integer"` + + // The ID of the security group. Required for a nondefault VPC. + GroupId *string `type:"string"` + + // [EC2-Classic, default VPC] The name of the security group. + GroupName *string `type:"string"` + + // A set of IP permissions. Can be used to specify multiple rules in a single + // command. + IpPermissions []*IpPermission `locationNameList:"item" type:"list"` + + // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). + // (VPC only) Use -1 to specify all. + IpProtocol *string `type:"string"` + + // [EC2-Classic, default VPC] The name of the source security group. You can't + // specify this parameter in combination with the following parameters: the + // CIDR IP address range, the start of the port range, the IP protocol, and + // the end of the port range. For EC2-VPC, the source security group must be + // in the same VPC. + SourceSecurityGroupName *string `type:"string"` + + // [EC2-Classic, default VPC] The AWS account number for the source security + // group. For EC2-VPC, the source security group must be in the same VPC. You + // can't specify this parameter in combination with the following parameters: + // the CIDR IP address range, the IP protocol, the start of the port range, + // and the end of the port range. Creates rules that grant full ICMP, UDP, and + // TCP access. To create a rule with a specific IP protocol and port range, + // use a set of IP permissions instead. + SourceSecurityGroupOwnerId *string `type:"string"` + + // The end of port range for the TCP and UDP protocols, or an ICMP code number. + // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. + ToPort *int64 `type:"integer"` +} + +// String returns the string representation +func (s AuthorizeSecurityGroupIngressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AuthorizeSecurityGroupIngressInput) GoString() string { + return s.String() +} + +type AuthorizeSecurityGroupIngressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s AuthorizeSecurityGroupIngressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AuthorizeSecurityGroupIngressOutput) GoString() string { + return s.String() +} + +// Describes an Availability Zone. +type AvailabilityZone struct { + _ struct{} `type:"structure"` + + // Any messages about the Availability Zone. + Messages []*AvailabilityZoneMessage `locationName:"messageSet" locationNameList:"item" type:"list"` + + // The name of the region. + RegionName *string `locationName:"regionName" type:"string"` + + // The state of the Availability Zone. + State *string `locationName:"zoneState" type:"string" enum:"AvailabilityZoneState"` + + // The name of the Availability Zone. + ZoneName *string `locationName:"zoneName" type:"string"` +} + +// String returns the string representation +func (s AvailabilityZone) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AvailabilityZone) GoString() string { + return s.String() +} + +// Describes a message about an Availability Zone. +type AvailabilityZoneMessage struct { + _ struct{} `type:"structure"` + + // The message about the Availability Zone. + Message *string `locationName:"message" type:"string"` +} + +// String returns the string representation +func (s AvailabilityZoneMessage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AvailabilityZoneMessage) GoString() string { + return s.String() +} + +// The capacity information for instances launched onto the Dedicated host. +type AvailableCapacity struct { + _ struct{} `type:"structure"` + + // The total number of instances that the Dedicated host supports. + AvailableInstanceCapacity []*InstanceCapacity `locationName:"availableInstanceCapacity" locationNameList:"item" type:"list"` + + // The number of vCPUs available on the Dedicated host. + AvailableVCpus *int64 `locationName:"availableVCpus" type:"integer"` +} + +// String returns the string representation +func (s AvailableCapacity) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AvailableCapacity) GoString() string { + return s.String() +} + +type BlobAttributeValue struct { + _ struct{} `type:"structure"` + + Value []byte `locationName:"value" type:"blob"` +} + +// String returns the string representation +func (s BlobAttributeValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BlobAttributeValue) GoString() string { + return s.String() +} + +// Describes a block device mapping. +type BlockDeviceMapping struct { + _ struct{} `type:"structure"` + + // The device name exposed to the instance (for example, /dev/sdh or xvdh). + DeviceName *string `locationName:"deviceName" type:"string"` + + // Parameters used to automatically set up EBS volumes when the instance is + // launched. + Ebs *EbsBlockDevice `locationName:"ebs" type:"structure"` + + // Suppresses the specified device included in the block device mapping of the + // AMI. + NoDevice *string `locationName:"noDevice" type:"string"` + + // The virtual device name (ephemeralN). Instance store volumes are numbered + // starting from 0. An instance type with 2 available instance store volumes + // can specify mappings for ephemeral0 and ephemeral1.The number of available + // instance store volumes depends on the instance type. After you connect to + // the instance, you must mount the volume. + // + // Constraints: For M3 instances, you must specify instance store volumes in + // the block device mapping for the instance. When you launch an M3 instance, + // we ignore any instance store volumes specified in the block device mapping + // for the AMI. + VirtualName *string `locationName:"virtualName" type:"string"` +} + +// String returns the string representation +func (s BlockDeviceMapping) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BlockDeviceMapping) GoString() string { + return s.String() +} + +type BundleInstanceInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance to bundle. + // + // Type: String + // + // Default: None + // + // Required: Yes + InstanceId *string `type:"string" required:"true"` + + // The bucket in which to store the AMI. You can specify a bucket that you already + // own or a new bucket that Amazon EC2 creates on your behalf. If you specify + // a bucket that belongs to someone else, Amazon EC2 returns an error. + Storage *Storage `type:"structure" required:"true"` +} + +// String returns the string representation +func (s BundleInstanceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BundleInstanceInput) GoString() string { + return s.String() +} + +type BundleInstanceOutput struct { + _ struct{} `type:"structure"` + + // Information about the bundle task. + BundleTask *BundleTask `locationName:"bundleInstanceTask" type:"structure"` +} + +// String returns the string representation +func (s BundleInstanceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BundleInstanceOutput) GoString() string { + return s.String() +} + +// Describes a bundle task. +type BundleTask struct { + _ struct{} `type:"structure"` + + // The ID of the bundle task. + BundleId *string `locationName:"bundleId" type:"string"` + + // If the task fails, a description of the error. + BundleTaskError *BundleTaskError `locationName:"error" type:"structure"` + + // The ID of the instance associated with this bundle task. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The level of task completion, as a percent (for example, 20%). + Progress *string `locationName:"progress" type:"string"` + + // The time this task started. + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` + + // The state of the task. + State *string `locationName:"state" type:"string" enum:"BundleTaskState"` + + // The Amazon S3 storage locations. + Storage *Storage `locationName:"storage" type:"structure"` + + // The time of the most recent update for the task. + UpdateTime *time.Time `locationName:"updateTime" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s BundleTask) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BundleTask) GoString() string { + return s.String() +} + +// Describes an error for BundleInstance. +type BundleTaskError struct { + _ struct{} `type:"structure"` + + // The error code. + Code *string `locationName:"code" type:"string"` + + // The error message. + Message *string `locationName:"message" type:"string"` +} + +// String returns the string representation +func (s BundleTaskError) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BundleTaskError) GoString() string { + return s.String() +} + +type CancelBundleTaskInput struct { + _ struct{} `type:"structure"` + + // The ID of the bundle task. + BundleId *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s CancelBundleTaskInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelBundleTaskInput) GoString() string { + return s.String() +} + +type CancelBundleTaskOutput struct { + _ struct{} `type:"structure"` + + // Information about the bundle task. + BundleTask *BundleTask `locationName:"bundleInstanceTask" type:"structure"` +} + +// String returns the string representation +func (s CancelBundleTaskOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelBundleTaskOutput) GoString() string { + return s.String() +} + +type CancelConversionTaskInput struct { + _ struct{} `type:"structure"` + + // The ID of the conversion task. + ConversionTaskId *string `locationName:"conversionTaskId" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The reason for canceling the conversion task. + ReasonMessage *string `locationName:"reasonMessage" type:"string"` +} + +// String returns the string representation +func (s CancelConversionTaskInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelConversionTaskInput) GoString() string { + return s.String() +} + +type CancelConversionTaskOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CancelConversionTaskOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelConversionTaskOutput) GoString() string { + return s.String() +} + +type CancelExportTaskInput struct { + _ struct{} `type:"structure"` + + // The ID of the export task. This is the ID returned by CreateInstanceExportTask. + ExportTaskId *string `locationName:"exportTaskId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CancelExportTaskInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelExportTaskInput) GoString() string { + return s.String() +} + +type CancelExportTaskOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CancelExportTaskOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelExportTaskOutput) GoString() string { + return s.String() +} + +type CancelImportTaskInput struct { + _ struct{} `type:"structure"` + + // The reason for canceling the task. + CancelReason *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // The ID of the import image or import snapshot task to be canceled. + ImportTaskId *string `type:"string"` +} + +// String returns the string representation +func (s CancelImportTaskInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelImportTaskInput) GoString() string { + return s.String() +} + +type CancelImportTaskOutput struct { + _ struct{} `type:"structure"` + + // The ID of the task being canceled. + ImportTaskId *string `locationName:"importTaskId" type:"string"` + + // The current state of the task being canceled. + PreviousState *string `locationName:"previousState" type:"string"` + + // The current state of the task being canceled. + State *string `locationName:"state" type:"string"` +} + +// String returns the string representation +func (s CancelImportTaskOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelImportTaskOutput) GoString() string { + return s.String() +} + +type CancelReservedInstancesListingInput struct { + _ struct{} `type:"structure"` + + // The ID of the Reserved Instance listing. + ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CancelReservedInstancesListingInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelReservedInstancesListingInput) GoString() string { + return s.String() +} + +type CancelReservedInstancesListingOutput struct { + _ struct{} `type:"structure"` + + // The Reserved Instance listing. + ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CancelReservedInstancesListingOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelReservedInstancesListingOutput) GoString() string { + return s.String() +} + +// Describes a Spot fleet error. +type CancelSpotFleetRequestsError struct { + _ struct{} `type:"structure"` + + // The error code. + Code *string `locationName:"code" type:"string" required:"true" enum:"CancelBatchErrorCode"` + + // The description for the error code. + Message *string `locationName:"message" type:"string" required:"true"` +} + +// String returns the string representation +func (s CancelSpotFleetRequestsError) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotFleetRequestsError) GoString() string { + return s.String() +} + +// Describes a Spot fleet request that was not successfully canceled. +type CancelSpotFleetRequestsErrorItem struct { + _ struct{} `type:"structure"` + + // The error. + Error *CancelSpotFleetRequestsError `locationName:"error" type:"structure" required:"true"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CancelSpotFleetRequestsErrorItem) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotFleetRequestsErrorItem) GoString() string { + return s.String() +} + +// Contains the parameters for CancelSpotFleetRequests. +type CancelSpotFleetRequestsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The IDs of the Spot fleet requests. + SpotFleetRequestIds []*string `locationName:"spotFleetRequestId" locationNameList:"item" type:"list" required:"true"` + + // Indicates whether to terminate instances for a Spot fleet request if it is + // canceled successfully. + TerminateInstances *bool `locationName:"terminateInstances" type:"boolean" required:"true"` +} + +// String returns the string representation +func (s CancelSpotFleetRequestsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotFleetRequestsInput) GoString() string { + return s.String() +} + +// Contains the output of CancelSpotFleetRequests. +type CancelSpotFleetRequestsOutput struct { + _ struct{} `type:"structure"` + + // Information about the Spot fleet requests that are successfully canceled. + SuccessfulFleetRequests []*CancelSpotFleetRequestsSuccessItem `locationName:"successfulFleetRequestSet" locationNameList:"item" type:"list"` + + // Information about the Spot fleet requests that are not successfully canceled. + UnsuccessfulFleetRequests []*CancelSpotFleetRequestsErrorItem `locationName:"unsuccessfulFleetRequestSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CancelSpotFleetRequestsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotFleetRequestsOutput) GoString() string { + return s.String() +} + +// Describes a Spot fleet request that was successfully canceled. +type CancelSpotFleetRequestsSuccessItem struct { + _ struct{} `type:"structure"` + + // The current state of the Spot fleet request. + CurrentSpotFleetRequestState *string `locationName:"currentSpotFleetRequestState" type:"string" required:"true" enum:"BatchState"` + + // The previous state of the Spot fleet request. + PreviousSpotFleetRequestState *string `locationName:"previousSpotFleetRequestState" type:"string" required:"true" enum:"BatchState"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CancelSpotFleetRequestsSuccessItem) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotFleetRequestsSuccessItem) GoString() string { + return s.String() +} + +// Contains the parameters for CancelSpotInstanceRequests. +type CancelSpotInstanceRequestsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more Spot instance request IDs. + SpotInstanceRequestIds []*string `locationName:"SpotInstanceRequestId" locationNameList:"SpotInstanceRequestId" type:"list" required:"true"` +} + +// String returns the string representation +func (s CancelSpotInstanceRequestsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotInstanceRequestsInput) GoString() string { + return s.String() +} + +// Contains the output of CancelSpotInstanceRequests. +type CancelSpotInstanceRequestsOutput struct { + _ struct{} `type:"structure"` + + // One or more Spot instance requests. + CancelledSpotInstanceRequests []*CancelledSpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CancelSpotInstanceRequestsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelSpotInstanceRequestsOutput) GoString() string { + return s.String() +} + +// Describes a request to cancel a Spot instance. +type CancelledSpotInstanceRequest struct { + _ struct{} `type:"structure"` + + // The ID of the Spot instance request. + SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` + + // The state of the Spot instance request. + State *string `locationName:"state" type:"string" enum:"CancelSpotInstanceRequestState"` +} + +// String returns the string representation +func (s CancelledSpotInstanceRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CancelledSpotInstanceRequest) GoString() string { + return s.String() +} + +// Describes the ClassicLink DNS support status of a VPC. +type ClassicLinkDnsSupport struct { + _ struct{} `type:"structure"` + + // Indicates whether ClassicLink DNS support is enabled for the VPC. + ClassicLinkDnsSupported *bool `locationName:"classicLinkDnsSupported" type:"boolean"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s ClassicLinkDnsSupport) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ClassicLinkDnsSupport) GoString() string { + return s.String() +} + +// Describes a linked EC2-Classic instance. +type ClassicLinkInstance struct { + _ struct{} `type:"structure"` + + // A list of security groups. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // Any tags assigned to the instance. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s ClassicLinkInstance) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ClassicLinkInstance) GoString() string { + return s.String() +} + +// Describes the client-specific data. +type ClientData struct { + _ struct{} `type:"structure"` + + // A user-defined comment about the disk upload. + Comment *string `type:"string"` + + // The time that the disk upload ends. + UploadEnd *time.Time `type:"timestamp" timestampFormat:"iso8601"` + + // The size of the uploaded disk image, in GiB. + UploadSize *float64 `type:"double"` + + // The time that the disk upload starts. + UploadStart *time.Time `type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s ClientData) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ClientData) GoString() string { + return s.String() +} + +type ConfirmProductInstanceInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `type:"string" required:"true"` + + // The product code. This must be a product code that you own. + ProductCode *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s ConfirmProductInstanceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ConfirmProductInstanceInput) GoString() string { + return s.String() +} + +type ConfirmProductInstanceOutput struct { + _ struct{} `type:"structure"` + + // The AWS account ID of the instance owner. This is only present if the product + // code is attached to the instance. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The return value of the request. Returns true if the specified product code + // is owned by the requester and associated with the specified instance. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s ConfirmProductInstanceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ConfirmProductInstanceOutput) GoString() string { + return s.String() +} + +// Describes a conversion task. +type ConversionTask struct { + _ struct{} `type:"structure"` + + // The ID of the conversion task. + ConversionTaskId *string `locationName:"conversionTaskId" type:"string" required:"true"` + + // The time when the task expires. If the upload isn't complete before the expiration + // time, we automatically cancel the task. + ExpirationTime *string `locationName:"expirationTime" type:"string"` + + // If the task is for importing an instance, this contains information about + // the import instance task. + ImportInstance *ImportInstanceTaskDetails `locationName:"importInstance" type:"structure"` + + // If the task is for importing a volume, this contains information about the + // import volume task. + ImportVolume *ImportVolumeTaskDetails `locationName:"importVolume" type:"structure"` + + // The state of the conversion task. + State *string `locationName:"state" type:"string" required:"true" enum:"ConversionTaskState"` + + // The status message related to the conversion task. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // Any tags assigned to the task. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s ConversionTask) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ConversionTask) GoString() string { + return s.String() +} + +type CopyImageInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure idempotency of the + // request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) + // in the Amazon Elastic Compute Cloud User Guide. + ClientToken *string `type:"string"` + + // A description for the new AMI in the destination region. + Description *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Specifies whether the destination snapshots of the copied image should be + // encrypted. The default CMK for EBS is used unless a non-default AWS Key Management + // Service (AWS KMS) CMK is specified with KmsKeyId. For more information, see + // Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) + // in the Amazon Elastic Compute Cloud User Guide. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // The full ARN of the AWS Key Management Service (AWS KMS) CMK to use when + // encrypting the snapshots of an image during a copy operation. This parameter + // is only required if you want to use a non-default CMK; if this parameter + // is not specified, the default CMK for EBS is used. The ARN contains the arn:aws:kms + // namespace, followed by the region of the CMK, the AWS account ID of the CMK + // owner, the key namespace, and then the CMK ID. For example, arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef. + // The specified CMK must exist in the region that the snapshot is being copied + // to. If a KmsKeyId is specified, the Encrypted flag must also be set. + KmsKeyId *string `locationName:"kmsKeyId" type:"string"` + + // The name of the new AMI in the destination region. + Name *string `type:"string" required:"true"` + + // The ID of the AMI to copy. + SourceImageId *string `type:"string" required:"true"` + + // The name of the region that contains the AMI to copy. + SourceRegion *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CopyImageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CopyImageInput) GoString() string { + return s.String() +} + +type CopyImageOutput struct { + _ struct{} `type:"structure"` + + // The ID of the new AMI. + ImageId *string `locationName:"imageId" type:"string"` +} + +// String returns the string representation +func (s CopyImageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CopyImageOutput) GoString() string { + return s.String() +} + +type CopySnapshotInput struct { + _ struct{} `type:"structure"` + + // A description for the EBS snapshot. + Description *string `type:"string"` + + // The destination region to use in the PresignedUrl parameter of a snapshot + // copy operation. This parameter is only valid for specifying the destination + // region in a PresignedUrl parameter, where it is required. + // + // CopySnapshot sends the snapshot copy to the regional endpoint that you + // send the HTTP request to, such as ec2.us-east-1.amazonaws.com (in the AWS + // CLI, this is specified with the --region parameter or the default region + // in your AWS configuration file). + DestinationRegion *string `locationName:"destinationRegion" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Specifies whether the destination snapshot should be encrypted. There is + // no way to create an unencrypted snapshot copy from an encrypted snapshot; + // however, you can encrypt a copy of an unencrypted snapshot with this flag. + // The default CMK for EBS is used unless a non-default AWS Key Management Service + // (AWS KMS) CMK is specified with KmsKeyId. For more information, see Amazon + // EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) + // in the Amazon Elastic Compute Cloud User Guide. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // The full ARN of the AWS Key Management Service (AWS KMS) CMK to use when + // creating the snapshot copy. This parameter is only required if you want to + // use a non-default CMK; if this parameter is not specified, the default CMK + // for EBS is used. The ARN contains the arn:aws:kms namespace, followed by + // the region of the CMK, the AWS account ID of the CMK owner, the key namespace, + // and then the CMK ID. For example, arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef. + // The specified CMK must exist in the region that the snapshot is being copied + // to. If a KmsKeyId is specified, the Encrypted flag must also be set. + KmsKeyId *string `locationName:"kmsKeyId" type:"string"` + + // The pre-signed URL that facilitates copying an encrypted snapshot. This parameter + // is only required when copying an encrypted snapshot with the Amazon EC2 Query + // API; it is available as an optional parameter in all other cases. The PresignedUrl + // should use the snapshot source endpoint, the CopySnapshot action, and include + // the SourceRegion, SourceSnapshotId, and DestinationRegion parameters. The + // PresignedUrl must be signed using AWS Signature Version 4. Because EBS snapshots + // are stored in Amazon S3, the signing algorithm for this parameter uses the + // same logic that is described in Authenticating Requests by Using Query Parameters + // (AWS Signature Version 4) (http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) + // in the Amazon Simple Storage Service API Reference. An invalid or improperly + // signed PresignedUrl will cause the copy operation to fail asynchronously, + // and the snapshot will move to an error state. + PresignedUrl *string `locationName:"presignedUrl" type:"string"` + + // The ID of the region that contains the snapshot to be copied. + SourceRegion *string `type:"string" required:"true"` + + // The ID of the EBS snapshot to copy. + SourceSnapshotId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CopySnapshotInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CopySnapshotInput) GoString() string { + return s.String() +} + +type CopySnapshotOutput struct { + _ struct{} `type:"structure"` + + // The ID of the new snapshot. + SnapshotId *string `locationName:"snapshotId" type:"string"` +} + +// String returns the string representation +func (s CopySnapshotOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CopySnapshotOutput) GoString() string { + return s.String() +} + +type CreateCustomerGatewayInput struct { + _ struct{} `type:"structure"` + + // For devices that support BGP, the customer gateway's BGP ASN. + // + // Default: 65000 + BgpAsn *int64 `type:"integer" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The Internet-routable IP address for the customer gateway's outside interface. + // The address must be static. + PublicIp *string `locationName:"IpAddress" type:"string" required:"true"` + + // The type of VPN connection that this customer gateway supports (ipsec.1). + Type *string `type:"string" required:"true" enum:"GatewayType"` +} + +// String returns the string representation +func (s CreateCustomerGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateCustomerGatewayInput) GoString() string { + return s.String() +} + +type CreateCustomerGatewayOutput struct { + _ struct{} `type:"structure"` + + // Information about the customer gateway. + CustomerGateway *CustomerGateway `locationName:"customerGateway" type:"structure"` +} + +// String returns the string representation +func (s CreateCustomerGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateCustomerGatewayOutput) GoString() string { + return s.String() +} + +type CreateDhcpOptionsInput struct { + _ struct{} `type:"structure"` + + // A DHCP configuration option. + DhcpConfigurations []*NewDhcpConfiguration `locationName:"dhcpConfiguration" locationNameList:"item" type:"list" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s CreateDhcpOptionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateDhcpOptionsInput) GoString() string { + return s.String() +} + +type CreateDhcpOptionsOutput struct { + _ struct{} `type:"structure"` + + // A set of DHCP options. + DhcpOptions *DhcpOptions `locationName:"dhcpOptions" type:"structure"` +} + +// String returns the string representation +func (s CreateDhcpOptionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateDhcpOptionsOutput) GoString() string { + return s.String() +} + +type CreateFlowLogsInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html). + ClientToken *string `type:"string"` + + // The ARN for the IAM role that's used to post flow logs to a CloudWatch Logs + // log group. + DeliverLogsPermissionArn *string `type:"string" required:"true"` + + // The name of the CloudWatch log group. + LogGroupName *string `type:"string" required:"true"` + + // One or more subnet, network interface, or VPC IDs. + ResourceIds []*string `locationName:"ResourceId" locationNameList:"item" type:"list" required:"true"` + + // The type of resource on which to create the flow log. + ResourceType *string `type:"string" required:"true" enum:"FlowLogsResourceType"` + + // The type of traffic to log. + TrafficType *string `type:"string" required:"true" enum:"TrafficType"` +} + +// String returns the string representation +func (s CreateFlowLogsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateFlowLogsInput) GoString() string { + return s.String() +} + +type CreateFlowLogsOutput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. + ClientToken *string `locationName:"clientToken" type:"string"` + + // The IDs of the flow logs. + FlowLogIds []*string `locationName:"flowLogIdSet" locationNameList:"item" type:"list"` + + // Information about the flow logs that could not be created successfully. + Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CreateFlowLogsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateFlowLogsOutput) GoString() string { + return s.String() +} + +type CreateImageInput struct { + _ struct{} `type:"structure"` + + // Information about one or more block device mappings. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` + + // A description for the new image. + Description *string `locationName:"description" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // A name for the new image. + // + // Constraints: 3-128 alphanumeric characters, parentheses (()), square brackets + // ([]), spaces ( ), periods (.), slashes (/), dashes (-), single quotes ('), + // at-signs (@), or underscores(_) + Name *string `locationName:"name" type:"string" required:"true"` + + // By default, this parameter is set to false, which means Amazon EC2 attempts + // to shut down the instance cleanly before image creation and then reboots + // the instance. When the parameter is set to true, Amazon EC2 doesn't shut + // down the instance before creating the image. When this option is used, file + // system integrity on the created image can't be guaranteed. + NoReboot *bool `locationName:"noReboot" type:"boolean"` +} + +// String returns the string representation +func (s CreateImageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateImageInput) GoString() string { + return s.String() +} + +type CreateImageOutput struct { + _ struct{} `type:"structure"` + + // The ID of the new AMI. + ImageId *string `locationName:"imageId" type:"string"` +} + +// String returns the string representation +func (s CreateImageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateImageOutput) GoString() string { + return s.String() +} + +type CreateInstanceExportTaskInput struct { + _ struct{} `type:"structure"` + + // A description for the conversion task or the resource being exported. The + // maximum length is 255 bytes. + Description *string `locationName:"description" type:"string"` + + // The format and location for an instance export task. + ExportToS3Task *ExportToS3TaskSpecification `locationName:"exportToS3" type:"structure"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // The target virtualization environment. + TargetEnvironment *string `locationName:"targetEnvironment" type:"string" enum:"ExportEnvironment"` +} + +// String returns the string representation +func (s CreateInstanceExportTaskInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateInstanceExportTaskInput) GoString() string { + return s.String() +} + +type CreateInstanceExportTaskOutput struct { + _ struct{} `type:"structure"` + + // Information about the instance export task. + ExportTask *ExportTask `locationName:"exportTask" type:"structure"` +} + +// String returns the string representation +func (s CreateInstanceExportTaskOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateInstanceExportTaskOutput) GoString() string { + return s.String() +} + +type CreateInternetGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s CreateInternetGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateInternetGatewayInput) GoString() string { + return s.String() +} + +type CreateInternetGatewayOutput struct { + _ struct{} `type:"structure"` + + // Information about the Internet gateway. + InternetGateway *InternetGateway `locationName:"internetGateway" type:"structure"` +} + +// String returns the string representation +func (s CreateInternetGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateInternetGatewayOutput) GoString() string { + return s.String() +} + +type CreateKeyPairInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // A unique name for the key pair. + // + // Constraints: Up to 255 ASCII characters + KeyName *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateKeyPairInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateKeyPairInput) GoString() string { + return s.String() +} + +// Describes a key pair. +type CreateKeyPairOutput struct { + _ struct{} `type:"structure"` + + // The SHA-1 digest of the DER encoded private key. + KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` + + // An unencrypted PEM encoded RSA private key. + KeyMaterial *string `locationName:"keyMaterial" type:"string"` + + // The name of the key pair. + KeyName *string `locationName:"keyName" type:"string"` +} + +// String returns the string representation +func (s CreateKeyPairOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateKeyPairOutput) GoString() string { + return s.String() +} + +type CreateNatGatewayInput struct { + _ struct{} `type:"structure"` + + // The allocation ID of an Elastic IP address to associate with the NAT gateway. + // If the Elastic IP address is associated with another resource, you must first + // disassociate it. + AllocationId *string `type:"string" required:"true"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + // + // Constraint: Maximum 64 ASCII characters. + ClientToken *string `type:"string"` + + // The subnet in which to create the NAT gateway. + SubnetId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateNatGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNatGatewayInput) GoString() string { + return s.String() +} + +type CreateNatGatewayOutput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier to ensure the idempotency of the request. + // Only returned if a client token was provided in the request. + ClientToken *string `locationName:"clientToken" type:"string"` + + // Information about the NAT gateway. + NatGateway *NatGateway `locationName:"natGateway" type:"structure"` +} + +// String returns the string representation +func (s CreateNatGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNatGatewayOutput) GoString() string { + return s.String() +} + +type CreateNetworkAclEntryInput struct { + _ struct{} `type:"structure"` + + // The network range to allow or deny, in CIDR notation (for example 172.16.0.0/24). + CidrBlock *string `locationName:"cidrBlock" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Indicates whether this is an egress rule (rule is applied to traffic leaving + // the subnet). + Egress *bool `locationName:"egress" type:"boolean" required:"true"` + + // ICMP protocol: The ICMP type and code. Required if specifying ICMP for the + // protocol. + IcmpTypeCode *IcmpTypeCode `locationName:"Icmp" type:"structure"` + + // The ID of the network ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` + + // TCP or UDP protocols: The range of ports the rule applies to. + PortRange *PortRange `locationName:"portRange" type:"structure"` + + // The protocol. A value of -1 means all protocols. + Protocol *string `locationName:"protocol" type:"string" required:"true"` + + // Indicates whether to allow or deny the traffic that matches the rule. + RuleAction *string `locationName:"ruleAction" type:"string" required:"true" enum:"RuleAction"` + + // The rule number for the entry (for example, 100). ACL entries are processed + // in ascending order by rule number. + // + // Constraints: Positive integer from 1 to 32766 + RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` +} + +// String returns the string representation +func (s CreateNetworkAclEntryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkAclEntryInput) GoString() string { + return s.String() +} + +type CreateNetworkAclEntryOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CreateNetworkAclEntryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkAclEntryOutput) GoString() string { + return s.String() +} + +type CreateNetworkAclInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateNetworkAclInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkAclInput) GoString() string { + return s.String() +} + +type CreateNetworkAclOutput struct { + _ struct{} `type:"structure"` + + // Information about the network ACL. + NetworkAcl *NetworkAcl `locationName:"networkAcl" type:"structure"` +} + +// String returns the string representation +func (s CreateNetworkAclOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkAclOutput) GoString() string { + return s.String() +} + +type CreateNetworkInterfaceInput struct { + _ struct{} `type:"structure"` + + // A description for the network interface. + Description *string `locationName:"description" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The IDs of one or more security groups. + Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` + + // The primary private IP address of the network interface. If you don't specify + // an IP address, Amazon EC2 selects one for you from the subnet range. If you + // specify an IP address, you cannot indicate any IP addresses specified in + // privateIpAddresses as primary (only one IP address can be designated as primary). + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // One or more private IP addresses. + PrivateIpAddresses []*PrivateIpAddressSpecification `locationName:"privateIpAddresses" locationNameList:"item" type:"list"` + + // The number of secondary private IP addresses to assign to a network interface. + // When you specify a number of secondary IP addresses, Amazon EC2 selects these + // IP addresses within the subnet range. You can't specify this option and specify + // more than one private IP address using privateIpAddresses. + // + // The number of IP addresses you can assign to a network interface varies + // by instance type. For more information, see Private IP Addresses Per ENI + // Per Instance Type (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI) + // in the Amazon Elastic Compute Cloud User Guide. + SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` + + // The ID of the subnet to associate with the network interface. + SubnetId *string `locationName:"subnetId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateNetworkInterfaceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkInterfaceInput) GoString() string { + return s.String() +} + +type CreateNetworkInterfaceOutput struct { + _ struct{} `type:"structure"` + + // Information about the network interface. + NetworkInterface *NetworkInterface `locationName:"networkInterface" type:"structure"` +} + +// String returns the string representation +func (s CreateNetworkInterfaceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateNetworkInterfaceOutput) GoString() string { + return s.String() +} + +type CreatePlacementGroupInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // A name for the placement group. + // + // Constraints: Up to 255 ASCII characters + GroupName *string `locationName:"groupName" type:"string" required:"true"` + + // The placement strategy. + Strategy *string `locationName:"strategy" type:"string" required:"true" enum:"PlacementStrategy"` +} + +// String returns the string representation +func (s CreatePlacementGroupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreatePlacementGroupInput) GoString() string { + return s.String() +} + +type CreatePlacementGroupOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CreatePlacementGroupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreatePlacementGroupOutput) GoString() string { + return s.String() +} + +type CreateReservedInstancesListingInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure idempotency of your + // listings. This helps avoid duplicate listings. For more information, see + // Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `locationName:"clientToken" type:"string" required:"true"` + + // The number of instances that are a part of a Reserved Instance account to + // be listed in the Reserved Instance Marketplace. This number should be less + // than or equal to the instance count associated with the Reserved Instance + // ID specified in this call. + InstanceCount *int64 `locationName:"instanceCount" type:"integer" required:"true"` + + // A list specifying the price of the Reserved Instance for each month remaining + // in the Reserved Instance term. + PriceSchedules []*PriceScheduleSpecification `locationName:"priceSchedules" locationNameList:"item" type:"list" required:"true"` + + // The ID of the active Reserved Instance. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateReservedInstancesListingInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateReservedInstancesListingInput) GoString() string { + return s.String() +} + +type CreateReservedInstancesListingOutput struct { + _ struct{} `type:"structure"` + + // Information about the Reserved Instance listing. + ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CreateReservedInstancesListingOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateReservedInstancesListingOutput) GoString() string { + return s.String() +} + +type CreateRouteInput struct { + _ struct{} `type:"structure"` + + // The CIDR address block used for the destination match. Routing decisions + // are based on the most specific match. + DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of an Internet gateway or virtual private gateway attached to your + // VPC. + GatewayId *string `locationName:"gatewayId" type:"string"` + + // The ID of a NAT instance in your VPC. The operation fails if you specify + // an instance ID unless exactly one network interface is attached. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The ID of a NAT gateway. + NatGatewayId *string `locationName:"natGatewayId" type:"string"` + + // The ID of a network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The ID of the route table for the route. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` + + // The ID of a VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` +} + +// String returns the string representation +func (s CreateRouteInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateRouteInput) GoString() string { + return s.String() +} + +type CreateRouteOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s CreateRouteOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateRouteOutput) GoString() string { + return s.String() +} + +type CreateRouteTableInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateRouteTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateRouteTableInput) GoString() string { + return s.String() +} + +type CreateRouteTableOutput struct { + _ struct{} `type:"structure"` + + // Information about the route table. + RouteTable *RouteTable `locationName:"routeTable" type:"structure"` +} + +// String returns the string representation +func (s CreateRouteTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateRouteTableOutput) GoString() string { + return s.String() +} + +type CreateSecurityGroupInput struct { + _ struct{} `type:"structure"` + + // A description for the security group. This is informational only. + // + // Constraints: Up to 255 characters in length + // + // Constraints for EC2-Classic: ASCII characters + // + // Constraints for EC2-VPC: a-z, A-Z, 0-9, spaces, and ._-:/()#,@[]+=;{}!$* + Description *string `locationName:"GroupDescription" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The name of the security group. + // + // Constraints: Up to 255 characters in length + // + // Constraints for EC2-Classic: ASCII characters + // + // Constraints for EC2-VPC: a-z, A-Z, 0-9, spaces, and ._-:/()#,@[]+=;{}!$* + GroupName *string `type:"string" required:"true"` + + // [EC2-VPC] The ID of the VPC. Required for EC2-VPC. + VpcId *string `type:"string"` +} + +// String returns the string representation +func (s CreateSecurityGroupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSecurityGroupInput) GoString() string { + return s.String() +} + +type CreateSecurityGroupOutput struct { + _ struct{} `type:"structure"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string"` +} + +// String returns the string representation +func (s CreateSecurityGroupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSecurityGroupOutput) GoString() string { + return s.String() +} + +type CreateSnapshotInput struct { + _ struct{} `type:"structure"` + + // A description for the snapshot. + Description *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the EBS volume. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateSnapshotInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSnapshotInput) GoString() string { + return s.String() +} + +// Contains the parameters for CreateSpotDatafeedSubscription. +type CreateSpotDatafeedSubscriptionInput struct { + _ struct{} `type:"structure"` + + // The Amazon S3 bucket in which to store the Spot instance data feed. + Bucket *string `locationName:"bucket" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // A prefix for the data feed file names. + Prefix *string `locationName:"prefix" type:"string"` +} + +// String returns the string representation +func (s CreateSpotDatafeedSubscriptionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSpotDatafeedSubscriptionInput) GoString() string { + return s.String() +} + +// Contains the output of CreateSpotDatafeedSubscription. +type CreateSpotDatafeedSubscriptionOutput struct { + _ struct{} `type:"structure"` + + // The Spot instance data feed subscription. + SpotDatafeedSubscription *SpotDatafeedSubscription `locationName:"spotDatafeedSubscription" type:"structure"` +} + +// String returns the string representation +func (s CreateSpotDatafeedSubscriptionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSpotDatafeedSubscriptionOutput) GoString() string { + return s.String() +} + +type CreateSubnetInput struct { + _ struct{} `type:"structure"` + + // The Availability Zone for the subnet. + // + // Default: AWS selects one for you. If you create more than one subnet in + // your VPC, we may not necessarily select a different zone for each subnet. + AvailabilityZone *string `type:"string"` + + // The network range for the subnet, in CIDR notation. For example, 10.0.0.0/24. + CidrBlock *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateSubnetInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSubnetInput) GoString() string { + return s.String() +} + +type CreateSubnetOutput struct { + _ struct{} `type:"structure"` + + // Information about the subnet. + Subnet *Subnet `locationName:"subnet" type:"structure"` +} + +// String returns the string representation +func (s CreateSubnetOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateSubnetOutput) GoString() string { + return s.String() +} + +type CreateTagsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The IDs of one or more resources to tag. For example, ami-1a2b3c4d. + Resources []*string `locationName:"ResourceId" type:"list" required:"true"` + + // One or more tags. The value parameter is required, but if you don't want + // the tag to have a value, specify the parameter with no value, and we set + // the value to an empty string. + Tags []*Tag `locationName:"Tag" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s CreateTagsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateTagsInput) GoString() string { + return s.String() +} + +type CreateTagsOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CreateTagsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateTagsOutput) GoString() string { + return s.String() +} + +type CreateVolumeInput struct { + _ struct{} `type:"structure"` + + // The Availability Zone in which to create the volume. Use DescribeAvailabilityZones + // to list the Availability Zones that are currently available to you. + AvailabilityZone *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Specifies whether the volume should be encrypted. Encrypted Amazon EBS volumes + // may only be attached to instances that support Amazon EBS encryption. Volumes + // that are created from encrypted snapshots are automatically encrypted. There + // is no way to create an encrypted volume from an unencrypted snapshot or vice + // versa. If your AMI uses encrypted volumes, you can only launch it on supported + // instance types. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) + // in the Amazon Elastic Compute Cloud User Guide. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // Only valid for Provisioned IOPS (SSD) volumes. The number of I/O operations + // per second (IOPS) to provision for the volume, with a maximum ratio of 30 + // IOPS/GiB. + // + // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes + Iops *int64 `type:"integer"` + + // The full ARN of the AWS Key Management Service (AWS KMS) customer master + // key (CMK) to use when creating the encrypted volume. This parameter is only + // required if you want to use a non-default CMK; if this parameter is not specified, + // the default CMK for EBS is used. The ARN contains the arn:aws:kms namespace, + // followed by the region of the CMK, the AWS account ID of the CMK owner, the + // key namespace, and then the CMK ID. For example, arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef. + // If a KmsKeyId is specified, the Encrypted flag must also be set. + KmsKeyId *string `type:"string"` + + // The size of the volume, in GiBs. + // + // Constraints: 1-1024 for standard volumes, 1-16384 for gp2 volumes, and 4-16384 + // for io1 volumes. If you specify a snapshot, the volume size must be equal + // to or larger than the snapshot size. + // + // Default: If you're creating the volume from a snapshot and don't specify + // a volume size, the default is the snapshot size. + Size *int64 `type:"integer"` + + // The snapshot from which to create the volume. + SnapshotId *string `type:"string"` + + // The volume type. This can be gp2 for General Purpose (SSD) volumes, io1 for + // Provisioned IOPS (SSD) volumes, or standard for Magnetic volumes. + // + // Default: standard + VolumeType *string `type:"string" enum:"VolumeType"` +} + +// String returns the string representation +func (s CreateVolumeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVolumeInput) GoString() string { + return s.String() +} + +// Describes the user or group to be added or removed from the permissions for +// a volume. +type CreateVolumePermission struct { + _ struct{} `type:"structure"` + + // The specific group that is to be added or removed from a volume's list of + // create volume permissions. + Group *string `locationName:"group" type:"string" enum:"PermissionGroup"` + + // The specific AWS account ID that is to be added or removed from a volume's + // list of create volume permissions. + UserId *string `locationName:"userId" type:"string"` +} + +// String returns the string representation +func (s CreateVolumePermission) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVolumePermission) GoString() string { + return s.String() +} + +// Describes modifications to the permissions for a volume. +type CreateVolumePermissionModifications struct { + _ struct{} `type:"structure"` + + // Adds a specific AWS account ID or group to a volume's list of create volume + // permissions. + Add []*CreateVolumePermission `locationNameList:"item" type:"list"` + + // Removes a specific AWS account ID or group from a volume's list of create + // volume permissions. + Remove []*CreateVolumePermission `locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s CreateVolumePermissionModifications) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVolumePermissionModifications) GoString() string { + return s.String() +} + +type CreateVpcEndpointInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // A policy to attach to the endpoint that controls access to the service. The + // policy must be in valid JSON format. If this parameter is not specified, + // we attach a default policy that allows full access to the service. + PolicyDocument *string `type:"string"` + + // One or more route table IDs. + RouteTableIds []*string `locationName:"RouteTableId" locationNameList:"item" type:"list"` + + // The AWS service name, in the form com.amazonaws.region.service. To get a + // list of available services, use the DescribeVpcEndpointServices request. + ServiceName *string `type:"string" required:"true"` + + // The ID of the VPC in which the endpoint will be used. + VpcId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateVpcEndpointInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcEndpointInput) GoString() string { + return s.String() +} + +type CreateVpcEndpointOutput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. + ClientToken *string `locationName:"clientToken" type:"string"` + + // Information about the endpoint. + VpcEndpoint *VpcEndpoint `locationName:"vpcEndpoint" type:"structure"` +} + +// String returns the string representation +func (s CreateVpcEndpointOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcEndpointOutput) GoString() string { + return s.String() +} + +type CreateVpcInput struct { + _ struct{} `type:"structure"` + + // The network range for the VPC, in CIDR notation. For example, 10.0.0.0/16. + CidrBlock *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The supported tenancy options for instances launched into the VPC. A value + // of default means that instances can be launched with any tenancy; a value + // of dedicated means all instances launched into the VPC are launched as dedicated + // tenancy instances regardless of the tenancy assigned to the instance at launch. + // Dedicated tenancy instances run on single-tenant hardware. + // + // Important: The host value cannot be used with this parameter. Use the default + // or dedicated values only. + // + // Default: default + InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` +} + +// String returns the string representation +func (s CreateVpcInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcInput) GoString() string { + return s.String() +} + +type CreateVpcOutput struct { + _ struct{} `type:"structure"` + + // Information about the VPC. + Vpc *Vpc `locationName:"vpc" type:"structure"` +} + +// String returns the string representation +func (s CreateVpcOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcOutput) GoString() string { + return s.String() +} + +type CreateVpcPeeringConnectionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The AWS account ID of the owner of the peer VPC. + // + // Default: Your AWS account ID + PeerOwnerId *string `locationName:"peerOwnerId" type:"string"` + + // The ID of the VPC with which you are creating the VPC peering connection. + PeerVpcId *string `locationName:"peerVpcId" type:"string"` + + // The ID of the requester VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s CreateVpcPeeringConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcPeeringConnectionInput) GoString() string { + return s.String() +} + +type CreateVpcPeeringConnectionOutput struct { + _ struct{} `type:"structure"` + + // Information about the VPC peering connection. + VpcPeeringConnection *VpcPeeringConnection `locationName:"vpcPeeringConnection" type:"structure"` +} + +// String returns the string representation +func (s CreateVpcPeeringConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpcPeeringConnectionOutput) GoString() string { + return s.String() +} + +type CreateVpnConnectionInput struct { + _ struct{} `type:"structure"` + + // The ID of the customer gateway. + CustomerGatewayId *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Indicates whether the VPN connection requires static routes. If you are creating + // a VPN connection for a device that does not support BGP, you must specify + // true. + // + // Default: false + Options *VpnConnectionOptionsSpecification `locationName:"options" type:"structure"` + + // The type of VPN connection (ipsec.1). + Type *string `type:"string" required:"true"` + + // The ID of the virtual private gateway. + VpnGatewayId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateVpnConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnConnectionInput) GoString() string { + return s.String() +} + +type CreateVpnConnectionOutput struct { + _ struct{} `type:"structure"` + + // Information about the VPN connection. + VpnConnection *VpnConnection `locationName:"vpnConnection" type:"structure"` +} + +// String returns the string representation +func (s CreateVpnConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnConnectionOutput) GoString() string { + return s.String() +} + +type CreateVpnConnectionRouteInput struct { + _ struct{} `type:"structure"` + + // The CIDR block associated with the local subnet of the customer network. + DestinationCidrBlock *string `type:"string" required:"true"` + + // The ID of the VPN connection. + VpnConnectionId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateVpnConnectionRouteInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnConnectionRouteInput) GoString() string { + return s.String() +} + +type CreateVpnConnectionRouteOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s CreateVpnConnectionRouteOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnConnectionRouteOutput) GoString() string { + return s.String() +} + +type CreateVpnGatewayInput struct { + _ struct{} `type:"structure"` + + // The Availability Zone for the virtual private gateway. + AvailabilityZone *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The type of VPN connection this virtual private gateway supports. + Type *string `type:"string" required:"true" enum:"GatewayType"` +} + +// String returns the string representation +func (s CreateVpnGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnGatewayInput) GoString() string { + return s.String() +} + +type CreateVpnGatewayOutput struct { + _ struct{} `type:"structure"` + + // Information about the virtual private gateway. + VpnGateway *VpnGateway `locationName:"vpnGateway" type:"structure"` +} + +// String returns the string representation +func (s CreateVpnGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateVpnGatewayOutput) GoString() string { + return s.String() +} + +// Describes a customer gateway. +type CustomerGateway struct { + _ struct{} `type:"structure"` + + // The customer gateway's Border Gateway Protocol (BGP) Autonomous System Number + // (ASN). + BgpAsn *string `locationName:"bgpAsn" type:"string"` + + // The ID of the customer gateway. + CustomerGatewayId *string `locationName:"customerGatewayId" type:"string"` + + // The Internet-routable IP address of the customer gateway's outside interface. + IpAddress *string `locationName:"ipAddress" type:"string"` + + // The current state of the customer gateway (pending | available | deleting + // | deleted). + State *string `locationName:"state" type:"string"` + + // Any tags assigned to the customer gateway. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The type of VPN connection the customer gateway supports (ipsec.1). + Type *string `locationName:"type" type:"string"` +} + +// String returns the string representation +func (s CustomerGateway) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CustomerGateway) GoString() string { + return s.String() +} + +type DeleteCustomerGatewayInput struct { + _ struct{} `type:"structure"` + + // The ID of the customer gateway. + CustomerGatewayId *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DeleteCustomerGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteCustomerGatewayInput) GoString() string { + return s.String() +} + +type DeleteCustomerGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteCustomerGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteCustomerGatewayOutput) GoString() string { + return s.String() +} + +type DeleteDhcpOptionsInput struct { + _ struct{} `type:"structure"` + + // The ID of the DHCP options set. + DhcpOptionsId *string `type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DeleteDhcpOptionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteDhcpOptionsInput) GoString() string { + return s.String() +} + +type DeleteDhcpOptionsOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteDhcpOptionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteDhcpOptionsOutput) GoString() string { + return s.String() +} + +type DeleteFlowLogsInput struct { + _ struct{} `type:"structure"` + + // One or more flow log IDs. + FlowLogIds []*string `locationName:"FlowLogId" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s DeleteFlowLogsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteFlowLogsInput) GoString() string { + return s.String() +} + +type DeleteFlowLogsOutput struct { + _ struct{} `type:"structure"` + + // Information about the flow logs that could not be deleted successfully. + Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DeleteFlowLogsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteFlowLogsOutput) GoString() string { + return s.String() +} + +type DeleteInternetGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the Internet gateway. + InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteInternetGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteInternetGatewayInput) GoString() string { + return s.String() +} + +type DeleteInternetGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteInternetGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteInternetGatewayOutput) GoString() string { + return s.String() +} + +type DeleteKeyPairInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The name of the key pair. + KeyName *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteKeyPairInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteKeyPairInput) GoString() string { + return s.String() +} + +type DeleteKeyPairOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteKeyPairOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteKeyPairOutput) GoString() string { + return s.String() +} + +type DeleteNatGatewayInput struct { + _ struct{} `type:"structure"` + + // The ID of the NAT gateway. + NatGatewayId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteNatGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNatGatewayInput) GoString() string { + return s.String() +} + +type DeleteNatGatewayOutput struct { + _ struct{} `type:"structure"` + + // The ID of the NAT gateway. + NatGatewayId *string `locationName:"natGatewayId" type:"string"` +} + +// String returns the string representation +func (s DeleteNatGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNatGatewayOutput) GoString() string { + return s.String() +} + +type DeleteNetworkAclEntryInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Indicates whether the rule is an egress rule. + Egress *bool `locationName:"egress" type:"boolean" required:"true"` + + // The ID of the network ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` + + // The rule number of the entry to delete. + RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` +} + +// String returns the string representation +func (s DeleteNetworkAclEntryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkAclEntryInput) GoString() string { + return s.String() +} + +type DeleteNetworkAclEntryOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteNetworkAclEntryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkAclEntryOutput) GoString() string { + return s.String() +} + +type DeleteNetworkAclInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the network ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteNetworkAclInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkAclInput) GoString() string { + return s.String() +} + +type DeleteNetworkAclOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteNetworkAclOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkAclOutput) GoString() string { + return s.String() +} + +type DeleteNetworkInterfaceInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteNetworkInterfaceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkInterfaceInput) GoString() string { + return s.String() +} + +type DeleteNetworkInterfaceOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteNetworkInterfaceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteNetworkInterfaceOutput) GoString() string { + return s.String() +} + +type DeletePlacementGroupInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The name of the placement group. + GroupName *string `locationName:"groupName" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeletePlacementGroupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeletePlacementGroupInput) GoString() string { + return s.String() +} + +type DeletePlacementGroupOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeletePlacementGroupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeletePlacementGroupOutput) GoString() string { + return s.String() +} + +type DeleteRouteInput struct { + _ struct{} `type:"structure"` + + // The CIDR range for the route. The value you specify must match the CIDR for + // the route exactly. + DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteRouteInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteRouteInput) GoString() string { + return s.String() +} + +type DeleteRouteOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteRouteOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteRouteOutput) GoString() string { + return s.String() +} + +type DeleteRouteTableInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteRouteTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteRouteTableInput) GoString() string { + return s.String() +} + +type DeleteRouteTableOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteRouteTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteRouteTableOutput) GoString() string { + return s.String() +} + +type DeleteSecurityGroupInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the security group. Required for a nondefault VPC. + GroupId *string `type:"string"` + + // [EC2-Classic, default VPC] The name of the security group. You can specify + // either the security group name or the security group ID. + GroupName *string `type:"string"` +} + +// String returns the string representation +func (s DeleteSecurityGroupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSecurityGroupInput) GoString() string { + return s.String() +} + +type DeleteSecurityGroupOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteSecurityGroupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSecurityGroupOutput) GoString() string { + return s.String() +} + +type DeleteSnapshotInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the EBS snapshot. + SnapshotId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteSnapshotInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSnapshotInput) GoString() string { + return s.String() +} + +type DeleteSnapshotOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteSnapshotOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSnapshotOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DeleteSpotDatafeedSubscription. +type DeleteSpotDatafeedSubscriptionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DeleteSpotDatafeedSubscriptionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSpotDatafeedSubscriptionInput) GoString() string { + return s.String() +} + +type DeleteSpotDatafeedSubscriptionOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteSpotDatafeedSubscriptionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSpotDatafeedSubscriptionOutput) GoString() string { + return s.String() +} + +type DeleteSubnetInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the subnet. + SubnetId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteSubnetInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSubnetInput) GoString() string { + return s.String() +} + +type DeleteSubnetOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteSubnetOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteSubnetOutput) GoString() string { + return s.String() +} + +type DeleteTagsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the resource. For example, ami-1a2b3c4d. You can specify more than + // one resource ID. + Resources []*string `locationName:"resourceId" type:"list" required:"true"` + + // One or more tags to delete. If you omit the value parameter, we delete the + // tag regardless of its value. If you specify this parameter with an empty + // string as the value, we delete the key only if its value is an empty string. + Tags []*Tag `locationName:"tag" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DeleteTagsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteTagsInput) GoString() string { + return s.String() +} + +type DeleteTagsOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteTagsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteTagsOutput) GoString() string { + return s.String() +} + +type DeleteVolumeInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the volume. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVolumeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVolumeInput) GoString() string { + return s.String() +} + +type DeleteVolumeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteVolumeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVolumeOutput) GoString() string { + return s.String() +} + +type DeleteVpcEndpointsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more endpoint IDs. + VpcEndpointIds []*string `locationName:"VpcEndpointId" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s DeleteVpcEndpointsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcEndpointsInput) GoString() string { + return s.String() +} + +type DeleteVpcEndpointsOutput struct { + _ struct{} `type:"structure"` + + // Information about the endpoints that were not successfully deleted. + Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DeleteVpcEndpointsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcEndpointsOutput) GoString() string { + return s.String() +} + +type DeleteVpcInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVpcInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcInput) GoString() string { + return s.String() +} + +type DeleteVpcOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteVpcOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcOutput) GoString() string { + return s.String() +} + +type DeleteVpcPeeringConnectionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVpcPeeringConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcPeeringConnectionInput) GoString() string { + return s.String() +} + +type DeleteVpcPeeringConnectionOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s DeleteVpcPeeringConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpcPeeringConnectionOutput) GoString() string { + return s.String() +} + +type DeleteVpnConnectionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPN connection. + VpnConnectionId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVpnConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnConnectionInput) GoString() string { + return s.String() +} + +type DeleteVpnConnectionOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteVpnConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnConnectionOutput) GoString() string { + return s.String() +} + +type DeleteVpnConnectionRouteInput struct { + _ struct{} `type:"structure"` + + // The CIDR block associated with the local subnet of the customer network. + DestinationCidrBlock *string `type:"string" required:"true"` + + // The ID of the VPN connection. + VpnConnectionId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVpnConnectionRouteInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnConnectionRouteInput) GoString() string { + return s.String() +} + +type DeleteVpnConnectionRouteOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteVpnConnectionRouteOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnConnectionRouteOutput) GoString() string { + return s.String() +} + +type DeleteVpnGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the virtual private gateway. + VpnGatewayId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteVpnGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnGatewayInput) GoString() string { + return s.String() +} + +type DeleteVpnGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeleteVpnGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteVpnGatewayOutput) GoString() string { + return s.String() +} + +type DeregisterImageInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the AMI. + ImageId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeregisterImageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeregisterImageInput) GoString() string { + return s.String() +} + +type DeregisterImageOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DeregisterImageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeregisterImageOutput) GoString() string { + return s.String() +} + +type DescribeAccountAttributesInput struct { + _ struct{} `type:"structure"` + + // One or more account attribute names. + AttributeNames []*string `locationName:"attributeName" locationNameList:"attributeName" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DescribeAccountAttributesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAccountAttributesInput) GoString() string { + return s.String() +} + +type DescribeAccountAttributesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more account attributes. + AccountAttributes []*AccountAttribute `locationName:"accountAttributeSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeAccountAttributesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAccountAttributesOutput) GoString() string { + return s.String() +} + +type DescribeAddressesInput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] One or more allocation IDs. + // + // Default: Describes all your Elastic IP addresses. + AllocationIds []*string `locationName:"AllocationId" locationNameList:"AllocationId" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. Filter names and values are case-sensitive. + // + // allocation-id - [EC2-VPC] The allocation ID for the address. + // + // association-id - [EC2-VPC] The association ID for the address. + // + // domain - Indicates whether the address is for use in EC2-Classic (standard) + // or in a VPC (vpc). + // + // instance-id - The ID of the instance the address is associated with, if + // any. + // + // network-interface-id - [EC2-VPC] The ID of the network interface that + // the address is associated with, if any. + // + // network-interface-owner-id - The AWS account ID of the owner. + // + // private-ip-address - [EC2-VPC] The private IP address associated with + // the Elastic IP address. + // + // public-ip - The Elastic IP address. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // [EC2-Classic] One or more Elastic IP addresses. + // + // Default: Describes all your Elastic IP addresses. + PublicIps []*string `locationName:"PublicIp" locationNameList:"PublicIp" type:"list"` +} + +// String returns the string representation +func (s DescribeAddressesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAddressesInput) GoString() string { + return s.String() +} + +type DescribeAddressesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more Elastic IP addresses. + Addresses []*Address `locationName:"addressesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeAddressesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAddressesOutput) GoString() string { + return s.String() +} + +type DescribeAvailabilityZonesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // message - Information about the Availability Zone. + // + // region-name - The name of the region for the Availability Zone (for example, + // us-east-1). + // + // state - The state of the Availability Zone (available | information | + // impaired | unavailable). + // + // zone-name - The name of the Availability Zone (for example, us-east-1a). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The names of one or more Availability Zones. + ZoneNames []*string `locationName:"ZoneName" locationNameList:"ZoneName" type:"list"` +} + +// String returns the string representation +func (s DescribeAvailabilityZonesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAvailabilityZonesInput) GoString() string { + return s.String() +} + +type DescribeAvailabilityZonesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more Availability Zones. + AvailabilityZones []*AvailabilityZone `locationName:"availabilityZoneInfo" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeAvailabilityZonesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeAvailabilityZonesOutput) GoString() string { + return s.String() +} + +type DescribeBundleTasksInput struct { + _ struct{} `type:"structure"` + + // One or more bundle task IDs. + // + // Default: Describes all your bundle tasks. + BundleIds []*string `locationName:"BundleId" locationNameList:"BundleId" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // bundle-id - The ID of the bundle task. + // + // error-code - If the task failed, the error code returned. + // + // error-message - If the task failed, the error message returned. + // + // instance-id - The ID of the instance. + // + // progress - The level of task completion, as a percentage (for example, + // 20%). + // + // s3-bucket - The Amazon S3 bucket to store the AMI. + // + // s3-prefix - The beginning of the AMI name. + // + // start-time - The time the task started (for example, 2013-09-15T17:15:20.000Z). + // + // state - The state of the task (pending | waiting-for-shutdown | bundling + // | storing | cancelling | complete | failed). + // + // update-time - The time of the most recent update for the task. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` +} + +// String returns the string representation +func (s DescribeBundleTasksInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeBundleTasksInput) GoString() string { + return s.String() +} + +type DescribeBundleTasksOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more bundle tasks. + BundleTasks []*BundleTask `locationName:"bundleInstanceTasksSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeBundleTasksOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeBundleTasksOutput) GoString() string { + return s.String() +} + +type DescribeClassicLinkInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // group-id - The ID of a VPC security group that's associated with the instance. + // + // instance-id - The ID of the instance. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC that the instance is linked to. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more instance IDs. Must be instances linked to a VPC through ClassicLink. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. You cannot specify this parameter and the instance IDs parameter + // in the same request. + // + // Constraint: If the value is greater than 1000, we return only 1000 items. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeClassicLinkInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeClassicLinkInstancesInput) GoString() string { + return s.String() +} + +type DescribeClassicLinkInstancesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more linked EC2-Classic instances. + Instances []*ClassicLinkInstance `locationName:"instancesSet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeClassicLinkInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeClassicLinkInstancesOutput) GoString() string { + return s.String() +} + +type DescribeConversionTasksInput struct { + _ struct{} `type:"structure"` + + // One or more conversion task IDs. + ConversionTaskIds []*string `locationName:"conversionTaskId" locationNameList:"item" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` +} + +// String returns the string representation +func (s DescribeConversionTasksInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeConversionTasksInput) GoString() string { + return s.String() +} + +type DescribeConversionTasksOutput struct { + _ struct{} `type:"structure"` + + // Information about the conversion tasks. + ConversionTasks []*ConversionTask `locationName:"conversionTasks" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeConversionTasksOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeConversionTasksOutput) GoString() string { + return s.String() +} + +type DescribeCustomerGatewaysInput struct { + _ struct{} `type:"structure"` + + // One or more customer gateway IDs. + // + // Default: Describes all your customer gateways. + CustomerGatewayIds []*string `locationName:"CustomerGatewayId" locationNameList:"CustomerGatewayId" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // bgp-asn - The customer gateway's Border Gateway Protocol (BGP) Autonomous + // System Number (ASN). + // + // customer-gateway-id - The ID of the customer gateway. + // + // ip-address - The IP address of the customer gateway's Internet-routable + // external interface. + // + // state - The state of the customer gateway (pending | available | deleting + // | deleted). + // + // type - The type of customer gateway. Currently, the only supported type + // is ipsec.1. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` +} + +// String returns the string representation +func (s DescribeCustomerGatewaysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeCustomerGatewaysInput) GoString() string { + return s.String() +} + +type DescribeCustomerGatewaysOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more customer gateways. + CustomerGateways []*CustomerGateway `locationName:"customerGatewaySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeCustomerGatewaysOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeCustomerGatewaysOutput) GoString() string { + return s.String() +} + +type DescribeDhcpOptionsInput struct { + _ struct{} `type:"structure"` + + // The IDs of one or more DHCP options sets. + // + // Default: Describes all your DHCP options sets. + DhcpOptionsIds []*string `locationName:"DhcpOptionsId" locationNameList:"DhcpOptionsId" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // dhcp-options-id - The ID of a set of DHCP options. + // + // key - The key for one of the options (for example, domain-name). + // + // value - The value for one of the options. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` +} + +// String returns the string representation +func (s DescribeDhcpOptionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeDhcpOptionsInput) GoString() string { + return s.String() +} + +type DescribeDhcpOptionsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more DHCP options sets. + DhcpOptions []*DhcpOptions `locationName:"dhcpOptionsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeDhcpOptionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeDhcpOptionsOutput) GoString() string { + return s.String() +} + +type DescribeExportTasksInput struct { + _ struct{} `type:"structure"` + + // One or more export task IDs. + ExportTaskIds []*string `locationName:"exportTaskId" locationNameList:"ExportTaskId" type:"list"` +} + +// String returns the string representation +func (s DescribeExportTasksInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeExportTasksInput) GoString() string { + return s.String() +} + +type DescribeExportTasksOutput struct { + _ struct{} `type:"structure"` + + // Information about the export tasks. + ExportTasks []*ExportTask `locationName:"exportTaskSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeExportTasksOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeExportTasksOutput) GoString() string { + return s.String() +} + +type DescribeFlowLogsInput struct { + _ struct{} `type:"structure"` + + // One or more filters. + // + // deliver-log-status - The status of the logs delivery (SUCCESS | FAILED). + // + // flow-log-id - The ID of the flow log. + // + // log-group-name - The name of the log group. + // + // resource-id - The ID of the VPC, subnet, or network interface. + // + // traffic-type - The type of traffic (ACCEPT | REJECT | ALL) + Filter []*Filter `locationNameList:"Filter" type:"list"` + + // One or more flow log IDs. + FlowLogIds []*string `locationName:"FlowLogId" locationNameList:"item" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results can be seen by sending another request with the returned + // NextToken value. This value can be between 5 and 1000; if MaxResults is given + // a value larger than 1000, only 1000 results are returned. You cannot specify + // this parameter and the flow log IDs parameter in the same request. + MaxResults *int64 `type:"integer"` + + // The token to retrieve the next page of results. + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeFlowLogsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeFlowLogsInput) GoString() string { + return s.String() +} + +type DescribeFlowLogsOutput struct { + _ struct{} `type:"structure"` + + // Information about the flow logs. + FlowLogs []*FlowLog `locationName:"flowLogSet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeFlowLogsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeFlowLogsOutput) GoString() string { + return s.String() +} + +type DescribeHostsInput struct { + _ struct{} `type:"structure"` + + // One or more filters. + // + // instance-type - The instance type size that the Dedicated host is configured + // to support. + // + // auto-placement - Whether auto-placement is enabled or disabled (on | off). + // + // host-reservation-id - The ID of the reservation associated with this host. + // + // client-token - The idempotency token you provided when you launched the + // instance + // + // state- The allocation state of the Dedicated host (available | under-assessment + // | permanent-failure | released | released-permanent-failure). + // + // availability-zone - The Availability Zone of the host. + Filter []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` + + // The IDs of the Dedicated hosts. The IDs are used for targeted instance launches. + HostIds []*string `locationName:"hostId" locationNameList:"item" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results can be seen by sending another request with the returned + // nextToken value. This value can be between 5 and 500; if maxResults is given + // a larger value than 500, you will receive an error. You cannot specify this + // parameter and the host IDs parameter in the same request. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeHostsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeHostsInput) GoString() string { + return s.String() +} + +type DescribeHostsOutput struct { + _ struct{} `type:"structure"` + + // Information about the Dedicated hosts. + Hosts []*Host `locationName:"hostSet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeHostsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeHostsOutput) GoString() string { + return s.String() +} + +type DescribeIdFormatInput struct { + _ struct{} `type:"structure"` + + // The type of resource. + Resource *string `type:"string"` +} + +// String returns the string representation +func (s DescribeIdFormatInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeIdFormatInput) GoString() string { + return s.String() +} + +type DescribeIdFormatOutput struct { + _ struct{} `type:"structure"` + + // Information about the ID format for the resource. + Statuses []*IdFormat `locationName:"statusSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeIdFormatOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeIdFormatOutput) GoString() string { + return s.String() +} + +type DescribeImageAttributeInput struct { + _ struct{} `type:"structure"` + + // The AMI attribute. + // + // Note: Depending on your account privileges, the blockDeviceMapping attribute + // may return a Client.AuthFailure error. If this happens, use DescribeImages + // to get information about the block device mapping for the AMI. + Attribute *string `type:"string" required:"true" enum:"ImageAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the AMI. + ImageId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeImageAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImageAttributeInput) GoString() string { + return s.String() +} + +// Describes an image attribute. +type DescribeImageAttributeOutput struct { + _ struct{} `type:"structure"` + + // One or more block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // A description for the AMI. + Description *AttributeValue `locationName:"description" type:"structure"` + + // The ID of the AMI. + ImageId *string `locationName:"imageId" type:"string"` + + // The kernel ID. + KernelId *AttributeValue `locationName:"kernel" type:"structure"` + + // One or more launch permissions. + LaunchPermissions []*LaunchPermission `locationName:"launchPermission" locationNameList:"item" type:"list"` + + // One or more product codes. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // The RAM disk ID. + RamdiskId *AttributeValue `locationName:"ramdisk" type:"structure"` + + // The value to use for a resource attribute. + SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` +} + +// String returns the string representation +func (s DescribeImageAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImageAttributeOutput) GoString() string { + return s.String() +} + +type DescribeImagesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Scopes the images by users with explicit launch permissions. Specify an AWS + // account ID, self (the sender of the request), or all (public AMIs). + ExecutableUsers []*string `locationName:"ExecutableBy" locationNameList:"ExecutableBy" type:"list"` + + // One or more filters. + // + // architecture - The image architecture (i386 | x86_64). + // + // block-device-mapping.delete-on-termination - A Boolean value that indicates + // whether the Amazon EBS volume is deleted on instance termination. + // + // block-device-mapping.device-name - The device name for the EBS volume + // (for example, /dev/sdh). + // + // block-device-mapping.snapshot-id - The ID of the snapshot used for the + // EBS volume. + // + // block-device-mapping.volume-size - The volume size of the EBS volume, + // in GiB. + // + // block-device-mapping.volume-type - The volume type of the EBS volume (gp2 + // | standard | io1). + // + // description - The description of the image (provided during image creation). + // + // hypervisor - The hypervisor type (ovm | xen). + // + // image-id - The ID of the image. + // + // image-type - The image type (machine | kernel | ramdisk). + // + // is-public - A Boolean that indicates whether the image is public. + // + // kernel-id - The kernel ID. + // + // manifest-location - The location of the image manifest. + // + // name - The name of the AMI (provided during image creation). + // + // owner-alias - The AWS account alias (for example, amazon). + // + // owner-id - The AWS account ID of the image owner. + // + // platform - The platform. To only list Windows-based AMIs, use windows. + // + // product-code - The product code. + // + // product-code.type - The type of the product code (devpay | marketplace). + // + // ramdisk-id - The RAM disk ID. + // + // root-device-name - The name of the root device volume (for example, /dev/sda1). + // + // root-device-type - The type of the root device volume (ebs | instance-store). + // + // state - The state of the image (available | pending | failed). + // + // state-reason-code - The reason code for the state change. + // + // state-reason-message - The message for the state change. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // virtualization-type - The virtualization type (paravirtual | hvm). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more image IDs. + // + // Default: Describes all images available to you. + ImageIds []*string `locationName:"ImageId" locationNameList:"ImageId" type:"list"` + + // Filters the images by the owner. Specify an AWS account ID, amazon (owner + // is Amazon), aws-marketplace (owner is AWS Marketplace), self (owner is the + // sender of the request). Omitting this option returns all images for which + // you have launch permissions, regardless of ownership. + Owners []*string `locationName:"Owner" locationNameList:"Owner" type:"list"` +} + +// String returns the string representation +func (s DescribeImagesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImagesInput) GoString() string { + return s.String() +} + +type DescribeImagesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more images. + Images []*Image `locationName:"imagesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeImagesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImagesOutput) GoString() string { + return s.String() +} + +type DescribeImportImageTasksInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + Filters []*Filter `locationNameList:"Filter" type:"list"` + + // A list of import image task IDs. + ImportTaskIds []*string `locationName:"ImportTaskId" locationNameList:"ImportTaskId" type:"list"` + + // The maximum number of results to return in a single request. + MaxResults *int64 `type:"integer"` + + // A token that indicates the next page of results. + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeImportImageTasksInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImportImageTasksInput) GoString() string { + return s.String() +} + +type DescribeImportImageTasksOutput struct { + _ struct{} `type:"structure"` + + // A list of zero or more import image tasks that are currently active or were + // completed or canceled in the previous 7 days. + ImportImageTasks []*ImportImageTask `locationName:"importImageTaskSet" locationNameList:"item" type:"list"` + + // The token to use to get the next page of results. This value is null when + // there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeImportImageTasksOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImportImageTasksOutput) GoString() string { + return s.String() +} + +type DescribeImportSnapshotTasksInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + Filters []*Filter `locationNameList:"Filter" type:"list"` + + // A list of import snapshot task IDs. + ImportTaskIds []*string `locationName:"ImportTaskId" locationNameList:"ImportTaskId" type:"list"` + + // The maximum number of results to return in a single request. + MaxResults *int64 `type:"integer"` + + // A token that indicates the next page of results. + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeImportSnapshotTasksInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImportSnapshotTasksInput) GoString() string { + return s.String() +} + +type DescribeImportSnapshotTasksOutput struct { + _ struct{} `type:"structure"` + + // A list of zero or more import snapshot tasks that are currently active or + // were completed or canceled in the previous 7 days. + ImportSnapshotTasks []*ImportSnapshotTask `locationName:"importSnapshotTaskSet" locationNameList:"item" type:"list"` + + // The token to use to get the next page of results. This value is null when + // there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeImportSnapshotTasksOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeImportSnapshotTasksOutput) GoString() string { + return s.String() +} + +type DescribeInstanceAttributeInput struct { + _ struct{} `type:"structure"` + + // The instance attribute. + Attribute *string `locationName:"attribute" type:"string" required:"true" enum:"InstanceAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeInstanceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstanceAttributeInput) GoString() string { + return s.String() +} + +// Describes an instance attribute. +type DescribeInstanceAttributeOutput struct { + _ struct{} `type:"structure"` + + // The block device mapping of the instance. + BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // If the value is true, you can't terminate the instance through the Amazon + // EC2 console, CLI, or API; otherwise, you can. + DisableApiTermination *AttributeBooleanValue `locationName:"disableApiTermination" type:"structure"` + + // Indicates whether the instance is optimized for EBS I/O. + EbsOptimized *AttributeBooleanValue `locationName:"ebsOptimized" type:"structure"` + + // The security groups associated with the instance. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // Indicates whether an instance stops or terminates when you initiate shutdown + // from the instance (using the operating system command for system shutdown). + InstanceInitiatedShutdownBehavior *AttributeValue `locationName:"instanceInitiatedShutdownBehavior" type:"structure"` + + // The instance type. + InstanceType *AttributeValue `locationName:"instanceType" type:"structure"` + + // The kernel ID. + KernelId *AttributeValue `locationName:"kernel" type:"structure"` + + // A list of product codes. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // The RAM disk ID. + RamdiskId *AttributeValue `locationName:"ramdisk" type:"structure"` + + // The name of the root device (for example, /dev/sda1 or /dev/xvda). + RootDeviceName *AttributeValue `locationName:"rootDeviceName" type:"structure"` + + // Indicates whether source/destination checking is enabled. A value of true + // means checking is enabled, and false means checking is disabled. This value + // must be false for a NAT instance to perform NAT. + SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` + + // The value to use for a resource attribute. + SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` + + // The Base64-encoded MIME user data. + UserData *AttributeValue `locationName:"userData" type:"structure"` +} + +// String returns the string representation +func (s DescribeInstanceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstanceAttributeOutput) GoString() string { + return s.String() +} + +type DescribeInstanceStatusInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // availability-zone - The Availability Zone of the instance. + // + // event.code - The code for the scheduled event (instance-reboot | system-reboot + // | system-maintenance | instance-retirement | instance-stop). + // + // event.description - A description of the event. + // + // event.not-after - The latest end time for the scheduled event (for example, + // 2014-09-15T17:15:20.000Z). + // + // event.not-before - The earliest start time for the scheduled event (for + // example, 2014-09-15T17:15:20.000Z). + // + // instance-state-code - The code for the instance state, as a 16-bit unsigned + // integer. The high byte is an opaque internal value and should be ignored. + // The low byte is set based on the state represented. The valid values are + // 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), + // and 80 (stopped). + // + // instance-state-name - The state of the instance (pending | running | shutting-down + // | terminated | stopping | stopped). + // + // instance-status.reachability - Filters on instance status where the name + // is reachability (passed | failed | initializing | insufficient-data). + // + // instance-status.status - The status of the instance (ok | impaired | initializing + // | insufficient-data | not-applicable). + // + // system-status.reachability - Filters on system status where the name is + // reachability (passed | failed | initializing | insufficient-data). + // + // system-status.status - The system status of the instance (ok | impaired + // | initializing | insufficient-data | not-applicable). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // When true, includes the health status for all instances. When false, includes + // the health status for running instances only. + // + // Default: false + IncludeAllInstances *bool `locationName:"includeAllInstances" type:"boolean"` + + // One or more instance IDs. + // + // Default: Describes all your instances. + // + // Constraints: Maximum 100 explicitly specified instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. You cannot specify this parameter and the instance IDs parameter + // in the same request. + MaxResults *int64 `type:"integer"` + + // The token to retrieve the next page of results. + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeInstanceStatusInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstanceStatusInput) GoString() string { + return s.String() +} + +type DescribeInstanceStatusOutput struct { + _ struct{} `type:"structure"` + + // One or more instance status descriptions. + InstanceStatuses []*InstanceStatus `locationName:"instanceStatusSet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeInstanceStatusOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstanceStatusOutput) GoString() string { + return s.String() +} + +type DescribeInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // affinity - The affinity setting for an instance running on a Dedicated + // host (default | host). + // + // architecture - The instance architecture (i386 | x86_64). + // + // availability-zone - The Availability Zone of the instance. + // + // block-device-mapping.attach-time - The attach time for an EBS volume mapped + // to the instance, for example, 2010-09-15T17:15:20.000Z. + // + // block-device-mapping.delete-on-termination - A Boolean that indicates + // whether the EBS volume is deleted on instance termination. + // + // block-device-mapping.device-name - The device name for the EBS volume + // (for example, /dev/sdh or xvdh). + // + // block-device-mapping.status - The status for the EBS volume (attaching + // | attached | detaching | detached). + // + // block-device-mapping.volume-id - The volume ID of the EBS volume. + // + // client-token - The idempotency token you provided when you launched the + // instance. + // + // dns-name - The public DNS name of the instance. + // + // group-id - The ID of the security group for the instance. EC2-Classic + // only. + // + // group-name - The name of the security group for the instance. EC2-Classic + // only. + // + // host-Id - The ID of the Dedicated host on which the instance is running, + // if applicable. + // + // hypervisor - The hypervisor type of the instance (ovm | xen). + // + // iam-instance-profile.arn - The instance profile associated with the instance. + // Specified as an ARN. + // + // image-id - The ID of the image used to launch the instance. + // + // instance-id - The ID of the instance. + // + // instance-lifecycle - Indicates whether this is a Spot Instance (spot). + // + // instance-state-code - The state of the instance, as a 16-bit unsigned + // integer. The high byte is an opaque internal value and should be ignored. + // The low byte is set based on the state represented. The valid values are: + // 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), + // and 80 (stopped). + // + // instance-state-name - The state of the instance (pending | running | shutting-down + // | terminated | stopping | stopped). + // + // instance-type - The type of instance (for example, t2.micro). + // + // instance.group-id - The ID of the security group for the instance. + // + // instance.group-name - The name of the security group for the instance. + // + // ip-address - The public IP address of the instance. + // + // kernel-id - The kernel ID. + // + // key-name - The name of the key pair used when the instance was launched. + // + // launch-index - When launching multiple instances, this is the index for + // the instance in the launch group (for example, 0, 1, 2, and so on). + // + // launch-time - The time when the instance was launched. + // + // monitoring-state - Indicates whether monitoring is enabled for the instance + // (disabled | enabled). + // + // owner-id - The AWS account ID of the instance owner. + // + // placement-group-name - The name of the placement group for the instance. + // + // platform - The platform. Use windows if you have Windows instances; otherwise, + // leave blank. + // + // private-dns-name - The private DNS name of the instance. + // + // private-ip-address - The private IP address of the instance. + // + // product-code - The product code associated with the AMI used to launch + // the instance. + // + // product-code.type - The type of product code (devpay | marketplace). + // + // ramdisk-id - The RAM disk ID. + // + // reason - The reason for the current state of the instance (for example, + // shows "User Initiated [date]" when you stop or terminate the instance). Similar + // to the state-reason-code filter. + // + // requester-id - The ID of the entity that launched the instance on your + // behalf (for example, AWS Management Console, Auto Scaling, and so on). + // + // reservation-id - The ID of the instance's reservation. A reservation ID + // is created any time you launch an instance. A reservation ID has a one-to-one + // relationship with an instance launch request, but can be associated with + // more than one instance if you launch multiple instances using the same launch + // request. For example, if you launch one instance, you'll get one reservation + // ID. If you launch ten instances using the same launch request, you'll also + // get one reservation ID. + // + // root-device-name - The name of the root device for the instance (for example, + // /dev/sda1 or /dev/xvda). + // + // root-device-type - The type of root device that the instance uses (ebs + // | instance-store). + // + // source-dest-check - Indicates whether the instance performs source/destination + // checking. A value of true means that checking is enabled, and false means + // checking is disabled. The value must be false for the instance to perform + // network address translation (NAT) in your VPC. + // + // spot-instance-request-id - The ID of the Spot instance request. + // + // state-reason-code - The reason code for the state change. + // + // state-reason-message - A message that describes the state change. + // + // subnet-id - The ID of the subnet for the instance. + // + // tag:key=value - The key/value combination of a tag assigned to the resource, + // where tag:key is the tag's key. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // tenancy - The tenancy of an instance (dedicated | default | host). + // + // virtualization-type - The virtualization type of the instance (paravirtual + // | hvm). + // + // vpc-id - The ID of the VPC that the instance is running in. + // + // network-interface.description - The description of the network interface. + // + // network-interface.subnet-id - The ID of the subnet for the network interface. + // + // network-interface.vpc-id - The ID of the VPC for the network interface. + // + // network-interface.network-interface-id - The ID of the network interface. + // + // network-interface.owner-id - The ID of the owner of the network interface. + // + // network-interface.availability-zone - The Availability Zone for the network + // interface. + // + // network-interface.requester-id - The requester ID for the network interface. + // + // network-interface.requester-managed - Indicates whether the network interface + // is being managed by AWS. + // + // network-interface.status - The status of the network interface (available) + // | in-use). + // + // network-interface.mac-address - The MAC address of the network interface. + // + // network-interface.private-dns-name - The private DNS name of the network + // interface. + // + // network-interface.source-dest-check - Whether the network interface performs + // source/destination checking. A value of true means checking is enabled, and + // false means checking is disabled. The value must be false for the network + // interface to perform network address translation (NAT) in your VPC. + // + // network-interface.group-id - The ID of a security group associated with + // the network interface. + // + // network-interface.group-name - The name of a security group associated + // with the network interface. + // + // network-interface.attachment.attachment-id - The ID of the interface attachment. + // + // network-interface.attachment.instance-id - The ID of the instance to which + // the network interface is attached. + // + // network-interface.attachment.instance-owner-id - The owner ID of the instance + // to which the network interface is attached. + // + // network-interface.addresses.private-ip-address - The private IP address + // associated with the network interface. + // + // network-interface.attachment.device-index - The device index to which + // the network interface is attached. + // + // network-interface.attachment.status - The status of the attachment (attaching + // | attached | detaching | detached). + // + // network-interface.attachment.attach-time - The time that the network interface + // was attached to an instance. + // + // network-interface.attachment.delete-on-termination - Specifies whether + // the attachment is deleted when an instance is terminated. + // + // network-interface.addresses.primary - Specifies whether the IP address + // of the network interface is the primary private IP address. + // + // network-interface.addresses.association.public-ip - The ID of the association + // of an Elastic IP address with a network interface. + // + // network-interface.addresses.association.ip-owner-id - The owner ID of + // the private IP address associated with the network interface. + // + // association.public-ip - The address of the Elastic IP address bound to + // the network interface. + // + // association.ip-owner-id - The owner of the Elastic IP address associated + // with the network interface. + // + // association.allocation-id - The allocation ID returned when you allocated + // the Elastic IP address for your network interface. + // + // association.association-id - The association ID returned when the network + // interface was associated with an IP address. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more instance IDs. + // + // Default: Describes all your instances. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. You cannot specify this parameter and the instance IDs parameter + // in the same request. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token to request the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstancesInput) GoString() string { + return s.String() +} + +type DescribeInstancesOutput struct { + _ struct{} `type:"structure"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Zero or more reservations. + Reservations []*Reservation `locationName:"reservationSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInstancesOutput) GoString() string { + return s.String() +} + +type DescribeInternetGatewaysInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // attachment.state - The current state of the attachment between the gateway + // and the VPC (available). Present only if a VPC is attached. + // + // attachment.vpc-id - The ID of an attached VPC. + // + // internet-gateway-id - The ID of the Internet gateway. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more Internet gateway IDs. + // + // Default: Describes all your Internet gateways. + InternetGatewayIds []*string `locationName:"internetGatewayId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeInternetGatewaysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInternetGatewaysInput) GoString() string { + return s.String() +} + +type DescribeInternetGatewaysOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more Internet gateways. + InternetGateways []*InternetGateway `locationName:"internetGatewaySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeInternetGatewaysOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeInternetGatewaysOutput) GoString() string { + return s.String() +} + +type DescribeKeyPairsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // fingerprint - The fingerprint of the key pair. + // + // key-name - The name of the key pair. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more key pair names. + // + // Default: Describes all your key pairs. + KeyNames []*string `locationName:"KeyName" locationNameList:"KeyName" type:"list"` +} + +// String returns the string representation +func (s DescribeKeyPairsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeKeyPairsInput) GoString() string { + return s.String() +} + +type DescribeKeyPairsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more key pairs. + KeyPairs []*KeyPairInfo `locationName:"keySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeKeyPairsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeKeyPairsOutput) GoString() string { + return s.String() +} + +type DescribeMovingAddressesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // moving-status - The status of the Elastic IP address (MovingToVpc | RestoringToClassic). + Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value outside of this range, an error is returned. + // + // Default: If no value is provided, the default is 1000. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token to use to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // One or more Elastic IP addresses. + PublicIps []*string `locationName:"publicIp" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeMovingAddressesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeMovingAddressesInput) GoString() string { + return s.String() +} + +type DescribeMovingAddressesOutput struct { + _ struct{} `type:"structure"` + + // The status for each Elastic IP address. + MovingAddressStatuses []*MovingAddressStatus `locationName:"movingAddressStatusSet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeMovingAddressesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeMovingAddressesOutput) GoString() string { + return s.String() +} + +type DescribeNatGatewaysInput struct { + _ struct{} `type:"structure"` + + // One or more filters. + // + // nat-gateway-id - The ID of the NAT gateway. + // + // state - The state of the NAT gateway (pending | failed | available | deleting + // | deleted). + // + // subnet-id - The ID of the subnet in which the NAT gateway resides. + // + // vpc-id - The ID of the VPC in which the NAT gateway resides. + Filter []*Filter `locationNameList:"Filter" type:"list"` + + // The maximum number of items to return for this request. The request returns + // a token that you can specify in a subsequent call to get the next set of + // results. + // + // Constraint: If the value specified is greater than 1000, we return only + // 1000 items. + MaxResults *int64 `type:"integer"` + + // One or more NAT gateway IDs. + NatGatewayIds []*string `locationName:"NatGatewayId" locationNameList:"item" type:"list"` + + // The token to retrieve the next page of results. + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeNatGatewaysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNatGatewaysInput) GoString() string { + return s.String() +} + +type DescribeNatGatewaysOutput struct { + _ struct{} `type:"structure"` + + // Information about the NAT gateways. + NatGateways []*NatGateway `locationName:"natGatewaySet" locationNameList:"item" type:"list"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeNatGatewaysOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNatGatewaysOutput) GoString() string { + return s.String() +} + +type DescribeNetworkAclsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // association.association-id - The ID of an association ID for the ACL. + // + // association.network-acl-id - The ID of the network ACL involved in the + // association. + // + // association.subnet-id - The ID of the subnet involved in the association. + // + // default - Indicates whether the ACL is the default network ACL for the + // VPC. + // + // entry.cidr - The CIDR range specified in the entry. + // + // entry.egress - Indicates whether the entry applies to egress traffic. + // + // entry.icmp.code - The ICMP code specified in the entry, if any. + // + // entry.icmp.type - The ICMP type specified in the entry, if any. + // + // entry.port-range.from - The start of the port range specified in the entry. + // + // entry.port-range.to - The end of the port range specified in the entry. + // + // entry.protocol - The protocol specified in the entry (tcp | udp | icmp + // or a protocol number). + // + // entry.rule-action - Allows or denies the matching traffic (allow | deny). + // + // entry.rule-number - The number of an entry (in other words, rule) in the + // ACL's set of entries. + // + // network-acl-id - The ID of the network ACL. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC for the network ACL. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more network ACL IDs. + // + // Default: Describes all your network ACLs. + NetworkAclIds []*string `locationName:"NetworkAclId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeNetworkAclsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkAclsInput) GoString() string { + return s.String() +} + +type DescribeNetworkAclsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more network ACLs. + NetworkAcls []*NetworkAcl `locationName:"networkAclSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeNetworkAclsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkAclsOutput) GoString() string { + return s.String() +} + +type DescribeNetworkInterfaceAttributeInput struct { + _ struct{} `type:"structure"` + + // The attribute of the network interface. + Attribute *string `locationName:"attribute" type:"string" enum:"NetworkInterfaceAttribute"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeNetworkInterfaceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkInterfaceAttributeInput) GoString() string { + return s.String() +} + +type DescribeNetworkInterfaceAttributeOutput struct { + _ struct{} `type:"structure"` + + // The attachment (if any) of the network interface. + Attachment *NetworkInterfaceAttachment `locationName:"attachment" type:"structure"` + + // The description of the network interface. + Description *AttributeValue `locationName:"description" type:"structure"` + + // The security groups associated with the network interface. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // Indicates whether source/destination checking is enabled. + SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` +} + +// String returns the string representation +func (s DescribeNetworkInterfaceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkInterfaceAttributeOutput) GoString() string { + return s.String() +} + +type DescribeNetworkInterfacesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // addresses.private-ip-address - The private IP addresses associated with + // the network interface. + // + // addresses.primary - Whether the private IP address is the primary IP address + // associated with the network interface. + // + // addresses.association.public-ip - The association ID returned when the + // network interface was associated with the Elastic IP address. + // + // addresses.association.owner-id - The owner ID of the addresses associated + // with the network interface. + // + // association.association-id - The association ID returned when the network + // interface was associated with an IP address. + // + // association.allocation-id - The allocation ID returned when you allocated + // the Elastic IP address for your network interface. + // + // association.ip-owner-id - The owner of the Elastic IP address associated + // with the network interface. + // + // association.public-ip - The address of the Elastic IP address bound to + // the network interface. + // + // association.public-dns-name - The public DNS name for the network interface. + // + // attachment.attachment-id - The ID of the interface attachment. + // + // attachment.attach.time - The time that the network interface was attached + // to an instance. + // + // attachment.delete-on-termination - Indicates whether the attachment is + // deleted when an instance is terminated. + // + // attachment.device-index - The device index to which the network interface + // is attached. + // + // attachment.instance-id - The ID of the instance to which the network interface + // is attached. + // + // attachment.instance-owner-id - The owner ID of the instance to which the + // network interface is attached. + // + // attachment.nat-gateway-id - The ID of the NAT gateway to which the network + // interface is attached. + // + // attachment.status - The status of the attachment (attaching | attached + // | detaching | detached). + // + // availability-zone - The Availability Zone of the network interface. + // + // description - The description of the network interface. + // + // group-id - The ID of a security group associated with the network interface. + // + // group-name - The name of a security group associated with the network + // interface. + // + // mac-address - The MAC address of the network interface. + // + // network-interface-id - The ID of the network interface. + // + // owner-id - The AWS account ID of the network interface owner. + // + // private-ip-address - The private IP address or addresses of the network + // interface. + // + // private-dns-name - The private DNS name of the network interface. + // + // requester-id - The ID of the entity that launched the instance on your + // behalf (for example, AWS Management Console, Auto Scaling, and so on). + // + // requester-managed - Indicates whether the network interface is being managed + // by an AWS service (for example, AWS Management Console, Auto Scaling, and + // so on). + // + // source-desk-check - Indicates whether the network interface performs source/destination + // checking. A value of true means checking is enabled, and false means checking + // is disabled. The value must be false for the network interface to perform + // network address translation (NAT) in your VPC. + // + // status - The status of the network interface. If the network interface + // is not attached to an instance, the status is available; if a network interface + // is attached to an instance the status is in-use. + // + // subnet-id - The ID of the subnet for the network interface. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC for the network interface. + Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` + + // One or more network interface IDs. + // + // Default: Describes all your network interfaces. + NetworkInterfaceIds []*string `locationName:"NetworkInterfaceId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeNetworkInterfacesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkInterfacesInput) GoString() string { + return s.String() +} + +type DescribeNetworkInterfacesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more network interfaces. + NetworkInterfaces []*NetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeNetworkInterfacesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeNetworkInterfacesOutput) GoString() string { + return s.String() +} + +type DescribePlacementGroupsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // group-name - The name of the placement group. + // + // state - The state of the placement group (pending | available | deleting + // | deleted). + // + // strategy - The strategy of the placement group (cluster). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more placement group names. + // + // Default: Describes all your placement groups, or only those otherwise specified. + GroupNames []*string `locationName:"groupName" type:"list"` +} + +// String returns the string representation +func (s DescribePlacementGroupsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribePlacementGroupsInput) GoString() string { + return s.String() +} + +type DescribePlacementGroupsOutput struct { + _ struct{} `type:"structure"` + + // One or more placement groups. + PlacementGroups []*PlacementGroup `locationName:"placementGroupSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribePlacementGroupsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribePlacementGroupsOutput) GoString() string { + return s.String() +} + +type DescribePrefixListsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + // + // prefix-list-id: The ID of a prefix list. + // + // prefix-list-name: The name of a prefix list. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of items to return for this request. The request returns + // a token that you can specify in a subsequent call to get the next set of + // results. + // + // Constraint: If the value specified is greater than 1000, we return only + // 1000 items. + MaxResults *int64 `type:"integer"` + + // The token for the next set of items to return. (You received this token from + // a prior call.) + NextToken *string `type:"string"` + + // One or more prefix list IDs. + PrefixListIds []*string `locationName:"PrefixListId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribePrefixListsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribePrefixListsInput) GoString() string { + return s.String() +} + +type DescribePrefixListsOutput struct { + _ struct{} `type:"structure"` + + // The token to use when requesting the next set of items. If there are no additional + // items to return, the string is empty. + NextToken *string `locationName:"nextToken" type:"string"` + + // All available prefix lists. + PrefixLists []*PrefixList `locationName:"prefixListSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribePrefixListsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribePrefixListsOutput) GoString() string { + return s.String() +} + +type DescribeRegionsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // endpoint - The endpoint of the region (for example, ec2.us-east-1.amazonaws.com). + // + // region-name - The name of the region (for example, us-east-1). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The names of one or more regions. + RegionNames []*string `locationName:"RegionName" locationNameList:"RegionName" type:"list"` +} + +// String returns the string representation +func (s DescribeRegionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeRegionsInput) GoString() string { + return s.String() +} + +type DescribeRegionsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more regions. + Regions []*Region `locationName:"regionInfo" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeRegionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeRegionsOutput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // availability-zone - The Availability Zone where the Reserved Instance + // can be used. + // + // duration - The duration of the Reserved Instance (one year or three years), + // in seconds (31536000 | 94608000). + // + // end - The time when the Reserved Instance expires (for example, 2015-08-07T11:54:42.000Z). + // + // fixed-price - The purchase price of the Reserved Instance (for example, + // 9800.0). + // + // instance-type - The instance type that is covered by the reservation. + // + // product-description - The Reserved Instance product platform description. + // Instances that include (Amazon VPC) in the product platform description will + // only be displayed to EC2-Classic account holders and are for use with Amazon + // VPC (Linux/UNIX | Linux/UNIX (Amazon VPC) | SUSE Linux | SUSE Linux (Amazon + // VPC) | Red Hat Enterprise Linux | Red Hat Enterprise Linux (Amazon VPC) | + // Windows | Windows (Amazon VPC) | Windows with SQL Server Standard | Windows + // with SQL Server Standard (Amazon VPC) | Windows with SQL Server Web | Windows + // with SQL Server Web (Amazon VPC) | Windows with SQL Server Enterprise | Windows + // with SQL Server Enterprise (Amazon VPC)). + // + // reserved-instances-id - The ID of the Reserved Instance. + // + // start - The time at which the Reserved Instance purchase request was placed + // (for example, 2014-08-07T11:54:42.000Z). + // + // state - The state of the Reserved Instance (payment-pending | active | + // payment-failed | retired). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // usage-price - The usage price of the Reserved Instance, per hour (for + // example, 0.84). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The Reserved Instance offering type. If you are using tools that predate + // the 2011-11-01 API version, you only have access to the Medium Utilization + // Reserved Instance offering type. + OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` + + // One or more Reserved Instance IDs. + // + // Default: Describes all your Reserved Instances, or only those otherwise + // specified. + ReservedInstancesIds []*string `locationName:"ReservedInstancesId" locationNameList:"ReservedInstancesId" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesInput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesListingsInput struct { + _ struct{} `type:"structure"` + + // One or more filters. + // + // reserved-instances-id - The ID of the Reserved Instances. + // + // reserved-instances-listing-id - The ID of the Reserved Instances listing. + // + // status - The status of the Reserved Instance listing (pending | active + // | cancelled | closed). + // + // status-message - The reason for the status. + Filters []*Filter `locationName:"filters" locationNameList:"Filter" type:"list"` + + // One or more Reserved Instance IDs. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` + + // One or more Reserved Instance listing IDs. + ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string"` +} + +// String returns the string representation +func (s DescribeReservedInstancesListingsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesListingsInput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesListingsOutput struct { + _ struct{} `type:"structure"` + + // Information about the Reserved Instance listing. + ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesListingsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesListingsOutput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesModificationsInput struct { + _ struct{} `type:"structure"` + + // One or more filters. + // + // client-token - The idempotency token for the modification request. + // + // create-date - The time when the modification request was created. + // + // effective-date - The time when the modification becomes effective. + // + // modification-result.reserved-instances-id - The ID for the Reserved Instances + // created as part of the modification request. This ID is only available when + // the status of the modification is fulfilled. + // + // modification-result.target-configuration.availability-zone - The Availability + // Zone for the new Reserved Instances. + // + // modification-result.target-configuration.instance-count - The number + // of new Reserved Instances. + // + // modification-result.target-configuration.instance-type - The instance + // type of the new Reserved Instances. + // + // modification-result.target-configuration.platform - The network platform + // of the new Reserved Instances (EC2-Classic | EC2-VPC). + // + // reserved-instances-id - The ID of the Reserved Instances modified. + // + // reserved-instances-modification-id - The ID of the modification request. + // + // status - The status of the Reserved Instances modification request (processing + // | fulfilled | failed). + // + // status-message - The reason for the status. + // + // update-date - The time when the modification request was last updated. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The token to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // IDs for the submitted modification request. + ReservedInstancesModificationIds []*string `locationName:"ReservedInstancesModificationId" locationNameList:"ReservedInstancesModificationId" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesModificationsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesModificationsInput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesModificationsOutput struct { + _ struct{} `type:"structure"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // The Reserved Instance modification information. + ReservedInstancesModifications []*ReservedInstancesModification `locationName:"reservedInstancesModificationsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesModificationsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesModificationsOutput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesOfferingsInput struct { + _ struct{} `type:"structure"` + + // The Availability Zone in which the Reserved Instance can be used. + AvailabilityZone *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // availability-zone - The Availability Zone where the Reserved Instance + // can be used. + // + // duration - The duration of the Reserved Instance (for example, one year + // or three years), in seconds (31536000 | 94608000). + // + // fixed-price - The purchase price of the Reserved Instance (for example, + // 9800.0). + // + // instance-type - The instance type that is covered by the reservation. + // + // marketplace - Set to true to show only Reserved Instance Marketplace offerings. + // When this filter is not used, which is the default behavior, all offerings + // from both AWS and the Reserved Instance Marketplace are listed. + // + // product-description - The Reserved Instance product platform description. + // Instances that include (Amazon VPC) in the product platform description will + // only be displayed to EC2-Classic account holders and are for use with Amazon + // VPC. (Linux/UNIX | Linux/UNIX (Amazon VPC) | SUSE Linux | SUSE Linux (Amazon + // VPC) | Red Hat Enterprise Linux | Red Hat Enterprise Linux (Amazon VPC) | + // Windows | Windows (Amazon VPC) | Windows with SQL Server Standard | Windows + // with SQL Server Standard (Amazon VPC) | Windows with SQL Server Web | Windows + // with SQL Server Web (Amazon VPC) | Windows with SQL Server Enterprise | Windows + // with SQL Server Enterprise (Amazon VPC)) + // + // reserved-instances-offering-id - The Reserved Instances offering ID. + // + // usage-price - The usage price of the Reserved Instance, per hour (for + // example, 0.84). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // Include Reserved Instance Marketplace offerings in the response. + IncludeMarketplace *bool `type:"boolean"` + + // The tenancy of the instances covered by the reservation. A Reserved Instance + // with a tenancy of dedicated is applied to instances that run in a VPC on + // single-tenant hardware (i.e., Dedicated Instances). + // + // Default: default + InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` + + // The instance type that the reservation will cover (for example, m1.small). + // For more information, see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) + // in the Amazon Elastic Compute Cloud User Guide. + InstanceType *string `type:"string" enum:"InstanceType"` + + // The maximum duration (in seconds) to filter when searching for offerings. + // + // Default: 94608000 (3 years) + MaxDuration *int64 `type:"long"` + + // The maximum number of instances to filter when searching for offerings. + // + // Default: 20 + MaxInstanceCount *int64 `type:"integer"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. The maximum is 100. + // + // Default: 100 + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The minimum duration (in seconds) to filter when searching for offerings. + // + // Default: 2592000 (1 month) + MinDuration *int64 `type:"long"` + + // The token to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // The Reserved Instance offering type. If you are using tools that predate + // the 2011-11-01 API version, you only have access to the Medium Utilization + // Reserved Instance offering type. + OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` + + // The Reserved Instance product platform description. Instances that include + // (Amazon VPC) in the description are for use with Amazon VPC. + ProductDescription *string `type:"string" enum:"RIProductDescription"` + + // One or more Reserved Instances offering IDs. + ReservedInstancesOfferingIds []*string `locationName:"ReservedInstancesOfferingId" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesOfferingsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesOfferingsInput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesOfferingsOutput struct { + _ struct{} `type:"structure"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // A list of Reserved Instances offerings. + ReservedInstancesOfferings []*ReservedInstancesOffering `locationName:"reservedInstancesOfferingsSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesOfferingsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesOfferingsOutput) GoString() string { + return s.String() +} + +type DescribeReservedInstancesOutput struct { + _ struct{} `type:"structure"` + + // A list of Reserved Instances. + ReservedInstances []*ReservedInstances `locationName:"reservedInstancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeReservedInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeReservedInstancesOutput) GoString() string { + return s.String() +} + +type DescribeRouteTablesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // association.route-table-association-id - The ID of an association ID for + // the route table. + // + // association.route-table-id - The ID of the route table involved in the + // association. + // + // association.subnet-id - The ID of the subnet involved in the association. + // + // association.main - Indicates whether the route table is the main route + // table for the VPC (true | false). + // + // route-table-id - The ID of the route table. + // + // route.destination-cidr-block - The CIDR range specified in a route in + // the table. + // + // route.destination-prefix-list-id - The ID (prefix) of the AWS service + // specified in a route in the table. + // + // route.gateway-id - The ID of a gateway specified in a route in the table. + // + // route.instance-id - The ID of an instance specified in a route in the + // table. + // + // route.nat-gateway-id - The ID of a NAT gateway. + // + // route.origin - Describes how the route was created. CreateRouteTable indicates + // that the route was automatically created when the route table was created; + // CreateRoute indicates that the route was manually added to the route table; + // EnableVgwRoutePropagation indicates that the route was propagated by route + // propagation. + // + // route.state - The state of a route in the route table (active | blackhole). + // The blackhole state indicates that the route's target isn't available (for + // example, the specified gateway isn't attached to the VPC, the specified NAT + // instance has been terminated, and so on). + // + // route.vpc-peering-connection-id - The ID of a VPC peering connection specified + // in a route in the table. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC for the route table. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more route table IDs. + // + // Default: Describes all your route tables. + RouteTableIds []*string `locationName:"RouteTableId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeRouteTablesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeRouteTablesInput) GoString() string { + return s.String() +} + +type DescribeRouteTablesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more route tables. + RouteTables []*RouteTable `locationName:"routeTableSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeRouteTablesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeRouteTablesOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeScheduledInstanceAvailability. +type DescribeScheduledInstanceAvailabilityInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + // + // availability-zone - The Availability Zone (for example, us-west-2a). + // + // instance-type - The instance type (for example, c4.large). + // + // network-platform - The network platform (EC2-Classic or EC2-VPC). + // + // platform - The platform (Linux/UNIX or Windows). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The time period for the first schedule to start. + FirstSlotStartTimeRange *SlotDateTimeRangeRequest `type:"structure" required:"true"` + + // The maximum number of results to return in a single call. To retrieve the + // remaining results, make another call with the returned NextToken value. + MaxResults *int64 `type:"integer"` + + // The maximum available duration, in hours. This value must be greater than + // MinSlotDurationInHours and less than 1,720. + MaxSlotDurationInHours *int64 `type:"integer"` + + // The minimum available duration, in hours. The minimum required duration is + // 1,200 hours per year. For example, the minimum daily schedule is 4 hours, + // the minimum weekly schedule is 24 hours, and the minimum monthly schedule + // is 100 hours. + MinSlotDurationInHours *int64 `type:"integer"` + + // The token for the next set of results. + NextToken *string `type:"string"` + + // The schedule recurrence. + Recurrence *ScheduledInstanceRecurrenceRequest `type:"structure" required:"true"` +} + +// String returns the string representation +func (s DescribeScheduledInstanceAvailabilityInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeScheduledInstanceAvailabilityInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeScheduledInstanceAvailability. +type DescribeScheduledInstanceAvailabilityOutput struct { + _ struct{} `type:"structure"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the available Scheduled Instances. + ScheduledInstanceAvailabilitySet []*ScheduledInstanceAvailability `locationName:"scheduledInstanceAvailabilitySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeScheduledInstanceAvailabilityOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeScheduledInstanceAvailabilityOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeScheduledInstances. +type DescribeScheduledInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + // + // availability-zone - The Availability Zone (for example, us-west-2a). + // + // instance-type - The instance type (for example, c4.large). + // + // network-platform - The network platform (EC2-Classic or EC2-VPC). + // + // platform - The platform (Linux/UNIX or Windows). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of results to return in a single call. To retrieve the + // remaining results, make another call with the returned NextToken value. + MaxResults *int64 `type:"integer"` + + // The token for the next set of results. + NextToken *string `type:"string"` + + // One or more Scheduled Instance IDs. + ScheduledInstanceIds []*string `locationName:"ScheduledInstanceId" locationNameList:"ScheduledInstanceId" type:"list"` + + // The time period for the first schedule to start. + SlotStartTimeRange *SlotStartTimeRangeRequest `type:"structure"` +} + +// String returns the string representation +func (s DescribeScheduledInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeScheduledInstancesInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeScheduledInstances. +type DescribeScheduledInstancesOutput struct { + _ struct{} `type:"structure"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the Scheduled Instances. + ScheduledInstanceSet []*ScheduledInstance `locationName:"scheduledInstanceSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeScheduledInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeScheduledInstancesOutput) GoString() string { + return s.String() +} + +type DescribeSecurityGroupsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. If using multiple filters for rules, the results include + // security groups for which any combination of rules - not necessarily a single + // rule - match all filters. + // + // description - The description of the security group. + // + // egress.ip-permission.prefix-list-id - The ID (prefix) of the AWS service + // to which the security group allows access. + // + // group-id - The ID of the security group. + // + // group-name - The name of the security group. + // + // ip-permission.cidr - A CIDR range that has been granted permission. + // + // ip-permission.from-port - The start of port range for the TCP and UDP + // protocols, or an ICMP type number. + // + // ip-permission.group-id - The ID of a security group that has been granted + // permission. + // + // ip-permission.group-name - The name of a security group that has been + // granted permission. + // + // ip-permission.protocol - The IP protocol for the permission (tcp | udp + // | icmp or a protocol number). + // + // ip-permission.to-port - The end of port range for the TCP and UDP protocols, + // or an ICMP code. + // + // ip-permission.user-id - The ID of an AWS account that has been granted + // permission. + // + // owner-id - The AWS account ID of the owner of the security group. + // + // tag-key - The key of a tag assigned to the security group. + // + // tag-value - The value of a tag assigned to the security group. + // + // vpc-id - The ID of the VPC specified when the security group was created. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more security group IDs. Required for security groups in a nondefault + // VPC. + // + // Default: Describes all your security groups. + GroupIds []*string `locationName:"GroupId" locationNameList:"groupId" type:"list"` + + // [EC2-Classic and default VPC only] One or more security group names. You + // can specify either the security group name or the security group ID. For + // security groups in a nondefault VPC, use the group-name filter to describe + // security groups by name. + // + // Default: Describes all your security groups. + GroupNames []*string `locationName:"GroupName" locationNameList:"GroupName" type:"list"` +} + +// String returns the string representation +func (s DescribeSecurityGroupsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSecurityGroupsInput) GoString() string { + return s.String() +} + +type DescribeSecurityGroupsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more security groups. + SecurityGroups []*SecurityGroup `locationName:"securityGroupInfo" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSecurityGroupsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSecurityGroupsOutput) GoString() string { + return s.String() +} + +type DescribeSnapshotAttributeInput struct { + _ struct{} `type:"structure"` + + // The snapshot attribute you would like to view. + Attribute *string `type:"string" required:"true" enum:"SnapshotAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the EBS snapshot. + SnapshotId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeSnapshotAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSnapshotAttributeInput) GoString() string { + return s.String() +} + +type DescribeSnapshotAttributeOutput struct { + _ struct{} `type:"structure"` + + // A list of permissions for creating volumes from the snapshot. + CreateVolumePermissions []*CreateVolumePermission `locationName:"createVolumePermission" locationNameList:"item" type:"list"` + + // A list of product codes. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // The ID of the EBS snapshot. + SnapshotId *string `locationName:"snapshotId" type:"string"` +} + +// String returns the string representation +func (s DescribeSnapshotAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSnapshotAttributeOutput) GoString() string { + return s.String() +} + +type DescribeSnapshotsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // description - A description of the snapshot. + // + // owner-alias - The AWS account alias (for example, amazon) that owns the + // snapshot. + // + // owner-id - The ID of the AWS account that owns the snapshot. + // + // progress - The progress of the snapshot, as a percentage (for example, + // 80%). + // + // snapshot-id - The snapshot ID. + // + // start-time - The time stamp when the snapshot was initiated. + // + // status - The status of the snapshot (pending | completed | error). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // volume-id - The ID of the volume the snapshot is for. + // + // volume-size - The size of the volume, in GiB. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of snapshot results returned by DescribeSnapshots in paginated + // output. When this parameter is used, DescribeSnapshots only returns MaxResults + // results in a single page along with a NextToken response element. The remaining + // results of the initial request can be seen by sending another DescribeSnapshots + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. If this parameter is not used, then DescribeSnapshots returns + // all results. You cannot specify this parameter and the snapshot IDs parameter + // in the same request. + MaxResults *int64 `type:"integer"` + + // The NextToken value returned from a previous paginated DescribeSnapshots + // request where MaxResults was used and the results exceeded the value of that + // parameter. Pagination continues from the end of the previous results that + // returned the NextToken value. This value is null when there are no more results + // to return. + NextToken *string `type:"string"` + + // Returns the snapshots owned by the specified owner. Multiple owners can be + // specified. + OwnerIds []*string `locationName:"Owner" locationNameList:"Owner" type:"list"` + + // One or more AWS accounts IDs that can create volumes from the snapshot. + RestorableByUserIds []*string `locationName:"RestorableBy" type:"list"` + + // One or more snapshot IDs. + // + // Default: Describes snapshots for which you have launch permissions. + SnapshotIds []*string `locationName:"SnapshotId" locationNameList:"SnapshotId" type:"list"` +} + +// String returns the string representation +func (s DescribeSnapshotsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSnapshotsInput) GoString() string { + return s.String() +} + +type DescribeSnapshotsOutput struct { + _ struct{} `type:"structure"` + + // The NextToken value to include in a future DescribeSnapshots request. When + // the results of a DescribeSnapshots request exceed MaxResults, this value + // can be used to retrieve the next page of results. This value is null when + // there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the snapshots. + Snapshots []*Snapshot `locationName:"snapshotSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSnapshotsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSnapshotsOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotDatafeedSubscription. +type DescribeSpotDatafeedSubscriptionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DescribeSpotDatafeedSubscriptionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotDatafeedSubscriptionInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotDatafeedSubscription. +type DescribeSpotDatafeedSubscriptionOutput struct { + _ struct{} `type:"structure"` + + // The Spot instance data feed subscription. + SpotDatafeedSubscription *SpotDatafeedSubscription `locationName:"spotDatafeedSubscription" type:"structure"` +} + +// String returns the string representation +func (s DescribeSpotDatafeedSubscriptionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotDatafeedSubscriptionOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotFleetInstances. +type DescribeSpotFleetInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The maximum number of results to return in a single call. Specify a value + // between 1 and 1000. The default value is 1000. To retrieve the remaining + // results, make another call with the returned NextToken value. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token for the next set of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeSpotFleetInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetInstancesInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotFleetInstances. +type DescribeSpotFleetInstancesOutput struct { + _ struct{} `type:"structure"` + + // The running instances. Note that this list is refreshed periodically and + // might be out of date. + ActiveInstances []*ActiveInstance `locationName:"activeInstanceSet" locationNameList:"item" type:"list" required:"true"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeSpotFleetInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetInstancesOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotFleetRequestHistory. +type DescribeSpotFleetRequestHistoryInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The type of events to describe. By default, all events are described. + EventType *string `locationName:"eventType" type:"string" enum:"EventType"` + + // The maximum number of results to return in a single call. Specify a value + // between 1 and 1000. The default value is 1000. To retrieve the remaining + // results, make another call with the returned NextToken value. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token for the next set of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` + + // The starting date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` +} + +// String returns the string representation +func (s DescribeSpotFleetRequestHistoryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetRequestHistoryInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotFleetRequestHistory. +type DescribeSpotFleetRequestHistoryOutput struct { + _ struct{} `type:"structure"` + + // Information about the events in the history of the Spot fleet request. + HistoryRecords []*HistoryRecord `locationName:"historyRecordSet" locationNameList:"item" type:"list" required:"true"` + + // The last date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + // All records up to this time were retrieved. + // + // If nextToken indicates that there are more results, this value is not present. + LastEvaluatedTime *time.Time `locationName:"lastEvaluatedTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` + + // The starting date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` +} + +// String returns the string representation +func (s DescribeSpotFleetRequestHistoryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetRequestHistoryOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotFleetRequests. +type DescribeSpotFleetRequestsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The maximum number of results to return in a single call. Specify a value + // between 1 and 1000. The default value is 1000. To retrieve the remaining + // results, make another call with the returned NextToken value. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token for the next set of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // The IDs of the Spot fleet requests. + SpotFleetRequestIds []*string `locationName:"spotFleetRequestId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSpotFleetRequestsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetRequestsInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotFleetRequests. +type DescribeSpotFleetRequestsOutput struct { + _ struct{} `type:"structure"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the configuration of your Spot fleet. + SpotFleetRequestConfigs []*SpotFleetRequestConfig `locationName:"spotFleetRequestConfigSet" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s DescribeSpotFleetRequestsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotFleetRequestsOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotInstanceRequests. +type DescribeSpotInstanceRequestsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // availability-zone-group - The Availability Zone group. + // + // create-time - The time stamp when the Spot instance request was created. + // + // fault-code - The fault code related to the request. + // + // fault-message - The fault message related to the request. + // + // instance-id - The ID of the instance that fulfilled the request. + // + // launch-group - The Spot instance launch group. + // + // launch.block-device-mapping.delete-on-termination - Indicates whether + // the Amazon EBS volume is deleted on instance termination. + // + // launch.block-device-mapping.device-name - The device name for the Amazon + // EBS volume (for example, /dev/sdh). + // + // launch.block-device-mapping.snapshot-id - The ID of the snapshot used + // for the Amazon EBS volume. + // + // launch.block-device-mapping.volume-size - The size of the Amazon EBS volume, + // in GiB. + // + // launch.block-device-mapping.volume-type - The type of the Amazon EBS volume + // (gp2 | standard | io1). + // + // launch.group-id - The security group for the instance. + // + // launch.image-id - The ID of the AMI. + // + // launch.instance-type - The type of instance (for example, m3.medium). + // + // launch.kernel-id - The kernel ID. + // + // launch.key-name - The name of the key pair the instance launched with. + // + // launch.monitoring-enabled - Whether monitoring is enabled for the Spot + // instance. + // + // launch.ramdisk-id - The RAM disk ID. + // + // network-interface.network-interface-id - The ID of the network interface. + // + // network-interface.device-index - The index of the device for the network + // interface attachment on the instance. + // + // network-interface.subnet-id - The ID of the subnet for the instance. + // + // network-interface.description - A description of the network interface. + // + // network-interface.private-ip-address - The primary private IP address + // of the network interface. + // + // network-interface.delete-on-termination - Indicates whether the network + // interface is deleted when the instance is terminated. + // + // network-interface.group-id - The ID of the security group associated with + // the network interface. + // + // network-interface.group-name - The name of the security group associated + // with the network interface. + // + // network-interface.addresses.primary - Indicates whether the IP address + // is the primary private IP address. + // + // product-description - The product description associated with the instance + // (Linux/UNIX | Windows). + // + // spot-instance-request-id - The Spot instance request ID. + // + // spot-price - The maximum hourly price for any Spot instance launched to + // fulfill the request. + // + // state - The state of the Spot instance request (open | active | closed + // | cancelled | failed). Spot bid status information can help you track your + // Amazon EC2 Spot instance requests. For more information, see Spot Bid Status + // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // status-code - The short code describing the most recent evaluation of + // your Spot instance request. + // + // status-message - The message explaining the status of the Spot instance + // request. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // type - The type of Spot instance request (one-time | persistent). + // + // launched-availability-zone - The Availability Zone in which the bid is + // launched. + // + // valid-from - The start date of the request. + // + // valid-until - The end date of the request. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more Spot instance request IDs. + SpotInstanceRequestIds []*string `locationName:"SpotInstanceRequestId" locationNameList:"SpotInstanceRequestId" type:"list"` +} + +// String returns the string representation +func (s DescribeSpotInstanceRequestsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotInstanceRequestsInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotInstanceRequests. +type DescribeSpotInstanceRequestsOutput struct { + _ struct{} `type:"structure"` + + // One or more Spot instance requests. + SpotInstanceRequests []*SpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSpotInstanceRequestsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotInstanceRequestsOutput) GoString() string { + return s.String() +} + +// Contains the parameters for DescribeSpotPriceHistory. +type DescribeSpotPriceHistoryInput struct { + _ struct{} `type:"structure"` + + // Filters the results by the specified Availability Zone. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The date and time, up to the current date, from which to stop retrieving + // the price history data, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + EndTime *time.Time `locationName:"endTime" type:"timestamp" timestampFormat:"iso8601"` + + // One or more filters. + // + // availability-zone - The Availability Zone for which prices should be returned. + // + // instance-type - The type of instance (for example, m3.medium). + // + // product-description - The product description for the Spot price (Linux/UNIX + // | SUSE Linux | Windows | Linux/UNIX (Amazon VPC) | SUSE Linux (Amazon VPC) + // | Windows (Amazon VPC)). + // + // spot-price - The Spot price. The value must match exactly (or use wildcards; + // greater than or less than comparison is not supported). + // + // timestamp - The timestamp of the Spot price history, in UTC format (for + // example, YYYY-MM-DDTHH:MM:SSZ). You can use wildcards (* and ?). Greater + // than or less than comparison is not supported. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // Filters the results by the specified instance types. + InstanceTypes []*string `locationName:"InstanceType" type:"list"` + + // The maximum number of results to return in a single call. Specify a value + // between 1 and 1000. The default value is 1000. To retrieve the remaining + // results, make another call with the returned NextToken value. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token for the next set of results. + NextToken *string `locationName:"nextToken" type:"string"` + + // Filters the results by the specified basic product descriptions. + ProductDescriptions []*string `locationName:"ProductDescription" type:"list"` + + // The date and time, up to the past 90 days, from which to start retrieving + // the price history data, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s DescribeSpotPriceHistoryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotPriceHistoryInput) GoString() string { + return s.String() +} + +// Contains the output of DescribeSpotPriceHistory. +type DescribeSpotPriceHistoryOutput struct { + _ struct{} `type:"structure"` + + // The token required to retrieve the next set of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // The historical Spot prices. + SpotPriceHistory []*SpotPrice `locationName:"spotPriceHistorySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSpotPriceHistoryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSpotPriceHistoryOutput) GoString() string { + return s.String() +} + +type DescribeSubnetsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // availabilityZone - The Availability Zone for the subnet. You can also + // use availability-zone as the filter name. + // + // available-ip-address-count - The number of IP addresses in the subnet + // that are available. + // + // cidrBlock - The CIDR block of the subnet. The CIDR block you specify must + // exactly match the subnet's CIDR block for information to be returned for + // the subnet. You can also use cidr or cidr-block as the filter names. + // + // defaultForAz - Indicates whether this is the default subnet for the Availability + // Zone. You can also use default-for-az as the filter name. + // + // state - The state of the subnet (pending | available). + // + // subnet-id - The ID of the subnet. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC for the subnet. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more subnet IDs. + // + // Default: Describes all your subnets. + SubnetIds []*string `locationName:"SubnetId" locationNameList:"SubnetId" type:"list"` +} + +// String returns the string representation +func (s DescribeSubnetsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSubnetsInput) GoString() string { + return s.String() +} + +type DescribeSubnetsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more subnets. + Subnets []*Subnet `locationName:"subnetSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeSubnetsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeSubnetsOutput) GoString() string { + return s.String() +} + +type DescribeTagsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // key - The tag key. + // + // resource-id - The resource ID. + // + // resource-type - The resource type (customer-gateway | dhcp-options | image + // | instance | internet-gateway | network-acl | network-interface | reserved-instances + // | route-table | security-group | snapshot | spot-instances-request | subnet + // | volume | vpc | vpn-connection | vpn-gateway). + // + // value - The tag value. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of results to return for the request in a single page. + // The remaining results of the initial request can be seen by sending another + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The token to retrieve the next page of results. + NextToken *string `locationName:"nextToken" type:"string"` +} + +// String returns the string representation +func (s DescribeTagsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTagsInput) GoString() string { + return s.String() +} + +type DescribeTagsOutput struct { + _ struct{} `type:"structure"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return.. + NextToken *string `locationName:"nextToken" type:"string"` + + // A list of tags. + Tags []*TagDescription `locationName:"tagSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeTagsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTagsOutput) GoString() string { + return s.String() +} + +type DescribeVolumeAttributeInput struct { + _ struct{} `type:"structure"` + + // The instance attribute. + Attribute *string `type:"string" enum:"VolumeAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the volume. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeVolumeAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumeAttributeInput) GoString() string { + return s.String() +} + +type DescribeVolumeAttributeOutput struct { + _ struct{} `type:"structure"` + + // The state of autoEnableIO attribute. + AutoEnableIO *AttributeBooleanValue `locationName:"autoEnableIO" type:"structure"` + + // A list of product codes. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // The ID of the volume. + VolumeId *string `locationName:"volumeId" type:"string"` +} + +// String returns the string representation +func (s DescribeVolumeAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumeAttributeOutput) GoString() string { + return s.String() +} + +type DescribeVolumeStatusInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // action.code - The action code for the event (for example, enable-volume-io). + // + // action.description - A description of the action. + // + // action.event-id - The event ID associated with the action. + // + // availability-zone - The Availability Zone of the instance. + // + // event.description - A description of the event. + // + // event.event-id - The event ID. + // + // event.event-type - The event type (for io-enabled: passed | failed; for + // io-performance: io-performance:degraded | io-performance:severely-degraded + // | io-performance:stalled). + // + // event.not-after - The latest end time for the event. + // + // event.not-before - The earliest start time for the event. + // + // volume-status.details-name - The cause for volume-status.status (io-enabled + // | io-performance). + // + // volume-status.details-status - The status of volume-status.details-name + // (for io-enabled: passed | failed; for io-performance: normal | degraded | + // severely-degraded | stalled). + // + // volume-status.status - The status of the volume (ok | impaired | warning + // | insufficient-data). + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of volume results returned by DescribeVolumeStatus in + // paginated output. When this parameter is used, the request only returns MaxResults + // results in a single page along with a NextToken response element. The remaining + // results of the initial request can be seen by sending another request with + // the returned NextToken value. This value can be between 5 and 1000; if MaxResults + // is given a value larger than 1000, only 1000 results are returned. If this + // parameter is not used, then DescribeVolumeStatus returns all results. You + // cannot specify this parameter and the volume IDs parameter in the same request. + MaxResults *int64 `type:"integer"` + + // The NextToken value to include in a future DescribeVolumeStatus request. + // When the results of the request exceed MaxResults, this value can be used + // to retrieve the next page of results. This value is null when there are no + // more results to return. + NextToken *string `type:"string"` + + // One or more volume IDs. + // + // Default: Describes all your volumes. + VolumeIds []*string `locationName:"VolumeId" locationNameList:"VolumeId" type:"list"` +} + +// String returns the string representation +func (s DescribeVolumeStatusInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumeStatusInput) GoString() string { + return s.String() +} + +type DescribeVolumeStatusOutput struct { + _ struct{} `type:"structure"` + + // The token to use to retrieve the next page of results. This value is null + // when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // A list of volumes. + VolumeStatuses []*VolumeStatusItem `locationName:"volumeStatusSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVolumeStatusOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumeStatusOutput) GoString() string { + return s.String() +} + +type DescribeVolumesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // attachment.attach-time - The time stamp when the attachment initiated. + // + // attachment.delete-on-termination - Whether the volume is deleted on instance + // termination. + // + // attachment.device - The device name that is exposed to the instance (for + // example, /dev/sda1). + // + // attachment.instance-id - The ID of the instance the volume is attached + // to. + // + // attachment.status - The attachment state (attaching | attached | detaching + // | detached). + // + // availability-zone - The Availability Zone in which the volume was created. + // + // create-time - The time stamp when the volume was created. + // + // encrypted - The encryption status of the volume. + // + // size - The size of the volume, in GiB. + // + // snapshot-id - The snapshot from which the volume was created. + // + // status - The status of the volume (creating | available | in-use | deleting + // | deleted | error). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // volume-id - The volume ID. + // + // volume-type - The Amazon EBS volume type. This can be gp2 for General + // Purpose (SSD) volumes, io1 for Provisioned IOPS (SSD) volumes, or standard + // for Magnetic volumes. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of volume results returned by DescribeVolumes in paginated + // output. When this parameter is used, DescribeVolumes only returns MaxResults + // results in a single page along with a NextToken response element. The remaining + // results of the initial request can be seen by sending another DescribeVolumes + // request with the returned NextToken value. This value can be between 5 and + // 1000; if MaxResults is given a value larger than 1000, only 1000 results + // are returned. If this parameter is not used, then DescribeVolumes returns + // all results. You cannot specify this parameter and the volume IDs parameter + // in the same request. + MaxResults *int64 `locationName:"maxResults" type:"integer"` + + // The NextToken value returned from a previous paginated DescribeVolumes request + // where MaxResults was used and the results exceeded the value of that parameter. + // Pagination continues from the end of the previous results that returned the + // NextToken value. This value is null when there are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // One or more volume IDs. + VolumeIds []*string `locationName:"VolumeId" locationNameList:"VolumeId" type:"list"` +} + +// String returns the string representation +func (s DescribeVolumesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumesInput) GoString() string { + return s.String() +} + +type DescribeVolumesOutput struct { + _ struct{} `type:"structure"` + + // The NextToken value to include in a future DescribeVolumes request. When + // the results of a DescribeVolumes request exceed MaxResults, this value can + // be used to retrieve the next page of results. This value is null when there + // are no more results to return. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the volumes. + Volumes []*Volume `locationName:"volumeSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVolumesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVolumesOutput) GoString() string { + return s.String() +} + +type DescribeVpcAttributeInput struct { + _ struct{} `type:"structure"` + + // The VPC attribute. + Attribute *string `type:"string" required:"true" enum:"VpcAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeVpcAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcAttributeInput) GoString() string { + return s.String() +} + +type DescribeVpcAttributeOutput struct { + _ struct{} `type:"structure"` + + // Indicates whether the instances launched in the VPC get DNS hostnames. If + // this attribute is true, instances in the VPC get DNS hostnames; otherwise, + // they do not. + EnableDnsHostnames *AttributeBooleanValue `locationName:"enableDnsHostnames" type:"structure"` + + // Indicates whether DNS resolution is enabled for the VPC. If this attribute + // is true, the Amazon DNS server resolves DNS hostnames for your instances + // to their corresponding IP addresses; otherwise, it does not. + EnableDnsSupport *AttributeBooleanValue `locationName:"enableDnsSupport" type:"structure"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s DescribeVpcAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcAttributeOutput) GoString() string { + return s.String() +} + +type DescribeVpcClassicLinkDnsSupportInput struct { + _ struct{} `type:"structure"` + + // The maximum number of items to return for this request. The request returns + // a token that you can specify in a subsequent call to get the next set of + // results. + MaxResults *int64 `locationName:"maxResults" min:"5" type:"integer"` + + // The token for the next set of items to return. (You received this token from + // a prior call.) + NextToken *string `locationName:"nextToken" min:"1" type:"string"` + + // One or more VPC IDs. + VpcIds []*string `locationNameList:"VpcId" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcClassicLinkDnsSupportInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcClassicLinkDnsSupportInput) GoString() string { + return s.String() +} + +type DescribeVpcClassicLinkDnsSupportOutput struct { + _ struct{} `type:"structure"` + + // The token to use when requesting the next set of items. + NextToken *string `locationName:"nextToken" min:"1" type:"string"` + + // Information about the ClassicLink DNS support status of the VPCs. + Vpcs []*ClassicLinkDnsSupport `locationName:"vpcs" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcClassicLinkDnsSupportOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcClassicLinkDnsSupportOutput) GoString() string { + return s.String() +} + +type DescribeVpcClassicLinkInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // is-classic-link-enabled - Whether the VPC is enabled for ClassicLink (true + // | false). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more VPCs for which you want to describe the ClassicLink status. + VpcIds []*string `locationName:"VpcId" locationNameList:"VpcId" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcClassicLinkInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcClassicLinkInput) GoString() string { + return s.String() +} + +type DescribeVpcClassicLinkOutput struct { + _ struct{} `type:"structure"` + + // The ClassicLink status of one or more VPCs. + Vpcs []*VpcClassicLink `locationName:"vpcSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcClassicLinkOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcClassicLinkOutput) GoString() string { + return s.String() +} + +type DescribeVpcEndpointServicesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // The maximum number of items to return for this request. The request returns + // a token that you can specify in a subsequent call to get the next set of + // results. + // + // Constraint: If the value is greater than 1000, we return only 1000 items. + MaxResults *int64 `type:"integer"` + + // The token for the next set of items to return. (You received this token from + // a prior call.) + NextToken *string `type:"string"` +} + +// String returns the string representation +func (s DescribeVpcEndpointServicesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcEndpointServicesInput) GoString() string { + return s.String() +} + +type DescribeVpcEndpointServicesOutput struct { + _ struct{} `type:"structure"` + + // The token to use when requesting the next set of items. If there are no additional + // items to return, the string is empty. + NextToken *string `locationName:"nextToken" type:"string"` + + // A list of supported AWS services. + ServiceNames []*string `locationName:"serviceNameSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcEndpointServicesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcEndpointServicesOutput) GoString() string { + return s.String() +} + +type DescribeVpcEndpointsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more filters. + // + // service-name: The name of the AWS service. + // + // vpc-id: The ID of the VPC in which the endpoint resides. + // + // vpc-endpoint-id: The ID of the endpoint. + // + // vpc-endpoint-state: The state of the endpoint. (pending | available | + // deleting | deleted) + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // The maximum number of items to return for this request. The request returns + // a token that you can specify in a subsequent call to get the next set of + // results. + // + // Constraint: If the value is greater than 1000, we return only 1000 items. + MaxResults *int64 `type:"integer"` + + // The token for the next set of items to return. (You received this token from + // a prior call.) + NextToken *string `type:"string"` + + // One or more endpoint IDs. + VpcEndpointIds []*string `locationName:"VpcEndpointId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcEndpointsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcEndpointsInput) GoString() string { + return s.String() +} + +type DescribeVpcEndpointsOutput struct { + _ struct{} `type:"structure"` + + // The token to use when requesting the next set of items. If there are no additional + // items to return, the string is empty. + NextToken *string `locationName:"nextToken" type:"string"` + + // Information about the endpoints. + VpcEndpoints []*VpcEndpoint `locationName:"vpcEndpointSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcEndpointsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcEndpointsOutput) GoString() string { + return s.String() +} + +type DescribeVpcPeeringConnectionsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // accepter-vpc-info.cidr-block - The CIDR block of the peer VPC. + // + // accepter-vpc-info.owner-id - The AWS account ID of the owner of the peer + // VPC. + // + // accepter-vpc-info.vpc-id - The ID of the peer VPC. + // + // expiration-time - The expiration date and time for the VPC peering connection. + // + // requester-vpc-info.cidr-block - The CIDR block of the requester's VPC. + // + // requester-vpc-info.owner-id - The AWS account ID of the owner of the requester + // VPC. + // + // requester-vpc-info.vpc-id - The ID of the requester VPC. + // + // status-code - The status of the VPC peering connection (pending-acceptance + // | failed | expired | provisioning | active | deleted | rejected). + // + // status-message - A message that provides more information about the status + // of the VPC peering connection, if applicable. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-peering-connection-id - The ID of the VPC peering connection. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more VPC peering connection IDs. + // + // Default: Describes all your VPC peering connections. + VpcPeeringConnectionIds []*string `locationName:"VpcPeeringConnectionId" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcPeeringConnectionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcPeeringConnectionsInput) GoString() string { + return s.String() +} + +type DescribeVpcPeeringConnectionsOutput struct { + _ struct{} `type:"structure"` + + // Information about the VPC peering connections. + VpcPeeringConnections []*VpcPeeringConnection `locationName:"vpcPeeringConnectionSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcPeeringConnectionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcPeeringConnectionsOutput) GoString() string { + return s.String() +} + +type DescribeVpcsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // cidr - The CIDR block of the VPC. The CIDR block you specify must exactly + // match the VPC's CIDR block for information to be returned for the VPC. Must + // contain the slash followed by one or two digits (for example, /28). + // + // dhcp-options-id - The ID of a set of DHCP options. + // + // isDefault - Indicates whether the VPC is the default VPC. + // + // state - The state of the VPC (pending | available). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // vpc-id - The ID of the VPC. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more VPC IDs. + // + // Default: Describes all your VPCs. + VpcIds []*string `locationName:"VpcId" locationNameList:"VpcId" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcsInput) GoString() string { + return s.String() +} + +type DescribeVpcsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more VPCs. + Vpcs []*Vpc `locationName:"vpcSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpcsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpcsOutput) GoString() string { + return s.String() +} + +type DescribeVpnConnectionsInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // customer-gateway-configuration - The configuration information for the + // customer gateway. + // + // customer-gateway-id - The ID of a customer gateway associated with the + // VPN connection. + // + // state - The state of the VPN connection (pending | available | deleting + // | deleted). + // + // option.static-routes-only - Indicates whether the connection has static + // routes only. Used for devices that do not support Border Gateway Protocol + // (BGP). + // + // route.destination-cidr-block - The destination CIDR block. This corresponds + // to the subnet used in a customer data center. + // + // bgp-asn - The BGP Autonomous System Number (ASN) associated with a BGP + // device. + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // type - The type of VPN connection. Currently the only supported type is + // ipsec.1. + // + // vpn-connection-id - The ID of the VPN connection. + // + // vpn-gateway-id - The ID of a virtual private gateway associated with the + // VPN connection. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more VPN connection IDs. + // + // Default: Describes your VPN connections. + VpnConnectionIds []*string `locationName:"VpnConnectionId" locationNameList:"VpnConnectionId" type:"list"` +} + +// String returns the string representation +func (s DescribeVpnConnectionsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpnConnectionsInput) GoString() string { + return s.String() +} + +type DescribeVpnConnectionsOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more VPN connections. + VpnConnections []*VpnConnection `locationName:"vpnConnectionSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpnConnectionsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpnConnectionsOutput) GoString() string { + return s.String() +} + +type DescribeVpnGatewaysInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more filters. + // + // attachment.state - The current state of the attachment between the gateway + // and the VPC (attaching | attached | detaching | detached). + // + // attachment.vpc-id - The ID of an attached VPC. + // + // availability-zone - The Availability Zone for the virtual private gateway + // (if applicable). + // + // state - The state of the virtual private gateway (pending | available + // | deleting | deleted). + // + // tag:key=value - The key/value combination of a tag assigned to the resource. + // + // tag-key - The key of a tag assigned to the resource. This filter is independent + // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" + // and the filter "tag-value=X", you get any resources assigned both the tag + // key Purpose (regardless of what the tag's value is), and the tag value X + // (regardless of what the tag's key is). If you want to list only resources + // where Purpose is X, see the tag:key=value filter. + // + // tag-value - The value of a tag assigned to the resource. This filter is + // independent of the tag-key filter. + // + // type - The type of virtual private gateway. Currently the only supported + // type is ipsec.1. + // + // vpn-gateway-id - The ID of the virtual private gateway. + Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` + + // One or more virtual private gateway IDs. + // + // Default: Describes all your virtual private gateways. + VpnGatewayIds []*string `locationName:"VpnGatewayId" locationNameList:"VpnGatewayId" type:"list"` +} + +// String returns the string representation +func (s DescribeVpnGatewaysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpnGatewaysInput) GoString() string { + return s.String() +} + +type DescribeVpnGatewaysOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more virtual private gateways. + VpnGateways []*VpnGateway `locationName:"vpnGatewaySet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DescribeVpnGatewaysOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeVpnGatewaysOutput) GoString() string { + return s.String() +} + +type DetachClassicLinkVpcInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance to unlink from the VPC. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // The ID of the VPC to which the instance is linked. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DetachClassicLinkVpcInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachClassicLinkVpcInput) GoString() string { + return s.String() +} + +type DetachClassicLinkVpcOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s DetachClassicLinkVpcOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachClassicLinkVpcOutput) GoString() string { + return s.String() +} + +type DetachInternetGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the Internet gateway. + InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DetachInternetGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachInternetGatewayInput) GoString() string { + return s.String() +} + +type DetachInternetGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DetachInternetGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachInternetGatewayOutput) GoString() string { + return s.String() +} + +type DetachNetworkInterfaceInput struct { + _ struct{} `type:"structure"` + + // The ID of the attachment. + AttachmentId *string `locationName:"attachmentId" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Specifies whether to force a detachment. + Force *bool `locationName:"force" type:"boolean"` +} + +// String returns the string representation +func (s DetachNetworkInterfaceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachNetworkInterfaceInput) GoString() string { + return s.String() +} + +type DetachNetworkInterfaceOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DetachNetworkInterfaceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachNetworkInterfaceOutput) GoString() string { + return s.String() +} + +type DetachVolumeInput struct { + _ struct{} `type:"structure"` + + // The device name. + Device *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Forces detachment if the previous detachment attempt did not occur cleanly + // (for example, logging into an instance, unmounting the volume, and detaching + // normally). This option can lead to data loss or a corrupted file system. + // Use this option only as a last resort to detach a volume from a failed instance. + // The instance won't have an opportunity to flush file system caches or file + // system metadata. If you use this option, you must perform file system check + // and repair procedures. + Force *bool `type:"boolean"` + + // The ID of the instance. + InstanceId *string `type:"string"` + + // The ID of the volume. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DetachVolumeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachVolumeInput) GoString() string { + return s.String() +} + +type DetachVpnGatewayInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `type:"string" required:"true"` + + // The ID of the virtual private gateway. + VpnGatewayId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DetachVpnGatewayInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachVpnGatewayInput) GoString() string { + return s.String() +} + +type DetachVpnGatewayOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DetachVpnGatewayOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DetachVpnGatewayOutput) GoString() string { + return s.String() +} + +// Describes a DHCP configuration option. +type DhcpConfiguration struct { + _ struct{} `type:"structure"` + + // The name of a DHCP option. + Key *string `locationName:"key" type:"string"` + + // One or more values for the DHCP option. + Values []*AttributeValue `locationName:"valueSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DhcpConfiguration) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DhcpConfiguration) GoString() string { + return s.String() +} + +// Describes a set of DHCP options. +type DhcpOptions struct { + _ struct{} `type:"structure"` + + // One or more DHCP options in the set. + DhcpConfigurations []*DhcpConfiguration `locationName:"dhcpConfigurationSet" locationNameList:"item" type:"list"` + + // The ID of the set of DHCP options. + DhcpOptionsId *string `locationName:"dhcpOptionsId" type:"string"` + + // Any tags assigned to the DHCP options set. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s DhcpOptions) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DhcpOptions) GoString() string { + return s.String() +} + +type DisableVgwRoutePropagationInput struct { + _ struct{} `type:"structure"` + + // The ID of the virtual private gateway. + GatewayId *string `type:"string" required:"true"` + + // The ID of the route table. + RouteTableId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DisableVgwRoutePropagationInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVgwRoutePropagationInput) GoString() string { + return s.String() +} + +type DisableVgwRoutePropagationOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DisableVgwRoutePropagationOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVgwRoutePropagationOutput) GoString() string { + return s.String() +} + +type DisableVpcClassicLinkDnsSupportInput struct { + _ struct{} `type:"structure"` + + // The ID of the VPC. + VpcId *string `type:"string"` +} + +// String returns the string representation +func (s DisableVpcClassicLinkDnsSupportInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVpcClassicLinkDnsSupportInput) GoString() string { + return s.String() +} + +type DisableVpcClassicLinkDnsSupportOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s DisableVpcClassicLinkDnsSupportOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVpcClassicLinkDnsSupportOutput) GoString() string { + return s.String() +} + +type DisableVpcClassicLinkInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s DisableVpcClassicLinkInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVpcClassicLinkInput) GoString() string { + return s.String() +} + +type DisableVpcClassicLinkOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s DisableVpcClassicLinkOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisableVpcClassicLinkOutput) GoString() string { + return s.String() +} + +type DisassociateAddressInput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] The association ID. Required for EC2-VPC. + AssociationId *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // [EC2-Classic] The Elastic IP address. Required for EC2-Classic. + PublicIp *string `type:"string"` +} + +// String returns the string representation +func (s DisassociateAddressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisassociateAddressInput) GoString() string { + return s.String() +} + +type DisassociateAddressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DisassociateAddressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisassociateAddressOutput) GoString() string { + return s.String() +} + +type DisassociateRouteTableInput struct { + _ struct{} `type:"structure"` + + // The association ID representing the current association between the route + // table and subnet. + AssociationId *string `locationName:"associationId" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` +} + +// String returns the string representation +func (s DisassociateRouteTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisassociateRouteTableInput) GoString() string { + return s.String() +} + +type DisassociateRouteTableOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DisassociateRouteTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DisassociateRouteTableOutput) GoString() string { + return s.String() +} + +// Describes a disk image. +type DiskImage struct { + _ struct{} `type:"structure"` + + // A description of the disk image. + Description *string `type:"string"` + + // Information about the disk image. + Image *DiskImageDetail `type:"structure"` + + // Information about the volume. + Volume *VolumeDetail `type:"structure"` +} + +// String returns the string representation +func (s DiskImage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DiskImage) GoString() string { + return s.String() +} + +// Describes a disk image. +type DiskImageDescription struct { + _ struct{} `type:"structure"` + + // The checksum computed for the disk image. + Checksum *string `locationName:"checksum" type:"string"` + + // The disk image format. + Format *string `locationName:"format" type:"string" required:"true" enum:"DiskImageFormat"` + + // A presigned URL for the import manifest stored in Amazon S3. For information + // about creating a presigned URL for an Amazon S3 object, read the "Query String + // Request Authentication Alternative" section of the Authenticating REST Requests + // (http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) + // topic in the Amazon Simple Storage Service Developer Guide. + ImportManifestUrl *string `locationName:"importManifestUrl" type:"string" required:"true"` + + // The size of the disk image, in GiB. + Size *int64 `locationName:"size" type:"long" required:"true"` +} + +// String returns the string representation +func (s DiskImageDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DiskImageDescription) GoString() string { + return s.String() +} + +// Describes a disk image. +type DiskImageDetail struct { + _ struct{} `type:"structure"` + + // The size of the disk image, in GiB. + Bytes *int64 `locationName:"bytes" type:"long" required:"true"` + + // The disk image format. + Format *string `locationName:"format" type:"string" required:"true" enum:"DiskImageFormat"` + + // A presigned URL for the import manifest stored in Amazon S3 and presented + // here as an Amazon S3 presigned URL. For information about creating a presigned + // URL for an Amazon S3 object, read the "Query String Request Authentication + // Alternative" section of the Authenticating REST Requests (http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) + // topic in the Amazon Simple Storage Service Developer Guide. + ImportManifestUrl *string `locationName:"importManifestUrl" type:"string" required:"true"` +} + +// String returns the string representation +func (s DiskImageDetail) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DiskImageDetail) GoString() string { + return s.String() +} + +// Describes a disk image volume. +type DiskImageVolumeDescription struct { + _ struct{} `type:"structure"` + + // The volume identifier. + Id *string `locationName:"id" type:"string" required:"true"` + + // The size of the volume, in GiB. + Size *int64 `locationName:"size" type:"long"` +} + +// String returns the string representation +func (s DiskImageVolumeDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DiskImageVolumeDescription) GoString() string { + return s.String() +} + +// Describes a block device for an EBS volume. +type EbsBlockDevice struct { + _ struct{} `type:"structure"` + + // Indicates whether the EBS volume is deleted on instance termination. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // Indicates whether the EBS volume is encrypted. Encrypted Amazon EBS volumes + // may only be attached to instances that support Amazon EBS encryption. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // The number of I/O operations per second (IOPS) that the volume supports. + // For Provisioned IOPS (SSD) volumes, this represents the number of IOPS that + // are provisioned for the volume. For General Purpose (SSD) volumes, this represents + // the baseline performance of the volume and the rate at which the volume accumulates + // I/O credits for bursting. For more information on General Purpose (SSD) baseline + // performance, I/O credits, and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes and + // 3 to 10000 for General Purpose (SSD) volumes. + // + // Condition: This parameter is required for requests to create io1 volumes; + // it is not used in requests to create standard or gp2 volumes. + Iops *int64 `locationName:"iops" type:"integer"` + + // The ID of the snapshot. + SnapshotId *string `locationName:"snapshotId" type:"string"` + + // The size of the volume, in GiB. + // + // Constraints: 1-1024 for standard volumes, 1-16384 for gp2 volumes, and 4-16384 + // for io1 volumes. If you specify a snapshot, the volume size must be equal + // to or larger than the snapshot size. + // + // Default: If you're creating the volume from a snapshot and don't specify + // a volume size, the default is the snapshot size. + VolumeSize *int64 `locationName:"volumeSize" type:"integer"` + + // The volume type. gp2 for General Purpose (SSD) volumes, io1 for Provisioned + // IOPS (SSD) volumes, and standard for Magnetic volumes. + // + // Default: standard + VolumeType *string `locationName:"volumeType" type:"string" enum:"VolumeType"` +} + +// String returns the string representation +func (s EbsBlockDevice) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EbsBlockDevice) GoString() string { + return s.String() +} + +// Describes a parameter used to set up an EBS volume in a block device mapping. +type EbsInstanceBlockDevice struct { + _ struct{} `type:"structure"` + + // The time stamp when the attachment initiated. + AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` + + // Indicates whether the volume is deleted on instance termination. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The attachment state. + Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` + + // The ID of the EBS volume. + VolumeId *string `locationName:"volumeId" type:"string"` +} + +// String returns the string representation +func (s EbsInstanceBlockDevice) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EbsInstanceBlockDevice) GoString() string { + return s.String() +} + +type EbsInstanceBlockDeviceSpecification struct { + _ struct{} `type:"structure"` + + // Indicates whether the volume is deleted on instance termination. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The ID of the EBS volume. + VolumeId *string `locationName:"volumeId" type:"string"` +} + +// String returns the string representation +func (s EbsInstanceBlockDeviceSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EbsInstanceBlockDeviceSpecification) GoString() string { + return s.String() +} + +type EnableVgwRoutePropagationInput struct { + _ struct{} `type:"structure"` + + // The ID of the virtual private gateway. + GatewayId *string `type:"string" required:"true"` + + // The ID of the route table. + RouteTableId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s EnableVgwRoutePropagationInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVgwRoutePropagationInput) GoString() string { + return s.String() +} + +type EnableVgwRoutePropagationOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s EnableVgwRoutePropagationOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVgwRoutePropagationOutput) GoString() string { + return s.String() +} + +type EnableVolumeIOInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the volume. + VolumeId *string `locationName:"volumeId" type:"string" required:"true"` +} + +// String returns the string representation +func (s EnableVolumeIOInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVolumeIOInput) GoString() string { + return s.String() +} + +type EnableVolumeIOOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s EnableVolumeIOOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVolumeIOOutput) GoString() string { + return s.String() +} + +type EnableVpcClassicLinkDnsSupportInput struct { + _ struct{} `type:"structure"` + + // The ID of the VPC. + VpcId *string `type:"string"` +} + +// String returns the string representation +func (s EnableVpcClassicLinkDnsSupportInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVpcClassicLinkDnsSupportInput) GoString() string { + return s.String() +} + +type EnableVpcClassicLinkDnsSupportOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s EnableVpcClassicLinkDnsSupportOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVpcClassicLinkDnsSupportOutput) GoString() string { + return s.String() +} + +type EnableVpcClassicLinkInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s EnableVpcClassicLinkInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVpcClassicLinkInput) GoString() string { + return s.String() +} + +type EnableVpcClassicLinkOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s EnableVpcClassicLinkOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EnableVpcClassicLinkOutput) GoString() string { + return s.String() +} + +// Describes a Spot fleet event. +type EventInformation struct { + _ struct{} `type:"structure"` + + // The description of the event. + EventDescription *string `locationName:"eventDescription" type:"string"` + + // The event. + // + // The following are the error events. + // + // iamFleetRoleInvalid - The Spot fleet did not have the required permissions + // either to launch or terminate an instance. + // + // launchSpecTemporarilyBlacklisted - The configuration is not valid and + // several attempts to launch instances have failed. For more information, see + // the description of the event. + // + // spotFleetRequestConfigurationInvalid - The configuration is not valid. + // For more information, see the description of the event. + // + // spotInstanceCountLimitExceeded - You've reached the limit on the number + // of Spot instances that you can launch. + // + // The following are the fleetRequestChange events. + // + // active - The Spot fleet has been validated and Amazon EC2 is attempting + // to maintain the target number of running Spot instances. + // + // cancelled - The Spot fleet is canceled and has no running Spot instances. + // The Spot fleet will be deleted two days after its instances were terminated. + // + // cancelled_running - The Spot fleet is canceled and will not launch additional + // Spot instances, but its existing Spot instances continue to run until they + // are interrupted or terminated. + // + // cancelled_terminating - The Spot fleet is canceled and its Spot instances + // are terminating. + // + // expired - The Spot fleet request has expired. A subsequent event indicates + // that the instances were terminated, if the request was created with TerminateInstancesWithExpiration + // set. + // + // modify_in_progress - A request to modify the Spot fleet request was accepted + // and is in progress. + // + // modify_successful - The Spot fleet request was modified. + // + // price_update - The bid price for a launch configuration was adjusted because + // it was too high. This change is permanent. + // + // submitted - The Spot fleet request is being evaluated and Amazon EC2 is + // preparing to launch the target number of Spot instances. + // + // The following are the instanceChange events. + // + // launched - A bid was fulfilled and a new instance was launched. + // + // terminated - An instance was terminated by the user. + EventSubType *string `locationName:"eventSubType" type:"string"` + + // The ID of the instance. This information is available only for instanceChange + // events. + InstanceId *string `locationName:"instanceId" type:"string"` +} + +// String returns the string representation +func (s EventInformation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s EventInformation) GoString() string { + return s.String() +} + +// Describes an instance export task. +type ExportTask struct { + _ struct{} `type:"structure"` + + // A description of the resource being exported. + Description *string `locationName:"description" type:"string"` + + // The ID of the export task. + ExportTaskId *string `locationName:"exportTaskId" type:"string"` + + // Information about the export task. + ExportToS3Task *ExportToS3Task `locationName:"exportToS3" type:"structure"` + + // Information about the instance to export. + InstanceExportDetails *InstanceExportDetails `locationName:"instanceExport" type:"structure"` + + // The state of the export task. + State *string `locationName:"state" type:"string" enum:"ExportTaskState"` + + // The status message related to the export task. + StatusMessage *string `locationName:"statusMessage" type:"string"` +} + +// String returns the string representation +func (s ExportTask) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ExportTask) GoString() string { + return s.String() +} + +// Describes the format and location for an instance export task. +type ExportToS3Task struct { + _ struct{} `type:"structure"` + + // The container format used to combine disk images with metadata (such as OVF). + // If absent, only the disk image is exported. + ContainerFormat *string `locationName:"containerFormat" type:"string" enum:"ContainerFormat"` + + // The format for the exported image. + DiskImageFormat *string `locationName:"diskImageFormat" type:"string" enum:"DiskImageFormat"` + + // The S3 bucket for the destination image. The destination bucket must exist + // and grant WRITE and READ_ACP permissions to the AWS account vm-import-export@amazon.com. + S3Bucket *string `locationName:"s3Bucket" type:"string"` + + // The encryption key for your S3 bucket. + S3Key *string `locationName:"s3Key" type:"string"` +} + +// String returns the string representation +func (s ExportToS3Task) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ExportToS3Task) GoString() string { + return s.String() +} + +// Describes an instance export task. +type ExportToS3TaskSpecification struct { + _ struct{} `type:"structure"` + + // The container format used to combine disk images with metadata (such as OVF). + // If absent, only the disk image is exported. + ContainerFormat *string `locationName:"containerFormat" type:"string" enum:"ContainerFormat"` + + // The format for the exported image. + DiskImageFormat *string `locationName:"diskImageFormat" type:"string" enum:"DiskImageFormat"` + + // The S3 bucket for the destination image. The destination bucket must exist + // and grant WRITE and READ_ACP permissions to the AWS account vm-import-export@amazon.com. + S3Bucket *string `locationName:"s3Bucket" type:"string"` + + // The image is written to a single object in the S3 bucket at the S3 key s3prefix + // + exportTaskId + '.' + diskImageFormat. + S3Prefix *string `locationName:"s3Prefix" type:"string"` +} + +// String returns the string representation +func (s ExportToS3TaskSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ExportToS3TaskSpecification) GoString() string { + return s.String() +} + +// A filter name and value pair that is used to return a more specific list +// of results. Filters can be used to match a set of resources by various criteria, +// such as tags, attributes, or IDs. +type Filter struct { + _ struct{} `type:"structure"` + + // The name of the filter. Filter names are case-sensitive. + Name *string `type:"string"` + + // One or more filter values. Filter values are case-sensitive. + Values []*string `locationName:"Value" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s Filter) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Filter) GoString() string { + return s.String() +} + +// Describes a flow log. +type FlowLog struct { + _ struct{} `type:"structure"` + + // The date and time the flow log was created. + CreationTime *time.Time `locationName:"creationTime" type:"timestamp" timestampFormat:"iso8601"` + + // Information about the error that occurred. Rate limited indicates that CloudWatch + // logs throttling has been applied for one or more network interfaces, or that + // you've reached the limit on the number of CloudWatch Logs log groups that + // you can create. Access error indicates that the IAM role associated with + // the flow log does not have sufficient permissions to publish to CloudWatch + // Logs. Unknown error indicates an internal error. + DeliverLogsErrorMessage *string `locationName:"deliverLogsErrorMessage" type:"string"` + + // The ARN of the IAM role that posts logs to CloudWatch Logs. + DeliverLogsPermissionArn *string `locationName:"deliverLogsPermissionArn" type:"string"` + + // The status of the logs delivery (SUCCESS | FAILED). + DeliverLogsStatus *string `locationName:"deliverLogsStatus" type:"string"` + + // The flow log ID. + FlowLogId *string `locationName:"flowLogId" type:"string"` + + // The status of the flow log (ACTIVE). + FlowLogStatus *string `locationName:"flowLogStatus" type:"string"` + + // The name of the flow log group. + LogGroupName *string `locationName:"logGroupName" type:"string"` + + // The ID of the resource on which the flow log was created. + ResourceId *string `locationName:"resourceId" type:"string"` + + // The type of traffic captured for the flow log. + TrafficType *string `locationName:"trafficType" type:"string" enum:"TrafficType"` +} + +// String returns the string representation +func (s FlowLog) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s FlowLog) GoString() string { + return s.String() +} + +type GetConsoleOutputInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s GetConsoleOutputInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetConsoleOutputInput) GoString() string { + return s.String() +} + +type GetConsoleOutputOutput struct { + _ struct{} `type:"structure"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The console output, Base64 encoded. If using a command line tool, the tools + // decode the output for you. + Output *string `locationName:"output" type:"string"` + + // The time the output was last updated. + Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s GetConsoleOutputOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetConsoleOutputOutput) GoString() string { + return s.String() +} + +type GetPasswordDataInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the Windows instance. + InstanceId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s GetPasswordDataInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetPasswordDataInput) GoString() string { + return s.String() +} + +type GetPasswordDataOutput struct { + _ struct{} `type:"structure"` + + // The ID of the Windows instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The password of the instance. + PasswordData *string `locationName:"passwordData" type:"string"` + + // The time the data was last updated. + Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s GetPasswordDataOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetPasswordDataOutput) GoString() string { + return s.String() +} + +// Describes a security group. +type GroupIdentifier struct { + _ struct{} `type:"structure"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string"` + + // The name of the security group. + GroupName *string `locationName:"groupName" type:"string"` +} + +// String returns the string representation +func (s GroupIdentifier) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GroupIdentifier) GoString() string { + return s.String() +} + +// Describes an event in the history of the Spot fleet request. +type HistoryRecord struct { + _ struct{} `type:"structure"` + + // Information about the event. + EventInformation *EventInformation `locationName:"eventInformation" type:"structure" required:"true"` + + // The event type. + // + // error - Indicates an error with the Spot fleet request. + // + // fleetRequestChange - Indicates a change in the status or configuration + // of the Spot fleet request. + // + // instanceChange - Indicates that an instance was launched or terminated. + EventType *string `locationName:"eventType" type:"string" required:"true" enum:"EventType"` + + // The date and time of the event, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601" required:"true"` +} + +// String returns the string representation +func (s HistoryRecord) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s HistoryRecord) GoString() string { + return s.String() +} + +// Describes the properties of the Dedicated host. +type Host struct { + _ struct{} `type:"structure"` + + // Whether auto-placement is on or off. + AutoPlacement *string `locationName:"autoPlacement" type:"string" enum:"AutoPlacement"` + + // The Availability Zone of the Dedicated host. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The number of new instances that can be launched onto the Dedicated host. + AvailableCapacity *AvailableCapacity `locationName:"availableCapacity" type:"structure"` + + // Unique, case-sensitive identifier you provide to ensure idempotency of the + // request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) + // in the Amazon Elastic Compute Cloud User Guide. + ClientToken *string `locationName:"clientToken" type:"string"` + + // The ID of the Dedicated host. + HostId *string `locationName:"hostId" type:"string"` + + // The hardware specifications of the Dedicated host. + HostProperties *HostProperties `locationName:"hostProperties" type:"structure"` + + // The reservation ID of the Dedicated host. This returns a null response if + // the Dedicated host doesn't have an associated reservation. + HostReservationId *string `locationName:"hostReservationId" type:"string"` + + // The IDs and instance type that are currently running on the Dedicated host. + Instances []*HostInstance `locationName:"instances" locationNameList:"item" type:"list"` + + // The Dedicated host's state. + State *string `locationName:"state" type:"string" enum:"AllocationState"` +} + +// String returns the string representation +func (s Host) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Host) GoString() string { + return s.String() +} + +type HostInstance struct { + _ struct{} `type:"structure"` + + // the IDs of instances that are running on the Dedicated host. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The instance type size (e.g., m3.medium) of the running instance. + InstanceType *string `locationName:"instanceType" type:"string"` +} + +// String returns the string representation +func (s HostInstance) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s HostInstance) GoString() string { + return s.String() +} + +type HostProperties struct { + _ struct{} `type:"structure"` + + // The number of cores on the Dedicated host. + Cores *int64 `locationName:"cores" type:"integer"` + + // The instance type size that the Dedicated host supports (e.g., m3.medium). + InstanceType *string `locationName:"instanceType" type:"string"` + + // The number of sockets on the Dedicated host. + Sockets *int64 `locationName:"sockets" type:"integer"` + + // The number of vCPUs on the Dedicated host. + TotalVCpus *int64 `locationName:"totalVCpus" type:"integer"` +} + +// String returns the string representation +func (s HostProperties) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s HostProperties) GoString() string { + return s.String() +} + +// Describes an IAM instance profile. +type IamInstanceProfile struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) of the instance profile. + Arn *string `locationName:"arn" type:"string"` + + // The ID of the instance profile. + Id *string `locationName:"id" type:"string"` +} + +// String returns the string representation +func (s IamInstanceProfile) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IamInstanceProfile) GoString() string { + return s.String() +} + +// Describes an IAM instance profile. +type IamInstanceProfileSpecification struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) of the instance profile. + Arn *string `locationName:"arn" type:"string"` + + // The name of the instance profile. + Name *string `locationName:"name" type:"string"` +} + +// String returns the string representation +func (s IamInstanceProfileSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IamInstanceProfileSpecification) GoString() string { + return s.String() +} + +// Describes the ICMP type and code. +type IcmpTypeCode struct { + _ struct{} `type:"structure"` + + // The ICMP type. A value of -1 means all types. + Code *int64 `locationName:"code" type:"integer"` + + // The ICMP code. A value of -1 means all codes for the specified ICMP type. + Type *int64 `locationName:"type" type:"integer"` +} + +// String returns the string representation +func (s IcmpTypeCode) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IcmpTypeCode) GoString() string { + return s.String() +} + +// Describes the ID format for a resource. +type IdFormat struct { + _ struct{} `type:"structure"` + + // The date in UTC at which you are permanently switched over to using longer + // IDs. + Deadline *time.Time `locationName:"deadline" type:"timestamp" timestampFormat:"iso8601"` + + // The type of resource. + Resource *string `locationName:"resource" type:"string"` + + // Indicates whether longer IDs (17-character IDs) are enabled for the resource. + UseLongIds *bool `locationName:"useLongIds" type:"boolean"` +} + +// String returns the string representation +func (s IdFormat) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IdFormat) GoString() string { + return s.String() +} + +// Describes an image. +type Image struct { + _ struct{} `type:"structure"` + + // The architecture of the image. + Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` + + // Any block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // The date and time the image was created. + CreationDate *string `locationName:"creationDate" type:"string"` + + // The description of the AMI that was provided during image creation. + Description *string `locationName:"description" type:"string"` + + // The hypervisor type of the image. + Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"` + + // The ID of the AMI. + ImageId *string `locationName:"imageId" type:"string"` + + // The location of the AMI. + ImageLocation *string `locationName:"imageLocation" type:"string"` + + // The AWS account alias (for example, amazon, self) or the AWS account ID of + // the AMI owner. + ImageOwnerAlias *string `locationName:"imageOwnerAlias" type:"string"` + + // The type of image. + ImageType *string `locationName:"imageType" type:"string" enum:"ImageTypeValues"` + + // The kernel associated with the image, if any. Only applicable for machine + // images. + KernelId *string `locationName:"kernelId" type:"string"` + + // The name of the AMI that was provided during image creation. + Name *string `locationName:"name" type:"string"` + + // The AWS account ID of the image owner. + OwnerId *string `locationName:"imageOwnerId" type:"string"` + + // The value is Windows for Windows AMIs; otherwise blank. + Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` + + // Any product codes associated with the AMI. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // Indicates whether the image has public launch permissions. The value is true + // if this image has public launch permissions or false if it has only implicit + // and explicit launch permissions. + Public *bool `locationName:"isPublic" type:"boolean"` + + // The RAM disk associated with the image, if any. Only applicable for machine + // images. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + // The device name of the root device (for example, /dev/sda1 or /dev/xvda). + RootDeviceName *string `locationName:"rootDeviceName" type:"string"` + + // The type of root device used by the AMI. The AMI can use an EBS volume or + // an instance store volume. + RootDeviceType *string `locationName:"rootDeviceType" type:"string" enum:"DeviceType"` + + // Specifies whether enhanced networking is enabled. + SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` + + // The current state of the AMI. If the state is available, the image is successfully + // registered and can be used to launch an instance. + State *string `locationName:"imageState" type:"string" enum:"ImageState"` + + // The reason for the state change. + StateReason *StateReason `locationName:"stateReason" type:"structure"` + + // Any tags assigned to the image. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The type of virtualization of the AMI. + VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"` +} + +// String returns the string representation +func (s Image) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Image) GoString() string { + return s.String() +} + +// Describes the disk container object for an import image task. +type ImageDiskContainer struct { + _ struct{} `type:"structure"` + + // The description of the disk image. + Description *string `type:"string"` + + // The block device mapping for the disk. + DeviceName *string `type:"string"` + + // The format of the disk image being imported. + // + // Valid values: RAW | VHD | VMDK | OVA + Format *string `type:"string"` + + // The ID of the EBS snapshot to be used for importing the snapshot. + SnapshotId *string `type:"string"` + + // The URL to the Amazon S3-based disk image being imported. The URL can either + // be a https URL (https://..) or an Amazon S3 URL (s3://..) + Url *string `type:"string"` + + // The S3 bucket for the disk image. + UserBucket *UserBucket `type:"structure"` +} + +// String returns the string representation +func (s ImageDiskContainer) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImageDiskContainer) GoString() string { + return s.String() +} + +type ImportImageInput struct { + _ struct{} `type:"structure"` + + // The architecture of the virtual machine. + // + // Valid values: i386 | x86_64 + Architecture *string `type:"string"` + + // The client-specific data. + ClientData *ClientData `type:"structure"` + + // The token to enable idempotency for VM import requests. + ClientToken *string `type:"string"` + + // A description string for the import image task. + Description *string `type:"string"` + + // Information about the disk containers. + DiskContainers []*ImageDiskContainer `locationName:"DiskContainer" locationNameList:"item" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // The target hypervisor platform. + // + // Valid values: xen + Hypervisor *string `type:"string"` + + // The license type to be used for the Amazon Machine Image (AMI) after importing. + // + // Note: You may only use BYOL if you have existing licenses with rights to + // use these licenses in a third party cloud like AWS. For more information, + // see VM Import/Export Prerequisites (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/VMImportPrerequisites.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Valid values: AWS | BYOL + LicenseType *string `type:"string"` + + // The operating system of the virtual machine. + // + // Valid values: Windows | Linux + Platform *string `type:"string"` + + // The name of the role to use when not using the default role, 'vmimport'. + RoleName *string `type:"string"` +} + +// String returns the string representation +func (s ImportImageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportImageInput) GoString() string { + return s.String() +} + +type ImportImageOutput struct { + _ struct{} `type:"structure"` + + // The architecture of the virtual machine. + Architecture *string `locationName:"architecture" type:"string"` + + // A description of the import task. + Description *string `locationName:"description" type:"string"` + + // The target hypervisor of the import task. + Hypervisor *string `locationName:"hypervisor" type:"string"` + + // The ID of the Amazon Machine Image (AMI) created by the import task. + ImageId *string `locationName:"imageId" type:"string"` + + // The task ID of the import image task. + ImportTaskId *string `locationName:"importTaskId" type:"string"` + + // The license type of the virtual machine. + LicenseType *string `locationName:"licenseType" type:"string"` + + // The operating system of the virtual machine. + Platform *string `locationName:"platform" type:"string"` + + // The progress of the task. + Progress *string `locationName:"progress" type:"string"` + + // Information about the snapshots. + SnapshotDetails []*SnapshotDetail `locationName:"snapshotDetailSet" locationNameList:"item" type:"list"` + + // A brief status of the task. + Status *string `locationName:"status" type:"string"` + + // A detailed status message of the import task. + StatusMessage *string `locationName:"statusMessage" type:"string"` +} + +// String returns the string representation +func (s ImportImageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportImageOutput) GoString() string { + return s.String() +} + +// Describes an import image task. +type ImportImageTask struct { + _ struct{} `type:"structure"` + + // The architecture of the virtual machine. + // + // Valid values: i386 | x86_64 + Architecture *string `locationName:"architecture" type:"string"` + + // A description of the import task. + Description *string `locationName:"description" type:"string"` + + // The target hypervisor for the import task. + // + // Valid values: xen + Hypervisor *string `locationName:"hypervisor" type:"string"` + + // The ID of the Amazon Machine Image (AMI) of the imported virtual machine. + ImageId *string `locationName:"imageId" type:"string"` + + // The ID of the import image task. + ImportTaskId *string `locationName:"importTaskId" type:"string"` + + // The license type of the virtual machine. + LicenseType *string `locationName:"licenseType" type:"string"` + + // The description string for the import image task. + Platform *string `locationName:"platform" type:"string"` + + // The percentage of progress of the import image task. + Progress *string `locationName:"progress" type:"string"` + + // Information about the snapshots. + SnapshotDetails []*SnapshotDetail `locationName:"snapshotDetailSet" locationNameList:"item" type:"list"` + + // A brief status for the import image task. + Status *string `locationName:"status" type:"string"` + + // A descriptive status message for the import image task. + StatusMessage *string `locationName:"statusMessage" type:"string"` +} + +// String returns the string representation +func (s ImportImageTask) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportImageTask) GoString() string { + return s.String() +} + +type ImportInstanceInput struct { + _ struct{} `type:"structure"` + + // A description for the instance being imported. + Description *string `locationName:"description" type:"string"` + + // The disk image. + DiskImages []*DiskImage `locationName:"diskImage" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The launch specification. + LaunchSpecification *ImportInstanceLaunchSpecification `locationName:"launchSpecification" type:"structure"` + + // The instance operating system. + Platform *string `locationName:"platform" type:"string" required:"true" enum:"PlatformValues"` +} + +// String returns the string representation +func (s ImportInstanceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportInstanceInput) GoString() string { + return s.String() +} + +// Describes the launch specification for VM import. +type ImportInstanceLaunchSpecification struct { + _ struct{} `type:"structure"` + + // Reserved. + AdditionalInfo *string `locationName:"additionalInfo" type:"string"` + + // The architecture of the instance. + Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` + + // One or more security group IDs. + GroupIds []*string `locationName:"GroupId" locationNameList:"SecurityGroupId" type:"list"` + + // One or more security group names. + GroupNames []*string `locationName:"GroupName" locationNameList:"SecurityGroup" type:"list"` + + // Indicates whether an instance stops or terminates when you initiate shutdown + // from the instance (using the operating system command for system shutdown). + InstanceInitiatedShutdownBehavior *string `locationName:"instanceInitiatedShutdownBehavior" type:"string" enum:"ShutdownBehavior"` + + // The instance type. For more information about the instance types that you + // can import, see Before You Get Started (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/VMImportPrerequisites.html) + // in the Amazon Elastic Compute Cloud User Guide. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // Indicates whether monitoring is enabled. + Monitoring *bool `locationName:"monitoring" type:"boolean"` + + // The placement information for the instance. + Placement *Placement `locationName:"placement" type:"structure"` + + // [EC2-VPC] An available IP address from the IP address range of the subnet. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // [EC2-VPC] The ID of the subnet in which to launch the instance. + SubnetId *string `locationName:"subnetId" type:"string"` + + // The Base64-encoded MIME user data to be made available to the instance. + UserData *UserData `locationName:"userData" type:"structure"` +} + +// String returns the string representation +func (s ImportInstanceLaunchSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportInstanceLaunchSpecification) GoString() string { + return s.String() +} + +type ImportInstanceOutput struct { + _ struct{} `type:"structure"` + + // Information about the conversion task. + ConversionTask *ConversionTask `locationName:"conversionTask" type:"structure"` +} + +// String returns the string representation +func (s ImportInstanceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportInstanceOutput) GoString() string { + return s.String() +} + +// Describes an import instance task. +type ImportInstanceTaskDetails struct { + _ struct{} `type:"structure"` + + // A description of the task. + Description *string `locationName:"description" type:"string"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The instance operating system. + Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` + + // One or more volumes. + Volumes []*ImportInstanceVolumeDetailItem `locationName:"volumes" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s ImportInstanceTaskDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportInstanceTaskDetails) GoString() string { + return s.String() +} + +// Describes an import volume task. +type ImportInstanceVolumeDetailItem struct { + _ struct{} `type:"structure"` + + // The Availability Zone where the resulting instance will reside. + AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` + + // The number of bytes converted so far. + BytesConverted *int64 `locationName:"bytesConverted" type:"long" required:"true"` + + // A description of the task. + Description *string `locationName:"description" type:"string"` + + // The image. + Image *DiskImageDescription `locationName:"image" type:"structure" required:"true"` + + // The status of the import of this particular disk image. + Status *string `locationName:"status" type:"string" required:"true"` + + // The status information or errors related to the disk image. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // The volume. + Volume *DiskImageVolumeDescription `locationName:"volume" type:"structure" required:"true"` +} + +// String returns the string representation +func (s ImportInstanceVolumeDetailItem) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportInstanceVolumeDetailItem) GoString() string { + return s.String() +} + +type ImportKeyPairInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // A unique name for the key pair. + KeyName *string `locationName:"keyName" type:"string" required:"true"` + + // The public key. You must base64 encode the public key material before sending + // it to AWS. + PublicKeyMaterial []byte `locationName:"publicKeyMaterial" type:"blob" required:"true"` +} + +// String returns the string representation +func (s ImportKeyPairInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportKeyPairInput) GoString() string { + return s.String() +} + +type ImportKeyPairOutput struct { + _ struct{} `type:"structure"` + + // The MD5 public key fingerprint as specified in section 4 of RFC 4716. + KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` + + // The key pair name you provided. + KeyName *string `locationName:"keyName" type:"string"` +} + +// String returns the string representation +func (s ImportKeyPairOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportKeyPairOutput) GoString() string { + return s.String() +} + +type ImportSnapshotInput struct { + _ struct{} `type:"structure"` + + // The client-specific data. + ClientData *ClientData `type:"structure"` + + // Token to enable idempotency for VM import requests. + ClientToken *string `type:"string"` + + // The description string for the import snapshot task. + Description *string `type:"string"` + + // Information about the disk container. + DiskContainer *SnapshotDiskContainer `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // The name of the role to use when not using the default role, 'vmimport'. + RoleName *string `type:"string"` +} + +// String returns the string representation +func (s ImportSnapshotInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportSnapshotInput) GoString() string { + return s.String() +} + +type ImportSnapshotOutput struct { + _ struct{} `type:"structure"` + + // A description of the import snapshot task. + Description *string `locationName:"description" type:"string"` + + // The ID of the import snapshot task. + ImportTaskId *string `locationName:"importTaskId" type:"string"` + + // Information about the import snapshot task. + SnapshotTaskDetail *SnapshotTaskDetail `locationName:"snapshotTaskDetail" type:"structure"` +} + +// String returns the string representation +func (s ImportSnapshotOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportSnapshotOutput) GoString() string { + return s.String() +} + +// Describes an import snapshot task. +type ImportSnapshotTask struct { + _ struct{} `type:"structure"` + + // A description of the import snapshot task. + Description *string `locationName:"description" type:"string"` + + // The ID of the import snapshot task. + ImportTaskId *string `locationName:"importTaskId" type:"string"` + + // Describes an import snapshot task. + SnapshotTaskDetail *SnapshotTaskDetail `locationName:"snapshotTaskDetail" type:"structure"` +} + +// String returns the string representation +func (s ImportSnapshotTask) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportSnapshotTask) GoString() string { + return s.String() +} + +type ImportVolumeInput struct { + _ struct{} `type:"structure"` + + // The Availability Zone for the resulting EBS volume. + AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` + + // A description of the volume. + Description *string `locationName:"description" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The disk image. + Image *DiskImageDetail `locationName:"image" type:"structure" required:"true"` + + // The volume size. + Volume *VolumeDetail `locationName:"volume" type:"structure" required:"true"` +} + +// String returns the string representation +func (s ImportVolumeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportVolumeInput) GoString() string { + return s.String() +} + +type ImportVolumeOutput struct { + _ struct{} `type:"structure"` + + // Information about the conversion task. + ConversionTask *ConversionTask `locationName:"conversionTask" type:"structure"` +} + +// String returns the string representation +func (s ImportVolumeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportVolumeOutput) GoString() string { + return s.String() +} + +// Describes an import volume task. +type ImportVolumeTaskDetails struct { + _ struct{} `type:"structure"` + + // The Availability Zone where the resulting volume will reside. + AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` + + // The number of bytes converted so far. + BytesConverted *int64 `locationName:"bytesConverted" type:"long" required:"true"` + + // The description you provided when starting the import volume task. + Description *string `locationName:"description" type:"string"` + + // The image. + Image *DiskImageDescription `locationName:"image" type:"structure" required:"true"` + + // The volume. + Volume *DiskImageVolumeDescription `locationName:"volume" type:"structure" required:"true"` +} + +// String returns the string representation +func (s ImportVolumeTaskDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ImportVolumeTaskDetails) GoString() string { + return s.String() +} + +// Describes an instance. +type Instance struct { + _ struct{} `type:"structure"` + + // The AMI launch index, which can be used to find this instance in the launch + // group. + AmiLaunchIndex *int64 `locationName:"amiLaunchIndex" type:"integer"` + + // The architecture of the image. + Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` + + // Any block device mapping entries for the instance. + BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // The idempotency token you provided when you launched the instance, if applicable. + ClientToken *string `locationName:"clientToken" type:"string"` + + // Indicates whether the instance is optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS + // Optimized instance. + EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` + + // The hypervisor type of the instance. + Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"` + + // The IAM instance profile associated with the instance, if applicable. + IamInstanceProfile *IamInstanceProfile `locationName:"iamInstanceProfile" type:"structure"` + + // The ID of the AMI used to launch the instance. + ImageId *string `locationName:"imageId" type:"string"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // Indicates whether this is a Spot instance. + InstanceLifecycle *string `locationName:"instanceLifecycle" type:"string" enum:"InstanceLifecycleType"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The kernel associated with this instance, if applicable. + KernelId *string `locationName:"kernelId" type:"string"` + + // The name of the key pair, if this instance was launched with an associated + // key pair. + KeyName *string `locationName:"keyName" type:"string"` + + // The time the instance was launched. + LaunchTime *time.Time `locationName:"launchTime" type:"timestamp" timestampFormat:"iso8601"` + + // The monitoring information for the instance. + Monitoring *Monitoring `locationName:"monitoring" type:"structure"` + + // [EC2-VPC] One or more network interfaces for the instance. + NetworkInterfaces []*InstanceNetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` + + // The location where the instance launched, if applicable. + Placement *Placement `locationName:"placement" type:"structure"` + + // The value is Windows for Windows instances; otherwise blank. + Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` + + // The private DNS name assigned to the instance. This DNS name can only be + // used inside the Amazon EC2 network. This name is not available until the + // instance enters the running state. For EC2-VPC, this name is only available + // if you've enabled DNS hostnames for your VPC. + PrivateDnsName *string `locationName:"privateDnsName" type:"string"` + + // The private IP address assigned to the instance. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The product codes attached to this instance, if applicable. + ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` + + // The public DNS name assigned to the instance. This name is not available + // until the instance enters the running state. For EC2-VPC, this name is only + // available if you've enabled DNS hostnames for your VPC. + PublicDnsName *string `locationName:"dnsName" type:"string"` + + // The public IP address assigned to the instance, if applicable. + PublicIpAddress *string `locationName:"ipAddress" type:"string"` + + // The RAM disk associated with this instance, if applicable. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + // The root device name (for example, /dev/sda1 or /dev/xvda). + RootDeviceName *string `locationName:"rootDeviceName" type:"string"` + + // The root device type used by the AMI. The AMI can use an EBS volume or an + // instance store volume. + RootDeviceType *string `locationName:"rootDeviceType" type:"string" enum:"DeviceType"` + + // One or more security groups for the instance. + SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // Specifies whether to enable an instance launched in a VPC to perform NAT. + // This controls whether source/destination checking is enabled on the instance. + // A value of true means checking is enabled, and false means checking is disabled. + // The value must be false for the instance to perform NAT. For more information, + // see NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) + // in the Amazon Virtual Private Cloud User Guide. + SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` + + // If the request is a Spot instance request, the ID of the request. + SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` + + // Specifies whether enhanced networking is enabled. + SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` + + // The current state of the instance. + State *InstanceState `locationName:"instanceState" type:"structure"` + + // The reason for the most recent state transition. + StateReason *StateReason `locationName:"stateReason" type:"structure"` + + // The reason for the most recent state transition. This might be an empty string. + StateTransitionReason *string `locationName:"reason" type:"string"` + + // [EC2-VPC] The ID of the subnet in which the instance is running. + SubnetId *string `locationName:"subnetId" type:"string"` + + // Any tags assigned to the instance. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The virtualization type of the instance. + VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"` + + // [EC2-VPC] The ID of the VPC in which the instance is running. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s Instance) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Instance) GoString() string { + return s.String() +} + +// Describes a block device mapping. +type InstanceBlockDeviceMapping struct { + _ struct{} `type:"structure"` + + // The device name exposed to the instance (for example, /dev/sdh or xvdh). + DeviceName *string `locationName:"deviceName" type:"string"` + + // Parameters used to automatically set up EBS volumes when the instance is + // launched. + Ebs *EbsInstanceBlockDevice `locationName:"ebs" type:"structure"` +} + +// String returns the string representation +func (s InstanceBlockDeviceMapping) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceBlockDeviceMapping) GoString() string { + return s.String() +} + +// Describes a block device mapping entry. +type InstanceBlockDeviceMappingSpecification struct { + _ struct{} `type:"structure"` + + // The device name exposed to the instance (for example, /dev/sdh or xvdh). + DeviceName *string `locationName:"deviceName" type:"string"` + + // Parameters used to automatically set up EBS volumes when the instance is + // launched. + Ebs *EbsInstanceBlockDeviceSpecification `locationName:"ebs" type:"structure"` + + // suppress the specified device included in the block device mapping. + NoDevice *string `locationName:"noDevice" type:"string"` + + // The virtual device name. + VirtualName *string `locationName:"virtualName" type:"string"` +} + +// String returns the string representation +func (s InstanceBlockDeviceMappingSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceBlockDeviceMappingSpecification) GoString() string { + return s.String() +} + +// Information about the instance type that the Dedicated host supports. +type InstanceCapacity struct { + _ struct{} `type:"structure"` + + // The number of instances that can still be launched onto the Dedicated host. + AvailableCapacity *int64 `locationName:"availableCapacity" type:"integer"` + + // The instance type size supported by the Dedicated host. + InstanceType *string `locationName:"instanceType" type:"string"` + + // The total number of instances that can be launched onto the Dedicated host. + TotalCapacity *int64 `locationName:"totalCapacity" type:"integer"` +} + +// String returns the string representation +func (s InstanceCapacity) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceCapacity) GoString() string { + return s.String() +} + +// Describes a Reserved Instance listing state. +type InstanceCount struct { + _ struct{} `type:"structure"` + + // The number of listed Reserved Instances in the state specified by the state. + InstanceCount *int64 `locationName:"instanceCount" type:"integer"` + + // The states of the listed Reserved Instances. + State *string `locationName:"state" type:"string" enum:"ListingState"` +} + +// String returns the string representation +func (s InstanceCount) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceCount) GoString() string { + return s.String() +} + +// Describes an instance to export. +type InstanceExportDetails struct { + _ struct{} `type:"structure"` + + // The ID of the resource being exported. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The target virtualization environment. + TargetEnvironment *string `locationName:"targetEnvironment" type:"string" enum:"ExportEnvironment"` +} + +// String returns the string representation +func (s InstanceExportDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceExportDetails) GoString() string { + return s.String() +} + +// Describes the monitoring information of the instance. +type InstanceMonitoring struct { + _ struct{} `type:"structure"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The monitoring information. + Monitoring *Monitoring `locationName:"monitoring" type:"structure"` +} + +// String returns the string representation +func (s InstanceMonitoring) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceMonitoring) GoString() string { + return s.String() +} + +// Describes a network interface. +type InstanceNetworkInterface struct { + _ struct{} `type:"structure"` + + // The association information for an Elastic IP associated with the network + // interface. + Association *InstanceNetworkInterfaceAssociation `locationName:"association" type:"structure"` + + // The network interface attachment. + Attachment *InstanceNetworkInterfaceAttachment `locationName:"attachment" type:"structure"` + + // The description. + Description *string `locationName:"description" type:"string"` + + // One or more security groups. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The MAC address. + MacAddress *string `locationName:"macAddress" type:"string"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The ID of the AWS account that created the network interface. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The private DNS name. + PrivateDnsName *string `locationName:"privateDnsName" type:"string"` + + // The IP address of the network interface within the subnet. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The private IP addresses associated with the network interface. + PrivateIpAddresses []*InstancePrivateIpAddress `locationName:"privateIpAddressesSet" locationNameList:"item" type:"list"` + + // Indicates whether to validate network traffic to or from this network interface. + SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` + + // The status of the network interface. + Status *string `locationName:"status" type:"string" enum:"NetworkInterfaceStatus"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s InstanceNetworkInterface) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceNetworkInterface) GoString() string { + return s.String() +} + +// Describes association information for an Elastic IP address. +type InstanceNetworkInterfaceAssociation struct { + _ struct{} `type:"structure"` + + // The ID of the owner of the Elastic IP address. + IpOwnerId *string `locationName:"ipOwnerId" type:"string"` + + // The public DNS name. + PublicDnsName *string `locationName:"publicDnsName" type:"string"` + + // The public IP address or Elastic IP address bound to the network interface. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s InstanceNetworkInterfaceAssociation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceNetworkInterfaceAssociation) GoString() string { + return s.String() +} + +// Describes a network interface attachment. +type InstanceNetworkInterfaceAttachment struct { + _ struct{} `type:"structure"` + + // The time stamp when the attachment initiated. + AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` + + // The ID of the network interface attachment. + AttachmentId *string `locationName:"attachmentId" type:"string"` + + // Indicates whether the network interface is deleted when the instance is terminated. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The index of the device on the instance for the network interface attachment. + DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` + + // The attachment state. + Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` +} + +// String returns the string representation +func (s InstanceNetworkInterfaceAttachment) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceNetworkInterfaceAttachment) GoString() string { + return s.String() +} + +// Describes a network interface. +type InstanceNetworkInterfaceSpecification struct { + _ struct{} `type:"structure"` + + // Indicates whether to assign a public IP address to an instance you launch + // in a VPC. The public IP address can only be assigned to a network interface + // for eth0, and can only be assigned to a new network interface, not an existing + // one. You cannot specify more than one network interface in the request. If + // launching into a default subnet, the default value is true. + AssociatePublicIpAddress *bool `locationName:"associatePublicIpAddress" type:"boolean"` + + // If set to true, the interface is deleted when the instance is terminated. + // You can specify true only if creating a new network interface when launching + // an instance. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The description of the network interface. Applies only if creating a network + // interface when launching an instance. + Description *string `locationName:"description" type:"string"` + + // The index of the device on the instance for the network interface attachment. + // If you are specifying a network interface in a RunInstances request, you + // must provide the device index. + DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` + + // The IDs of the security groups for the network interface. Applies only if + // creating a network interface when launching an instance. + Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The private IP address of the network interface. Applies only if creating + // a network interface when launching an instance. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // One or more private IP addresses to assign to the network interface. Only + // one private IP address can be designated as primary. + PrivateIpAddresses []*PrivateIpAddressSpecification `locationName:"privateIpAddressesSet" queryName:"PrivateIpAddresses" locationNameList:"item" type:"list"` + + // The number of secondary private IP addresses. You can't specify this option + // and specify more than one private IP address using the private IP addresses + // option. + SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` + + // The ID of the subnet associated with the network string. Applies only if + // creating a network interface when launching an instance. + SubnetId *string `locationName:"subnetId" type:"string"` +} + +// String returns the string representation +func (s InstanceNetworkInterfaceSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceNetworkInterfaceSpecification) GoString() string { + return s.String() +} + +// Describes a private IP address. +type InstancePrivateIpAddress struct { + _ struct{} `type:"structure"` + + // The association information for an Elastic IP address for the network interface. + Association *InstanceNetworkInterfaceAssociation `locationName:"association" type:"structure"` + + // Indicates whether this IP address is the primary private IP address of the + // network interface. + Primary *bool `locationName:"primary" type:"boolean"` + + // The private DNS name. + PrivateDnsName *string `locationName:"privateDnsName" type:"string"` + + // The private IP address of the network interface. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` +} + +// String returns the string representation +func (s InstancePrivateIpAddress) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstancePrivateIpAddress) GoString() string { + return s.String() +} + +// Describes the current state of the instance. +type InstanceState struct { + _ struct{} `type:"structure"` + + // The low byte represents the state. The high byte is an opaque internal value + // and should be ignored. + // + // 0 : pending + // + // 16 : running + // + // 32 : shutting-down + // + // 48 : terminated + // + // 64 : stopping + // + // 80 : stopped + Code *int64 `locationName:"code" type:"integer"` + + // The current state of the instance. + Name *string `locationName:"name" type:"string" enum:"InstanceStateName"` +} + +// String returns the string representation +func (s InstanceState) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceState) GoString() string { + return s.String() +} + +// Describes an instance state change. +type InstanceStateChange struct { + _ struct{} `type:"structure"` + + // The current state of the instance. + CurrentState *InstanceState `locationName:"currentState" type:"structure"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The previous state of the instance. + PreviousState *InstanceState `locationName:"previousState" type:"structure"` +} + +// String returns the string representation +func (s InstanceStateChange) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceStateChange) GoString() string { + return s.String() +} + +// Describes the status of an instance. +type InstanceStatus struct { + _ struct{} `type:"structure"` + + // The Availability Zone of the instance. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // Any scheduled events associated with the instance. + Events []*InstanceStatusEvent `locationName:"eventsSet" locationNameList:"item" type:"list"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The intended state of the instance. DescribeInstanceStatus requires that + // an instance be in the running state. + InstanceState *InstanceState `locationName:"instanceState" type:"structure"` + + // Reports impaired functionality that stems from issues internal to the instance, + // such as impaired reachability. + InstanceStatus *InstanceStatusSummary `locationName:"instanceStatus" type:"structure"` + + // Reports impaired functionality that stems from issues related to the systems + // that support an instance, such as hardware failures and network connectivity + // problems. + SystemStatus *InstanceStatusSummary `locationName:"systemStatus" type:"structure"` +} + +// String returns the string representation +func (s InstanceStatus) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceStatus) GoString() string { + return s.String() +} + +// Describes the instance status. +type InstanceStatusDetails struct { + _ struct{} `type:"structure"` + + // The time when a status check failed. For an instance that was launched and + // impaired, this is the time when the instance was launched. + ImpairedSince *time.Time `locationName:"impairedSince" type:"timestamp" timestampFormat:"iso8601"` + + // The type of instance status. + Name *string `locationName:"name" type:"string" enum:"StatusName"` + + // The status. + Status *string `locationName:"status" type:"string" enum:"StatusType"` +} + +// String returns the string representation +func (s InstanceStatusDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceStatusDetails) GoString() string { + return s.String() +} + +// Describes a scheduled event for an instance. +type InstanceStatusEvent struct { + _ struct{} `type:"structure"` + + // The event code. + Code *string `locationName:"code" type:"string" enum:"EventCode"` + + // A description of the event. + // + // After a scheduled event is completed, it can still be described for up to + // a week. If the event has been completed, this description starts with the + // following text: [Completed]. + Description *string `locationName:"description" type:"string"` + + // The latest scheduled end time for the event. + NotAfter *time.Time `locationName:"notAfter" type:"timestamp" timestampFormat:"iso8601"` + + // The earliest scheduled start time for the event. + NotBefore *time.Time `locationName:"notBefore" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s InstanceStatusEvent) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceStatusEvent) GoString() string { + return s.String() +} + +// Describes the status of an instance. +type InstanceStatusSummary struct { + _ struct{} `type:"structure"` + + // The system instance health or application instance health. + Details []*InstanceStatusDetails `locationName:"details" locationNameList:"item" type:"list"` + + // The status. + Status *string `locationName:"status" type:"string" enum:"SummaryStatus"` +} + +// String returns the string representation +func (s InstanceStatusSummary) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InstanceStatusSummary) GoString() string { + return s.String() +} + +// Describes an Internet gateway. +type InternetGateway struct { + _ struct{} `type:"structure"` + + // Any VPCs attached to the Internet gateway. + Attachments []*InternetGatewayAttachment `locationName:"attachmentSet" locationNameList:"item" type:"list"` + + // The ID of the Internet gateway. + InternetGatewayId *string `locationName:"internetGatewayId" type:"string"` + + // Any tags assigned to the Internet gateway. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s InternetGateway) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InternetGateway) GoString() string { + return s.String() +} + +// Describes the attachment of a VPC to an Internet gateway. +type InternetGatewayAttachment struct { + _ struct{} `type:"structure"` + + // The current state of the attachment. + State *string `locationName:"state" type:"string" enum:"AttachmentStatus"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s InternetGatewayAttachment) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s InternetGatewayAttachment) GoString() string { + return s.String() +} + +// Describes a security group rule. +type IpPermission struct { + _ struct{} `type:"structure"` + + // The start of port range for the TCP and UDP protocols, or an ICMP type number. + // A value of -1 indicates all ICMP types. + FromPort *int64 `locationName:"fromPort" type:"integer"` + + // The IP protocol name (for tcp, udp, and icmp) or number (see Protocol Numbers + // (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). + // + // [EC2-VPC only] When you authorize or revoke security group rules, you can + // use -1 to specify all. + IpProtocol *string `locationName:"ipProtocol" type:"string"` + + // One or more IP ranges. + IpRanges []*IpRange `locationName:"ipRanges" locationNameList:"item" type:"list"` + + // (Valid for AuthorizeSecurityGroupEgress, RevokeSecurityGroupEgress and DescribeSecurityGroups + // only) One or more prefix list IDs for an AWS service. In an AuthorizeSecurityGroupEgress + // request, this is the AWS service that you want to access through a VPC endpoint + // from instances associated with the security group. + PrefixListIds []*PrefixListId `locationName:"prefixListIds" locationNameList:"item" type:"list"` + + // The end of port range for the TCP and UDP protocols, or an ICMP code. A value + // of -1 indicates all ICMP codes for the specified ICMP type. + ToPort *int64 `locationName:"toPort" type:"integer"` + + // One or more security group and AWS account ID pairs. + UserIdGroupPairs []*UserIdGroupPair `locationName:"groups" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s IpPermission) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IpPermission) GoString() string { + return s.String() +} + +// Describes an IP range. +type IpRange struct { + _ struct{} `type:"structure"` + + // The CIDR range. You can either specify a CIDR range or a source security + // group, not both. + CidrIp *string `locationName:"cidrIp" type:"string"` +} + +// String returns the string representation +func (s IpRange) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s IpRange) GoString() string { + return s.String() +} + +// Describes a key pair. +type KeyPairInfo struct { + _ struct{} `type:"structure"` + + // If you used CreateKeyPair to create the key pair, this is the SHA-1 digest + // of the DER encoded private key. If you used ImportKeyPair to provide AWS + // the public key, this is the MD5 public key fingerprint as specified in section + // 4 of RFC4716. + KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` + + // The name of the key pair. + KeyName *string `locationName:"keyName" type:"string"` +} + +// String returns the string representation +func (s KeyPairInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s KeyPairInfo) GoString() string { + return s.String() +} + +// Describes a launch permission. +type LaunchPermission struct { + _ struct{} `type:"structure"` + + // The name of the group. + Group *string `locationName:"group" type:"string" enum:"PermissionGroup"` + + // The AWS account ID. + UserId *string `locationName:"userId" type:"string"` +} + +// String returns the string representation +func (s LaunchPermission) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LaunchPermission) GoString() string { + return s.String() +} + +// Describes a launch permission modification. +type LaunchPermissionModifications struct { + _ struct{} `type:"structure"` + + // The AWS account ID to add to the list of launch permissions for the AMI. + Add []*LaunchPermission `locationNameList:"item" type:"list"` + + // The AWS account ID to remove from the list of launch permissions for the + // AMI. + Remove []*LaunchPermission `locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s LaunchPermissionModifications) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LaunchPermissionModifications) GoString() string { + return s.String() +} + +// Describes the launch specification for an instance. +type LaunchSpecification struct { + _ struct{} `type:"structure"` + + // Deprecated. + AddressingType *string `locationName:"addressingType" type:"string"` + + // One or more block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // Indicates whether the instance is optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS + // Optimized instance. + // + // Default: false + EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` + + // The IAM instance profile. + IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` + + // The ID of the AMI. + ImageId *string `locationName:"imageId" type:"string"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The ID of the kernel. + KernelId *string `locationName:"kernelId" type:"string"` + + // The name of the key pair. + KeyName *string `locationName:"keyName" type:"string"` + + // Describes the monitoring for the instance. + Monitoring *RunInstancesMonitoringEnabled `locationName:"monitoring" type:"structure"` + + // One or more network interfaces. + NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` + + // The placement information for the instance. + Placement *SpotPlacement `locationName:"placement" type:"structure"` + + // The ID of the RAM disk. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + // One or more security groups. When requesting instances in a VPC, you must + // specify the IDs of the security groups. When requesting instances in EC2-Classic, + // you can specify the names or the IDs of the security groups. + SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The ID of the subnet in which to launch the instance. + SubnetId *string `locationName:"subnetId" type:"string"` + + // The Base64-encoded MIME user data to make available to the instances. + UserData *string `locationName:"userData" type:"string"` +} + +// String returns the string representation +func (s LaunchSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LaunchSpecification) GoString() string { + return s.String() +} + +type ModifyHostsInput struct { + _ struct{} `type:"structure"` + + // Specify whether to enable or disable auto-placement. + AutoPlacement *string `locationName:"autoPlacement" type:"string" required:"true" enum:"AutoPlacement"` + + // The host IDs of the Dedicated hosts you want to modify. + HostIds []*string `locationName:"hostId" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s ModifyHostsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyHostsInput) GoString() string { + return s.String() +} + +type ModifyHostsOutput struct { + _ struct{} `type:"structure"` + + // The IDs of the Dedicated hosts that were successfully modified. + Successful []*string `locationName:"successful" locationNameList:"item" type:"list"` + + // The IDs of the Dedicated hosts that could not be modified. Check whether + // the setting you requested can be used. + Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s ModifyHostsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyHostsOutput) GoString() string { + return s.String() +} + +type ModifyIdFormatInput struct { + _ struct{} `type:"structure"` + + // The type of resource. + Resource *string `type:"string" required:"true"` + + // Indicate whether the resource should use longer IDs (17-character IDs). + UseLongIds *bool `type:"boolean" required:"true"` +} + +// String returns the string representation +func (s ModifyIdFormatInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyIdFormatInput) GoString() string { + return s.String() +} + +type ModifyIdFormatOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyIdFormatOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyIdFormatOutput) GoString() string { + return s.String() +} + +type ModifyImageAttributeInput struct { + _ struct{} `type:"structure"` + + // The name of the attribute to modify. + Attribute *string `type:"string"` + + // A description for the AMI. + Description *AttributeValue `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the AMI. + ImageId *string `type:"string" required:"true"` + + // A launch permission modification. + LaunchPermission *LaunchPermissionModifications `type:"structure"` + + // The operation type. + OperationType *string `type:"string" enum:"OperationType"` + + // One or more product codes. After you add a product code to an AMI, it can't + // be removed. This is only valid when modifying the productCodes attribute. + ProductCodes []*string `locationName:"ProductCode" locationNameList:"ProductCode" type:"list"` + + // One or more user groups. This is only valid when modifying the launchPermission + // attribute. + UserGroups []*string `locationName:"UserGroup" locationNameList:"UserGroup" type:"list"` + + // One or more AWS account IDs. This is only valid when modifying the launchPermission + // attribute. + UserIds []*string `locationName:"UserId" locationNameList:"UserId" type:"list"` + + // The value of the attribute being modified. This is only valid when modifying + // the description attribute. + Value *string `type:"string"` +} + +// String returns the string representation +func (s ModifyImageAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyImageAttributeInput) GoString() string { + return s.String() +} + +type ModifyImageAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyImageAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyImageAttributeOutput) GoString() string { + return s.String() +} + +type ModifyInstanceAttributeInput struct { + _ struct{} `type:"structure"` + + // The name of the attribute. + Attribute *string `locationName:"attribute" type:"string" enum:"InstanceAttributeName"` + + // Modifies the DeleteOnTermination attribute for volumes that are currently + // attached. The volume must be owned by the caller. If no value is specified + // for DeleteOnTermination, the default is true and the volume is deleted when + // the instance is terminated. + // + // To add instance store volumes to an Amazon EBS-backed instance, you must + // add them when you launch the instance. For more information, see Updating + // the Block Device Mapping when Launching an Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html#Using_OverridingAMIBDM) + // in the Amazon Elastic Compute Cloud User Guide. + BlockDeviceMappings []*InstanceBlockDeviceMappingSpecification `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // If the value is true, you can't terminate the instance using the Amazon EC2 + // console, CLI, or API; otherwise, you can. You cannot use this paramater for + // Spot Instances. + DisableApiTermination *AttributeBooleanValue `locationName:"disableApiTermination" type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Specifies whether the instance is optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS + // Optimized instance. + EbsOptimized *AttributeBooleanValue `locationName:"ebsOptimized" type:"structure"` + + // [EC2-VPC] Changes the security groups of the instance. You must specify at + // least one security group, even if it's just the default security group for + // the VPC. You must specify the security group ID, not the security group name. + Groups []*string `locationName:"GroupId" locationNameList:"groupId" type:"list"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // Specifies whether an instance stops or terminates when you initiate shutdown + // from the instance (using the operating system command for system shutdown). + InstanceInitiatedShutdownBehavior *AttributeValue `locationName:"instanceInitiatedShutdownBehavior" type:"structure"` + + // Changes the instance type to the specified value. For more information, see + // Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html). + // If the instance type is not valid, the error returned is InvalidInstanceAttributeValue. + InstanceType *AttributeValue `locationName:"instanceType" type:"structure"` + + // Changes the instance's kernel to the specified value. We recommend that you + // use PV-GRUB instead of kernels and RAM disks. For more information, see PV-GRUB + // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedKernels.html). + Kernel *AttributeValue `locationName:"kernel" type:"structure"` + + // Changes the instance's RAM disk to the specified value. We recommend that + // you use PV-GRUB instead of kernels and RAM disks. For more information, see + // PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedKernels.html). + Ramdisk *AttributeValue `locationName:"ramdisk" type:"structure"` + + // Specifies whether source/destination checking is enabled. A value of true + // means that checking is enabled, and false means checking is disabled. This + // value must be false for a NAT instance to perform NAT. + SourceDestCheck *AttributeBooleanValue `type:"structure"` + + // Set to simple to enable enhanced networking for the instance. + // + // There is no way to disable enhanced networking at this time. + // + // This option is supported only for HVM instances. Specifying this option + // with a PV instance can make it unreachable. + SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` + + // Changes the instance's user data to the specified value. + UserData *BlobAttributeValue `locationName:"userData" type:"structure"` + + // A new value for the attribute. Use only with the kernel, ramdisk, userData, + // disableApiTermination, or instanceInitiatedShutdownBehavior attribute. + Value *string `locationName:"value" type:"string"` +} + +// String returns the string representation +func (s ModifyInstanceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyInstanceAttributeInput) GoString() string { + return s.String() +} + +type ModifyInstanceAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyInstanceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyInstanceAttributeOutput) GoString() string { + return s.String() +} + +type ModifyInstancePlacementInput struct { + _ struct{} `type:"structure"` + + // The new affinity setting for the instance. + Affinity *string `locationName:"affinity" type:"string" enum:"Affinity"` + + // The ID of the Dedicated host that the instance will have affinity with. + HostId *string `locationName:"hostId" type:"string"` + + // The ID of the instance that you are modifying. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` + + // The tenancy of the instance that you are modifying. + Tenancy *string `locationName:"tenancy" type:"string" enum:"HostTenancy"` +} + +// String returns the string representation +func (s ModifyInstancePlacementInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyInstancePlacementInput) GoString() string { + return s.String() +} + +type ModifyInstancePlacementOutput struct { + _ struct{} `type:"structure"` + + // Is true if the request succeeds, and an error otherwise. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s ModifyInstancePlacementOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyInstancePlacementOutput) GoString() string { + return s.String() +} + +type ModifyNetworkInterfaceAttributeInput struct { + _ struct{} `type:"structure"` + + // Information about the interface attachment. If modifying the 'delete on termination' + // attribute, you must specify the ID of the interface attachment. + Attachment *NetworkInterfaceAttachmentChanges `locationName:"attachment" type:"structure"` + + // A description for the network interface. + Description *AttributeValue `locationName:"description" type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Changes the security groups for the network interface. The new set of groups + // you specify replaces the current set. You must specify at least one group, + // even if it's just the default security group in the VPC. You must specify + // the ID of the security group, not the name. + Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` + + // Indicates whether source/destination checking is enabled. A value of true + // means checking is enabled, and false means checking is disabled. This value + // must be false for a NAT instance to perform NAT. For more information, see + // NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) + // in the Amazon Virtual Private Cloud User Guide. + SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` +} + +// String returns the string representation +func (s ModifyNetworkInterfaceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyNetworkInterfaceAttributeInput) GoString() string { + return s.String() +} + +type ModifyNetworkInterfaceAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyNetworkInterfaceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyNetworkInterfaceAttributeOutput) GoString() string { + return s.String() +} + +type ModifyReservedInstancesInput struct { + _ struct{} `type:"structure"` + + // A unique, case-sensitive token you provide to ensure idempotency of your + // modification request. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `locationName:"clientToken" type:"string"` + + // The IDs of the Reserved Instances to modify. + ReservedInstancesIds []*string `locationName:"ReservedInstancesId" locationNameList:"ReservedInstancesId" type:"list" required:"true"` + + // The configuration settings for the Reserved Instances to modify. + TargetConfigurations []*ReservedInstancesConfiguration `locationName:"ReservedInstancesConfigurationSetItemType" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s ModifyReservedInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyReservedInstancesInput) GoString() string { + return s.String() +} + +type ModifyReservedInstancesOutput struct { + _ struct{} `type:"structure"` + + // The ID for the modification. + ReservedInstancesModificationId *string `locationName:"reservedInstancesModificationId" type:"string"` +} + +// String returns the string representation +func (s ModifyReservedInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyReservedInstancesOutput) GoString() string { + return s.String() +} + +type ModifySnapshotAttributeInput struct { + _ struct{} `type:"structure"` + + // The snapshot attribute to modify. + // + // Only volume creation permissions may be modified at the customer level. + Attribute *string `type:"string" enum:"SnapshotAttributeName"` + + // A JSON representation of the snapshot attribute modification. + CreateVolumePermission *CreateVolumePermissionModifications `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The group to modify for the snapshot. + GroupNames []*string `locationName:"UserGroup" locationNameList:"GroupName" type:"list"` + + // The type of operation to perform to the attribute. + OperationType *string `type:"string" enum:"OperationType"` + + // The ID of the snapshot. + SnapshotId *string `type:"string" required:"true"` + + // The account ID to modify for the snapshot. + UserIds []*string `locationName:"UserId" locationNameList:"UserId" type:"list"` +} + +// String returns the string representation +func (s ModifySnapshotAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySnapshotAttributeInput) GoString() string { + return s.String() +} + +type ModifySnapshotAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifySnapshotAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySnapshotAttributeOutput) GoString() string { + return s.String() +} + +// Contains the parameters for ModifySpotFleetRequest. +type ModifySpotFleetRequestInput struct { + _ struct{} `type:"structure"` + + // Indicates whether running Spot instances should be terminated if the target + // capacity of the Spot fleet request is decreased below the current size of + // the Spot fleet. + ExcessCapacityTerminationPolicy *string `locationName:"excessCapacityTerminationPolicy" type:"string" enum:"ExcessCapacityTerminationPolicy"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` + + // The size of the fleet. + TargetCapacity *int64 `locationName:"targetCapacity" type:"integer"` +} + +// String returns the string representation +func (s ModifySpotFleetRequestInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySpotFleetRequestInput) GoString() string { + return s.String() +} + +// Contains the output of ModifySpotFleetRequest. +type ModifySpotFleetRequestOutput struct { + _ struct{} `type:"structure"` + + // Is true if the request succeeds, and an error otherwise. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s ModifySpotFleetRequestOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySpotFleetRequestOutput) GoString() string { + return s.String() +} + +type ModifySubnetAttributeInput struct { + _ struct{} `type:"structure"` + + // Specify true to indicate that instances launched into the specified subnet + // should be assigned public IP address. + MapPublicIpOnLaunch *AttributeBooleanValue `type:"structure"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string" required:"true"` +} + +// String returns the string representation +func (s ModifySubnetAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySubnetAttributeInput) GoString() string { + return s.String() +} + +type ModifySubnetAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifySubnetAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifySubnetAttributeOutput) GoString() string { + return s.String() +} + +type ModifyVolumeAttributeInput struct { + _ struct{} `type:"structure"` + + // Indicates whether the volume should be auto-enabled for I/O operations. + AutoEnableIO *AttributeBooleanValue `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the volume. + VolumeId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s ModifyVolumeAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVolumeAttributeInput) GoString() string { + return s.String() +} + +type ModifyVolumeAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyVolumeAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVolumeAttributeOutput) GoString() string { + return s.String() +} + +type ModifyVpcAttributeInput struct { + _ struct{} `type:"structure"` + + // Indicates whether the instances launched in the VPC get DNS hostnames. If + // enabled, instances in the VPC get DNS hostnames; otherwise, they do not. + // + // You cannot modify the DNS resolution and DNS hostnames attributes in the + // same request. Use separate requests for each attribute. You can only enable + // DNS hostnames if you've enabled DNS support. + EnableDnsHostnames *AttributeBooleanValue `type:"structure"` + + // Indicates whether the DNS resolution is supported for the VPC. If enabled, + // queries to the Amazon provided DNS server at the 169.254.169.253 IP address, + // or the reserved IP address at the base of the VPC network range "plus two" + // will succeed. If disabled, the Amazon provided DNS service in the VPC that + // resolves public DNS hostnames to IP addresses is not enabled. + // + // You cannot modify the DNS resolution and DNS hostnames attributes in the + // same request. Use separate requests for each attribute. + EnableDnsSupport *AttributeBooleanValue `type:"structure"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string" required:"true"` +} + +// String returns the string representation +func (s ModifyVpcAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVpcAttributeInput) GoString() string { + return s.String() +} + +type ModifyVpcAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ModifyVpcAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVpcAttributeOutput) GoString() string { + return s.String() +} + +type ModifyVpcEndpointInput struct { + _ struct{} `type:"structure"` + + // One or more route tables IDs to associate with the endpoint. + AddRouteTableIds []*string `locationName:"AddRouteTableId" locationNameList:"item" type:"list"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // A policy document to attach to the endpoint. The policy must be in valid + // JSON format. + PolicyDocument *string `type:"string"` + + // One or more route table IDs to disassociate from the endpoint. + RemoveRouteTableIds []*string `locationName:"RemoveRouteTableId" locationNameList:"item" type:"list"` + + // Specify true to reset the policy document to the default policy. The default + // policy allows access to the service. + ResetPolicy *bool `type:"boolean"` + + // The ID of the endpoint. + VpcEndpointId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s ModifyVpcEndpointInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVpcEndpointInput) GoString() string { + return s.String() +} + +type ModifyVpcEndpointOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s ModifyVpcEndpointOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ModifyVpcEndpointOutput) GoString() string { + return s.String() +} + +type MonitorInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s MonitorInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s MonitorInstancesInput) GoString() string { + return s.String() +} + +type MonitorInstancesOutput struct { + _ struct{} `type:"structure"` + + // Monitoring information for one or more instances. + InstanceMonitorings []*InstanceMonitoring `locationName:"instancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s MonitorInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s MonitorInstancesOutput) GoString() string { + return s.String() +} + +// Describes the monitoring for the instance. +type Monitoring struct { + _ struct{} `type:"structure"` + + // Indicates whether monitoring is enabled for the instance. + State *string `locationName:"state" type:"string" enum:"MonitoringState"` +} + +// String returns the string representation +func (s Monitoring) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Monitoring) GoString() string { + return s.String() +} + +type MoveAddressToVpcInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string" required:"true"` +} + +// String returns the string representation +func (s MoveAddressToVpcInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s MoveAddressToVpcInput) GoString() string { + return s.String() +} + +type MoveAddressToVpcOutput struct { + _ struct{} `type:"structure"` + + // The allocation ID for the Elastic IP address. + AllocationId *string `locationName:"allocationId" type:"string"` + + // The status of the move of the IP address. + Status *string `locationName:"status" type:"string" enum:"Status"` +} + +// String returns the string representation +func (s MoveAddressToVpcOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s MoveAddressToVpcOutput) GoString() string { + return s.String() +} + +// Describes the status of a moving Elastic IP address. +type MovingAddressStatus struct { + _ struct{} `type:"structure"` + + // The status of the Elastic IP address that's being moved to the EC2-VPC platform, + // or restored to the EC2-Classic platform. + MoveStatus *string `locationName:"moveStatus" type:"string" enum:"MoveStatus"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s MovingAddressStatus) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s MovingAddressStatus) GoString() string { + return s.String() +} + +// Describes a NAT gateway. +type NatGateway struct { + _ struct{} `type:"structure"` + + // The date and time the NAT gateway was created. + CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"` + + // The date and time the NAT gateway was deleted, if applicable. + DeleteTime *time.Time `locationName:"deleteTime" type:"timestamp" timestampFormat:"iso8601"` + + // If the NAT gateway could not be created, specifies the error code for the + // failure. (InsufficientFreeAddressesInSubnet | Gateway.NotAttached | InvalidAllocationID.NotFound + // | Resource.AlreadyAssociated | InternalError) + FailureCode *string `locationName:"failureCode" type:"string"` + + // If the NAT gateway could not be created, specifies the error message for + // the failure, that corresponds to the error code. + // + // For InsufficientFreeAddressesInSubnet: Subnet has insufficient free addresses + // to create this NAT gateway For Gateway.NotAttached: Network vpc-xxxxxxxx + // has no Internet gateway attached For InvalidAllocationID.NotFound: Elastic + // IP address eipalloc-xxxxxxxx could not be associated with this NAT gateway + // For Resource.AlreadyAssociated: Elastic IP address eipalloc-xxxxxxxx is already + // associated For InternalError: Network interface eni-xxxxxxxx, created and + // used internally by this NAT gateway is in an invalid state. Please try again. + FailureMessage *string `locationName:"failureMessage" type:"string"` + + // Information about the IP addresses and network interface associated with + // the NAT gateway. + NatGatewayAddresses []*NatGatewayAddress `locationName:"natGatewayAddressSet" locationNameList:"item" type:"list"` + + // The ID of the NAT gateway. + NatGatewayId *string `locationName:"natGatewayId" type:"string"` + + // The state of the NAT gateway. + State *string `locationName:"state" type:"string" enum:"NatGatewayState"` + + // The ID of the subnet in which the NAT gateway is located. + SubnetId *string `locationName:"subnetId" type:"string"` + + // The ID of the VPC in which the NAT gateway is located. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s NatGateway) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NatGateway) GoString() string { + return s.String() +} + +// Describes the IP addresses and network interface associated with a NAT gateway. +type NatGatewayAddress struct { + _ struct{} `type:"structure"` + + // The allocation ID of the Elastic IP address that's associated with the NAT + // gateway. + AllocationId *string `locationName:"allocationId" type:"string"` + + // The ID of the network interface associated with the NAT gateway. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The private IP address associated with the Elastic IP address. + PrivateIp *string `locationName:"privateIp" type:"string"` + + // The Elastic IP address associated with the NAT gateway. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s NatGatewayAddress) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NatGatewayAddress) GoString() string { + return s.String() +} + +// Describes a network ACL. +type NetworkAcl struct { + _ struct{} `type:"structure"` + + // Any associations between the network ACL and one or more subnets + Associations []*NetworkAclAssociation `locationName:"associationSet" locationNameList:"item" type:"list"` + + // One or more entries (rules) in the network ACL. + Entries []*NetworkAclEntry `locationName:"entrySet" locationNameList:"item" type:"list"` + + // Indicates whether this is the default network ACL for the VPC. + IsDefault *bool `locationName:"default" type:"boolean"` + + // The ID of the network ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string"` + + // Any tags assigned to the network ACL. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC for the network ACL. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s NetworkAcl) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkAcl) GoString() string { + return s.String() +} + +// Describes an association between a network ACL and a subnet. +type NetworkAclAssociation struct { + _ struct{} `type:"structure"` + + // The ID of the association between a network ACL and a subnet. + NetworkAclAssociationId *string `locationName:"networkAclAssociationId" type:"string"` + + // The ID of the network ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string"` +} + +// String returns the string representation +func (s NetworkAclAssociation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkAclAssociation) GoString() string { + return s.String() +} + +// Describes an entry in a network ACL. +type NetworkAclEntry struct { + _ struct{} `type:"structure"` + + // The network range to allow or deny, in CIDR notation. + CidrBlock *string `locationName:"cidrBlock" type:"string"` + + // Indicates whether the rule is an egress rule (applied to traffic leaving + // the subnet). + Egress *bool `locationName:"egress" type:"boolean"` + + // ICMP protocol: The ICMP type and code. + IcmpTypeCode *IcmpTypeCode `locationName:"icmpTypeCode" type:"structure"` + + // TCP or UDP protocols: The range of ports the rule applies to. + PortRange *PortRange `locationName:"portRange" type:"structure"` + + // The protocol. A value of -1 means all protocols. + Protocol *string `locationName:"protocol" type:"string"` + + // Indicates whether to allow or deny the traffic that matches the rule. + RuleAction *string `locationName:"ruleAction" type:"string" enum:"RuleAction"` + + // The rule number for the entry. ACL entries are processed in ascending order + // by rule number. + RuleNumber *int64 `locationName:"ruleNumber" type:"integer"` +} + +// String returns the string representation +func (s NetworkAclEntry) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkAclEntry) GoString() string { + return s.String() +} + +// Describes a network interface. +type NetworkInterface struct { + _ struct{} `type:"structure"` + + // The association information for an Elastic IP associated with the network + // interface. + Association *NetworkInterfaceAssociation `locationName:"association" type:"structure"` + + // The network interface attachment. + Attachment *NetworkInterfaceAttachment `locationName:"attachment" type:"structure"` + + // The Availability Zone. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // A description. + Description *string `locationName:"description" type:"string"` + + // Any security groups for the network interface. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The type of interface. + InterfaceType *string `locationName:"interfaceType" type:"string" enum:"NetworkInterfaceType"` + + // The MAC address. + MacAddress *string `locationName:"macAddress" type:"string"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The AWS account ID of the owner of the network interface. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The private DNS name. + PrivateDnsName *string `locationName:"privateDnsName" type:"string"` + + // The IP address of the network interface within the subnet. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The private IP addresses associated with the network interface. + PrivateIpAddresses []*NetworkInterfacePrivateIpAddress `locationName:"privateIpAddressesSet" locationNameList:"item" type:"list"` + + // The ID of the entity that launched the instance on your behalf (for example, + // AWS Management Console or Auto Scaling). + RequesterId *string `locationName:"requesterId" type:"string"` + + // Indicates whether the network interface is being managed by AWS. + RequesterManaged *bool `locationName:"requesterManaged" type:"boolean"` + + // Indicates whether traffic to or from the instance is validated. + SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` + + // The status of the network interface. + Status *string `locationName:"status" type:"string" enum:"NetworkInterfaceStatus"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string"` + + // Any tags assigned to the network interface. + TagSet []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s NetworkInterface) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkInterface) GoString() string { + return s.String() +} + +// Describes association information for an Elastic IP address. +type NetworkInterfaceAssociation struct { + _ struct{} `type:"structure"` + + // The allocation ID. + AllocationId *string `locationName:"allocationId" type:"string"` + + // The association ID. + AssociationId *string `locationName:"associationId" type:"string"` + + // The ID of the Elastic IP address owner. + IpOwnerId *string `locationName:"ipOwnerId" type:"string"` + + // The public DNS name. + PublicDnsName *string `locationName:"publicDnsName" type:"string"` + + // The address of the Elastic IP address bound to the network interface. + PublicIp *string `locationName:"publicIp" type:"string"` +} + +// String returns the string representation +func (s NetworkInterfaceAssociation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkInterfaceAssociation) GoString() string { + return s.String() +} + +// Describes a network interface attachment. +type NetworkInterfaceAttachment struct { + _ struct{} `type:"structure"` + + // The timestamp indicating when the attachment initiated. + AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` + + // The ID of the network interface attachment. + AttachmentId *string `locationName:"attachmentId" type:"string"` + + // Indicates whether the network interface is deleted when the instance is terminated. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The device index of the network interface attachment on the instance. + DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The AWS account ID of the owner of the instance. + InstanceOwnerId *string `locationName:"instanceOwnerId" type:"string"` + + // The attachment state. + Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` +} + +// String returns the string representation +func (s NetworkInterfaceAttachment) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkInterfaceAttachment) GoString() string { + return s.String() +} + +// Describes an attachment change. +type NetworkInterfaceAttachmentChanges struct { + _ struct{} `type:"structure"` + + // The ID of the network interface attachment. + AttachmentId *string `locationName:"attachmentId" type:"string"` + + // Indicates whether the network interface is deleted when the instance is terminated. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` +} + +// String returns the string representation +func (s NetworkInterfaceAttachmentChanges) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkInterfaceAttachmentChanges) GoString() string { + return s.String() +} + +// Describes the private IP address of a network interface. +type NetworkInterfacePrivateIpAddress struct { + _ struct{} `type:"structure"` + + // The association information for an Elastic IP address associated with the + // network interface. + Association *NetworkInterfaceAssociation `locationName:"association" type:"structure"` + + // Indicates whether this IP address is the primary private IP address of the + // network interface. + Primary *bool `locationName:"primary" type:"boolean"` + + // The private DNS name. + PrivateDnsName *string `locationName:"privateDnsName" type:"string"` + + // The private IP address. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` +} + +// String returns the string representation +func (s NetworkInterfacePrivateIpAddress) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NetworkInterfacePrivateIpAddress) GoString() string { + return s.String() +} + +type NewDhcpConfiguration struct { + _ struct{} `type:"structure"` + + Key *string `locationName:"key" type:"string"` + + Values []*string `locationName:"Value" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s NewDhcpConfiguration) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s NewDhcpConfiguration) GoString() string { + return s.String() +} + +// Describes the placement for the instance. +type Placement struct { + _ struct{} `type:"structure"` + + // The affinity setting for the instance on the Dedicated host. This parameter + // is not supported for the ImportInstance command. + Affinity *string `locationName:"affinity" type:"string"` + + // The Availability Zone of the instance. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The name of the placement group the instance is in (for cluster compute instances). + GroupName *string `locationName:"groupName" type:"string"` + + // The ID of the Dedicted host on which the instance resides. This parameter + // is not support for the ImportInstance command. + HostId *string `locationName:"hostId" type:"string"` + + // The tenancy of the instance (if the instance is running in a VPC). An instance + // with a tenancy of dedicated runs on single-tenant hardware. The host tenancy + // is not supported for the ImportInstance command. + Tenancy *string `locationName:"tenancy" type:"string" enum:"Tenancy"` +} + +// String returns the string representation +func (s Placement) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Placement) GoString() string { + return s.String() +} + +// Describes a placement group. +type PlacementGroup struct { + _ struct{} `type:"structure"` + + // The name of the placement group. + GroupName *string `locationName:"groupName" type:"string"` + + // The state of the placement group. + State *string `locationName:"state" type:"string" enum:"PlacementGroupState"` + + // The placement strategy. + Strategy *string `locationName:"strategy" type:"string" enum:"PlacementStrategy"` +} + +// String returns the string representation +func (s PlacementGroup) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PlacementGroup) GoString() string { + return s.String() +} + +// Describes a range of ports. +type PortRange struct { + _ struct{} `type:"structure"` + + // The first port in the range. + From *int64 `locationName:"from" type:"integer"` + + // The last port in the range. + To *int64 `locationName:"to" type:"integer"` +} + +// String returns the string representation +func (s PortRange) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PortRange) GoString() string { + return s.String() +} + +// Describes prefixes for AWS services. +type PrefixList struct { + _ struct{} `type:"structure"` + + // The IP address range of the AWS service. + Cidrs []*string `locationName:"cidrSet" locationNameList:"item" type:"list"` + + // The ID of the prefix. + PrefixListId *string `locationName:"prefixListId" type:"string"` + + // The name of the prefix. + PrefixListName *string `locationName:"prefixListName" type:"string"` +} + +// String returns the string representation +func (s PrefixList) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PrefixList) GoString() string { + return s.String() +} + +// The ID of the prefix. +type PrefixListId struct { + _ struct{} `type:"structure"` + + // The ID of the prefix. + PrefixListId *string `locationName:"prefixListId" type:"string"` +} + +// String returns the string representation +func (s PrefixListId) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PrefixListId) GoString() string { + return s.String() +} + +// Describes the price for a Reserved Instance. +type PriceSchedule struct { + _ struct{} `type:"structure"` + + // The current price schedule, as determined by the term remaining for the Reserved + // Instance in the listing. + // + // A specific price schedule is always in effect, but only one price schedule + // can be active at any time. Take, for example, a Reserved Instance listing + // that has five months remaining in its term. When you specify price schedules + // for five months and two months, this means that schedule 1, covering the + // first three months of the remaining term, will be active during months 5, + // 4, and 3. Then schedule 2, covering the last two months of the term, will + // be active for months 2 and 1. + Active *bool `locationName:"active" type:"boolean"` + + // The currency for transacting the Reserved Instance resale. At this time, + // the only supported currency is USD. + CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` + + // The fixed price for the term. + Price *float64 `locationName:"price" type:"double"` + + // The number of months remaining in the reservation. For example, 2 is the + // second to the last month before the capacity reservation expires. + Term *int64 `locationName:"term" type:"long"` +} + +// String returns the string representation +func (s PriceSchedule) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PriceSchedule) GoString() string { + return s.String() +} + +// Describes the price for a Reserved Instance. +type PriceScheduleSpecification struct { + _ struct{} `type:"structure"` + + // The currency for transacting the Reserved Instance resale. At this time, + // the only supported currency is USD. + CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` + + // The fixed price for the term. + Price *float64 `locationName:"price" type:"double"` + + // The number of months remaining in the reservation. For example, 2 is the + // second to the last month before the capacity reservation expires. + Term *int64 `locationName:"term" type:"long"` +} + +// String returns the string representation +func (s PriceScheduleSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PriceScheduleSpecification) GoString() string { + return s.String() +} + +// Describes a Reserved Instance offering. +type PricingDetail struct { + _ struct{} `type:"structure"` + + // The number of reservations available for the price. + Count *int64 `locationName:"count" type:"integer"` + + // The price per instance. + Price *float64 `locationName:"price" type:"double"` +} + +// String returns the string representation +func (s PricingDetail) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PricingDetail) GoString() string { + return s.String() +} + +// Describes a secondary private IP address for a network interface. +type PrivateIpAddressSpecification struct { + _ struct{} `type:"structure"` + + // Indicates whether the private IP address is the primary private IP address. + // Only one IP address can be designated as primary. + Primary *bool `locationName:"primary" type:"boolean"` + + // The private IP addresses. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string" required:"true"` +} + +// String returns the string representation +func (s PrivateIpAddressSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PrivateIpAddressSpecification) GoString() string { + return s.String() +} + +// Describes a product code. +type ProductCode struct { + _ struct{} `type:"structure"` + + // The product code. + ProductCodeId *string `locationName:"productCode" type:"string"` + + // The type of product code. + ProductCodeType *string `locationName:"type" type:"string" enum:"ProductCodeValues"` +} + +// String returns the string representation +func (s ProductCode) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ProductCode) GoString() string { + return s.String() +} + +// Describes a virtual private gateway propagating route. +type PropagatingVgw struct { + _ struct{} `type:"structure"` + + // The ID of the virtual private gateway (VGW). + GatewayId *string `locationName:"gatewayId" type:"string"` +} + +// String returns the string representation +func (s PropagatingVgw) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PropagatingVgw) GoString() string { + return s.String() +} + +// Describes a request to purchase Scheduled Instances. +type PurchaseRequest struct { + _ struct{} `type:"structure"` + + // The number of instances. + InstanceCount *int64 `type:"integer"` + + // The purchase token. + PurchaseToken *string `type:"string"` +} + +// String returns the string representation +func (s PurchaseRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PurchaseRequest) GoString() string { + return s.String() +} + +type PurchaseReservedInstancesOfferingInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The number of Reserved Instances to purchase. + InstanceCount *int64 `type:"integer" required:"true"` + + // Specified for Reserved Instance Marketplace offerings to limit the total + // order and ensure that the Reserved Instances are not purchased at unexpected + // prices. + LimitPrice *ReservedInstanceLimitPrice `locationName:"limitPrice" type:"structure"` + + // The ID of the Reserved Instance offering to purchase. + ReservedInstancesOfferingId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s PurchaseReservedInstancesOfferingInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PurchaseReservedInstancesOfferingInput) GoString() string { + return s.String() +} + +type PurchaseReservedInstancesOfferingOutput struct { + _ struct{} `type:"structure"` + + // The IDs of the purchased Reserved Instances. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` +} + +// String returns the string representation +func (s PurchaseReservedInstancesOfferingOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PurchaseReservedInstancesOfferingOutput) GoString() string { + return s.String() +} + +// Contains the parameters for PurchaseScheduledInstances. +type PurchaseScheduledInstancesInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier that ensures the idempotency of the request. + // For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // One or more purchase requests. + PurchaseRequests []*PurchaseRequest `locationName:"PurchaseRequest" locationNameList:"PurchaseRequest" type:"list" required:"true"` +} + +// String returns the string representation +func (s PurchaseScheduledInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PurchaseScheduledInstancesInput) GoString() string { + return s.String() +} + +// Contains the output of PurchaseScheduledInstances. +type PurchaseScheduledInstancesOutput struct { + _ struct{} `type:"structure"` + + // Information about the Scheduled Instances. + ScheduledInstanceSet []*ScheduledInstance `locationName:"scheduledInstanceSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s PurchaseScheduledInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PurchaseScheduledInstancesOutput) GoString() string { + return s.String() +} + +type RebootInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s RebootInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RebootInstancesInput) GoString() string { + return s.String() +} + +type RebootInstancesOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s RebootInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RebootInstancesOutput) GoString() string { + return s.String() +} + +// Describes a recurring charge. +type RecurringCharge struct { + _ struct{} `type:"structure"` + + // The amount of the recurring charge. + Amount *float64 `locationName:"amount" type:"double"` + + // The frequency of the recurring charge. + Frequency *string `locationName:"frequency" type:"string" enum:"RecurringChargeFrequency"` +} + +// String returns the string representation +func (s RecurringCharge) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RecurringCharge) GoString() string { + return s.String() +} + +// Describes a region. +type Region struct { + _ struct{} `type:"structure"` + + // The region service endpoint. + Endpoint *string `locationName:"regionEndpoint" type:"string"` + + // The name of the region. + RegionName *string `locationName:"regionName" type:"string"` +} + +// String returns the string representation +func (s Region) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Region) GoString() string { + return s.String() +} + +type RegisterImageInput struct { + _ struct{} `type:"structure"` + + // The architecture of the AMI. + // + // Default: For Amazon EBS-backed AMIs, i386. For instance store-backed AMIs, + // the architecture specified in the manifest file. + Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` + + // One or more block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"BlockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` + + // A description for your AMI. + Description *string `locationName:"description" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The full path to your AMI manifest in Amazon S3 storage. + ImageLocation *string `type:"string"` + + // The ID of the kernel. + KernelId *string `locationName:"kernelId" type:"string"` + + // A name for your AMI. + // + // Constraints: 3-128 alphanumeric characters, parentheses (()), square brackets + // ([]), spaces ( ), periods (.), slashes (/), dashes (-), single quotes ('), + // at-signs (@), or underscores(_) + Name *string `locationName:"name" type:"string" required:"true"` + + // The ID of the RAM disk. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + // The name of the root device (for example, /dev/sda1, or /dev/xvda). + RootDeviceName *string `locationName:"rootDeviceName" type:"string"` + + // Set to simple to enable enhanced networking for the AMI and any instances + // that you launch from the AMI. + // + // There is no way to disable enhanced networking at this time. + // + // This option is supported only for HVM AMIs. Specifying this option with + // a PV AMI can make instances launched from the AMI unreachable. + SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` + + // The type of virtualization. + // + // Default: paravirtual + VirtualizationType *string `locationName:"virtualizationType" type:"string"` +} + +// String returns the string representation +func (s RegisterImageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RegisterImageInput) GoString() string { + return s.String() +} + +type RegisterImageOutput struct { + _ struct{} `type:"structure"` + + // The ID of the newly registered AMI. + ImageId *string `locationName:"imageId" type:"string"` +} + +// String returns the string representation +func (s RegisterImageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RegisterImageOutput) GoString() string { + return s.String() +} + +type RejectVpcPeeringConnectionInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string" required:"true"` +} + +// String returns the string representation +func (s RejectVpcPeeringConnectionInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RejectVpcPeeringConnectionInput) GoString() string { + return s.String() +} + +type RejectVpcPeeringConnectionOutput struct { + _ struct{} `type:"structure"` + + // Returns true if the request succeeds; otherwise, it returns an error. + Return *bool `locationName:"return" type:"boolean"` +} + +// String returns the string representation +func (s RejectVpcPeeringConnectionOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RejectVpcPeeringConnectionOutput) GoString() string { + return s.String() +} + +type ReleaseAddressInput struct { + _ struct{} `type:"structure"` + + // [EC2-VPC] The allocation ID. Required for EC2-VPC. + AllocationId *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // [EC2-Classic] The Elastic IP address. Required for EC2-Classic. + PublicIp *string `type:"string"` +} + +// String returns the string representation +func (s ReleaseAddressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReleaseAddressInput) GoString() string { + return s.String() +} + +type ReleaseAddressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ReleaseAddressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReleaseAddressOutput) GoString() string { + return s.String() +} + +type ReleaseHostsInput struct { + _ struct{} `type:"structure"` + + // The IDs of the Dedicated hosts you want to release. + HostIds []*string `locationName:"hostId" locationNameList:"item" type:"list" required:"true"` +} + +// String returns the string representation +func (s ReleaseHostsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReleaseHostsInput) GoString() string { + return s.String() +} + +type ReleaseHostsOutput struct { + _ struct{} `type:"structure"` + + // The IDs of the Dedicated hosts that were successfully released. + Successful []*string `locationName:"successful" locationNameList:"item" type:"list"` + + // The IDs of the Dedicated hosts that could not be released, including an error + // message. + Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s ReleaseHostsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReleaseHostsOutput) GoString() string { + return s.String() +} + +type ReplaceNetworkAclAssociationInput struct { + _ struct{} `type:"structure"` + + // The ID of the current association between the original network ACL and the + // subnet. + AssociationId *string `locationName:"associationId" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the new network ACL to associate with the subnet. + NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` +} + +// String returns the string representation +func (s ReplaceNetworkAclAssociationInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceNetworkAclAssociationInput) GoString() string { + return s.String() +} + +type ReplaceNetworkAclAssociationOutput struct { + _ struct{} `type:"structure"` + + // The ID of the new association. + NewAssociationId *string `locationName:"newAssociationId" type:"string"` +} + +// String returns the string representation +func (s ReplaceNetworkAclAssociationOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceNetworkAclAssociationOutput) GoString() string { + return s.String() +} + +type ReplaceNetworkAclEntryInput struct { + _ struct{} `type:"structure"` + + // The network range to allow or deny, in CIDR notation. + CidrBlock *string `locationName:"cidrBlock" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Indicates whether to replace the egress rule. + // + // Default: If no value is specified, we replace the ingress rule. + Egress *bool `locationName:"egress" type:"boolean" required:"true"` + + // ICMP protocol: The ICMP type and code. Required if specifying 1 (ICMP) for + // the protocol. + IcmpTypeCode *IcmpTypeCode `locationName:"Icmp" type:"structure"` + + // The ID of the ACL. + NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` + + // TCP or UDP protocols: The range of ports the rule applies to. Required if + // specifying 6 (TCP) or 17 (UDP) for the protocol. + PortRange *PortRange `locationName:"portRange" type:"structure"` + + // The IP protocol. You can specify all or -1 to mean all protocols. + Protocol *string `locationName:"protocol" type:"string" required:"true"` + + // Indicates whether to allow or deny the traffic that matches the rule. + RuleAction *string `locationName:"ruleAction" type:"string" required:"true" enum:"RuleAction"` + + // The rule number of the entry to replace. + RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` +} + +// String returns the string representation +func (s ReplaceNetworkAclEntryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceNetworkAclEntryInput) GoString() string { + return s.String() +} + +type ReplaceNetworkAclEntryOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ReplaceNetworkAclEntryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceNetworkAclEntryOutput) GoString() string { + return s.String() +} + +type ReplaceRouteInput struct { + _ struct{} `type:"structure"` + + // The CIDR address block used for the destination match. The value you provide + // must match the CIDR of an existing route in the table. + DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of an Internet gateway or virtual private gateway. + GatewayId *string `locationName:"gatewayId" type:"string"` + + // The ID of a NAT instance in your VPC. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The ID of a NAT gateway. + NatGatewayId *string `locationName:"natGatewayId" type:"string"` + + // The ID of a network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` + + // The ID of a VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` +} + +// String returns the string representation +func (s ReplaceRouteInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceRouteInput) GoString() string { + return s.String() +} + +type ReplaceRouteOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ReplaceRouteOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceRouteOutput) GoString() string { + return s.String() +} + +type ReplaceRouteTableAssociationInput struct { + _ struct{} `type:"structure"` + + // The association ID. + AssociationId *string `locationName:"associationId" type:"string" required:"true"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the new route table to associate with the subnet. + RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` +} + +// String returns the string representation +func (s ReplaceRouteTableAssociationInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceRouteTableAssociationInput) GoString() string { + return s.String() +} + +type ReplaceRouteTableAssociationOutput struct { + _ struct{} `type:"structure"` + + // The ID of the new association. + NewAssociationId *string `locationName:"newAssociationId" type:"string"` +} + +// String returns the string representation +func (s ReplaceRouteTableAssociationOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplaceRouteTableAssociationOutput) GoString() string { + return s.String() +} + +type ReportInstanceStatusInput struct { + _ struct{} `type:"structure"` + + // Descriptive text about the health state of your instance. + Description *string `locationName:"description" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The time at which the reported instance health state ended. + EndTime *time.Time `locationName:"endTime" type:"timestamp" timestampFormat:"iso8601"` + + // One or more instances. + Instances []*string `locationName:"instanceId" locationNameList:"InstanceId" type:"list" required:"true"` + + // One or more reason codes that describes the health state of your instance. + // + // instance-stuck-in-state: My instance is stuck in a state. + // + // unresponsive: My instance is unresponsive. + // + // not-accepting-credentials: My instance is not accepting my credentials. + // + // password-not-available: A password is not available for my instance. + // + // performance-network: My instance is experiencing performance problems which + // I believe are network related. + // + // performance-instance-store: My instance is experiencing performance problems + // which I believe are related to the instance stores. + // + // performance-ebs-volume: My instance is experiencing performance problems + // which I believe are related to an EBS volume. + // + // performance-other: My instance is experiencing performance problems. + // + // other: [explain using the description parameter] + ReasonCodes []*string `locationName:"reasonCode" locationNameList:"item" type:"list" required:"true"` + + // The time at which the reported instance health state began. + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` + + // The status of all instances listed. + Status *string `locationName:"status" type:"string" required:"true" enum:"ReportStatusType"` +} + +// String returns the string representation +func (s ReportInstanceStatusInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReportInstanceStatusInput) GoString() string { + return s.String() +} + +type ReportInstanceStatusOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ReportInstanceStatusOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReportInstanceStatusOutput) GoString() string { + return s.String() +} + +// Contains the parameters for RequestSpotFleet. +type RequestSpotFleetInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The configuration for the Spot fleet request. + SpotFleetRequestConfig *SpotFleetRequestConfigData `locationName:"spotFleetRequestConfig" type:"structure" required:"true"` +} + +// String returns the string representation +func (s RequestSpotFleetInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RequestSpotFleetInput) GoString() string { + return s.String() +} + +// Contains the output of RequestSpotFleet. +type RequestSpotFleetOutput struct { + _ struct{} `type:"structure"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` +} + +// String returns the string representation +func (s RequestSpotFleetOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RequestSpotFleetOutput) GoString() string { + return s.String() +} + +// Contains the parameters for RequestSpotInstances. +type RequestSpotInstancesInput struct { + _ struct{} `type:"structure"` + + // The user-specified name for a logical grouping of bids. + // + // When you specify an Availability Zone group in a Spot Instance request, + // all Spot instances in the request are launched in the same Availability Zone. + // Instance proximity is maintained with this parameter, but the choice of Availability + // Zone is not. The group applies only to bids for Spot Instances of the same + // instance type. Any additional Spot instance requests that are specified with + // the same Availability Zone group name are launched in that same Availability + // Zone, as long as at least one instance from the group is still active. + // + // If there is no active instance running in the Availability Zone group that + // you specify for a new Spot instance request (all instances are terminated, + // the bid is expired, or the bid falls below current market), then Amazon EC2 + // launches the instance in any Availability Zone where the constraint can be + // met. Consequently, the subsequent set of Spot instances could be placed in + // a different zone from the original request, even if you specified the same + // Availability Zone group. + // + // Default: Instances are launched in any available Availability Zone. + AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"` + + // The required duration for the Spot instances, in minutes. This value must + // be a multiple of 60 (60, 120, 180, 240, 300, or 360). + // + // The duration period starts as soon as your Spot instance receives its instance + // ID. At the end of the duration period, Amazon EC2 marks the Spot instance + // for termination and provides a Spot instance termination notice, which gives + // the instance a two-minute warning before it terminates. + // + // Note that you can't specify an Availability Zone group or a launch group + // if you specify a duration. + BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"` + + // Unique, case-sensitive identifier that you provide to ensure the idempotency + // of the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) + // in the Amazon Elastic Compute Cloud User Guide. + ClientToken *string `locationName:"clientToken" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The maximum number of Spot instances to launch. + // + // Default: 1 + InstanceCount *int64 `locationName:"instanceCount" type:"integer"` + + // The instance launch group. Launch groups are Spot instances that launch together + // and terminate together. + // + // Default: Instances are launched and terminated individually + LaunchGroup *string `locationName:"launchGroup" type:"string"` + + // Describes the launch specification for an instance. + LaunchSpecification *RequestSpotLaunchSpecification `type:"structure"` + + // The maximum hourly price (bid) for any Spot instance launched to fulfill + // the request. + SpotPrice *string `locationName:"spotPrice" type:"string" required:"true"` + + // The Spot instance request type. + // + // Default: one-time + Type *string `locationName:"type" type:"string" enum:"SpotInstanceType"` + + // The start date of the request. If this is a one-time request, the request + // becomes active at this date and time and remains active until all instances + // launch, the request expires, or the request is canceled. If the request is + // persistent, the request becomes active at this date and time and remains + // active until it expires or is canceled. + // + // Default: The request is effective indefinitely. + ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` + + // The end date of the request. If this is a one-time request, the request remains + // active until all instances launch, the request is canceled, or this date + // is reached. If the request is persistent, it remains active until it is canceled + // or this date and time is reached. + // + // Default: The request is effective indefinitely. + ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s RequestSpotInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RequestSpotInstancesInput) GoString() string { + return s.String() +} + +// Contains the output of RequestSpotInstances. +type RequestSpotInstancesOutput struct { + _ struct{} `type:"structure"` + + // One or more Spot instance requests. + SpotInstanceRequests []*SpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s RequestSpotInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RequestSpotInstancesOutput) GoString() string { + return s.String() +} + +// Describes the launch specification for an instance. +type RequestSpotLaunchSpecification struct { + _ struct{} `type:"structure"` + + // Deprecated. + AddressingType *string `locationName:"addressingType" type:"string"` + + // One or more block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // Indicates whether the instance is optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS + // Optimized instance. + // + // Default: false + EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` + + // The IAM instance profile. + IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` + + // The ID of the AMI. + ImageId *string `locationName:"imageId" type:"string"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The ID of the kernel. + KernelId *string `locationName:"kernelId" type:"string"` + + // The name of the key pair. + KeyName *string `locationName:"keyName" type:"string"` + + // Describes the monitoring for the instance. + Monitoring *RunInstancesMonitoringEnabled `locationName:"monitoring" type:"structure"` + + // One or more network interfaces. + NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"NetworkInterface" locationNameList:"item" type:"list"` + + // The placement information for the instance. + Placement *SpotPlacement `locationName:"placement" type:"structure"` + + // The ID of the RAM disk. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"item" type:"list"` + + SecurityGroups []*string `locationName:"SecurityGroup" locationNameList:"item" type:"list"` + + // The ID of the subnet in which to launch the instance. + SubnetId *string `locationName:"subnetId" type:"string"` + + // The Base64-encoded MIME user data to make available to the instances. + UserData *string `locationName:"userData" type:"string"` +} + +// String returns the string representation +func (s RequestSpotLaunchSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RequestSpotLaunchSpecification) GoString() string { + return s.String() +} + +// Describes a reservation. +type Reservation struct { + _ struct{} `type:"structure"` + + // One or more security groups. + Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // One or more instances. + Instances []*Instance `locationName:"instancesSet" locationNameList:"item" type:"list"` + + // The ID of the AWS account that owns the reservation. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The ID of the requester that launched the instances on your behalf (for example, + // AWS Management Console or Auto Scaling). + RequesterId *string `locationName:"requesterId" type:"string"` + + // The ID of the reservation. + ReservationId *string `locationName:"reservationId" type:"string"` +} + +// String returns the string representation +func (s Reservation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Reservation) GoString() string { + return s.String() +} + +// Describes the limit price of a Reserved Instance offering. +type ReservedInstanceLimitPrice struct { + _ struct{} `type:"structure"` + + // Used for Reserved Instance Marketplace offerings. Specifies the limit price + // on the total order (instanceCount * price). + Amount *float64 `locationName:"amount" type:"double"` + + // The currency in which the limitPrice amount is specified. At this time, the + // only supported currency is USD. + CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` +} + +// String returns the string representation +func (s ReservedInstanceLimitPrice) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstanceLimitPrice) GoString() string { + return s.String() +} + +// Describes a Reserved Instance. +type ReservedInstances struct { + _ struct{} `type:"structure"` + + // The Availability Zone in which the Reserved Instance can be used. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The currency of the Reserved Instance. It's specified using ISO 4217 standard + // currency codes. At this time, the only supported currency is USD. + CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` + + // The duration of the Reserved Instance, in seconds. + Duration *int64 `locationName:"duration" type:"long"` + + // The time when the Reserved Instance expires. + End *time.Time `locationName:"end" type:"timestamp" timestampFormat:"iso8601"` + + // The purchase price of the Reserved Instance. + FixedPrice *float64 `locationName:"fixedPrice" type:"float"` + + // The number of reservations purchased. + InstanceCount *int64 `locationName:"instanceCount" type:"integer"` + + // The tenancy of the instance. + InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` + + // The instance type on which the Reserved Instance can be used. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The Reserved Instance offering type. + OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` + + // The Reserved Instance product platform description. + ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` + + // The recurring charge tag assigned to the resource. + RecurringCharges []*RecurringCharge `locationName:"recurringCharges" locationNameList:"item" type:"list"` + + // The ID of the Reserved Instance. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` + + // The date and time the Reserved Instance started. + Start *time.Time `locationName:"start" type:"timestamp" timestampFormat:"iso8601"` + + // The state of the Reserved Instance purchase. + State *string `locationName:"state" type:"string" enum:"ReservedInstanceState"` + + // Any tags assigned to the resource. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The usage price of the Reserved Instance, per hour. + UsagePrice *float64 `locationName:"usagePrice" type:"float"` +} + +// String returns the string representation +func (s ReservedInstances) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstances) GoString() string { + return s.String() +} + +// Describes the configuration settings for the modified Reserved Instances. +type ReservedInstancesConfiguration struct { + _ struct{} `type:"structure"` + + // The Availability Zone for the modified Reserved Instances. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The number of modified Reserved Instances. + InstanceCount *int64 `locationName:"instanceCount" type:"integer"` + + // The instance type for the modified Reserved Instances. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The network platform of the modified Reserved Instances, which is either + // EC2-Classic or EC2-VPC. + Platform *string `locationName:"platform" type:"string"` +} + +// String returns the string representation +func (s ReservedInstancesConfiguration) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesConfiguration) GoString() string { + return s.String() +} + +// Describes the ID of a Reserved Instance. +type ReservedInstancesId struct { + _ struct{} `type:"structure"` + + // The ID of the Reserved Instance. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` +} + +// String returns the string representation +func (s ReservedInstancesId) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesId) GoString() string { + return s.String() +} + +// Describes a Reserved Instance listing. +type ReservedInstancesListing struct { + _ struct{} `type:"structure"` + + // A unique, case-sensitive key supplied by the client to ensure that the request + // is idempotent. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `locationName:"clientToken" type:"string"` + + // The time the listing was created. + CreateDate *time.Time `locationName:"createDate" type:"timestamp" timestampFormat:"iso8601"` + + // The number of instances in this state. + InstanceCounts []*InstanceCount `locationName:"instanceCounts" locationNameList:"item" type:"list"` + + // The price of the Reserved Instance listing. + PriceSchedules []*PriceSchedule `locationName:"priceSchedules" locationNameList:"item" type:"list"` + + // The ID of the Reserved Instance. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` + + // The ID of the Reserved Instance listing. + ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string"` + + // The status of the Reserved Instance listing. + Status *string `locationName:"status" type:"string" enum:"ListingStatus"` + + // The reason for the current status of the Reserved Instance listing. The response + // can be blank. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // Any tags assigned to the resource. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The last modified timestamp of the listing. + UpdateDate *time.Time `locationName:"updateDate" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s ReservedInstancesListing) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesListing) GoString() string { + return s.String() +} + +// Describes a Reserved Instance modification. +type ReservedInstancesModification struct { + _ struct{} `type:"structure"` + + // A unique, case-sensitive key supplied by the client to ensure that the request + // is idempotent. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `locationName:"clientToken" type:"string"` + + // The time when the modification request was created. + CreateDate *time.Time `locationName:"createDate" type:"timestamp" timestampFormat:"iso8601"` + + // The time for the modification to become effective. + EffectiveDate *time.Time `locationName:"effectiveDate" type:"timestamp" timestampFormat:"iso8601"` + + // Contains target configurations along with their corresponding new Reserved + // Instance IDs. + ModificationResults []*ReservedInstancesModificationResult `locationName:"modificationResultSet" locationNameList:"item" type:"list"` + + // The IDs of one or more Reserved Instances. + ReservedInstancesIds []*ReservedInstancesId `locationName:"reservedInstancesSet" locationNameList:"item" type:"list"` + + // A unique ID for the Reserved Instance modification. + ReservedInstancesModificationId *string `locationName:"reservedInstancesModificationId" type:"string"` + + // The status of the Reserved Instances modification request. + Status *string `locationName:"status" type:"string"` + + // The reason for the status. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // The time when the modification request was last updated. + UpdateDate *time.Time `locationName:"updateDate" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s ReservedInstancesModification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesModification) GoString() string { + return s.String() +} + +type ReservedInstancesModificationResult struct { + _ struct{} `type:"structure"` + + // The ID for the Reserved Instances that were created as part of the modification + // request. This field is only available when the modification is fulfilled. + ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` + + // The target Reserved Instances configurations supplied as part of the modification + // request. + TargetConfiguration *ReservedInstancesConfiguration `locationName:"targetConfiguration" type:"structure"` +} + +// String returns the string representation +func (s ReservedInstancesModificationResult) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesModificationResult) GoString() string { + return s.String() +} + +// Describes a Reserved Instance offering. +type ReservedInstancesOffering struct { + _ struct{} `type:"structure"` + + // The Availability Zone in which the Reserved Instance can be used. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The currency of the Reserved Instance offering you are purchasing. It's specified + // using ISO 4217 standard currency codes. At this time, the only supported + // currency is USD. + CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` + + // The duration of the Reserved Instance, in seconds. + Duration *int64 `locationName:"duration" type:"long"` + + // The purchase price of the Reserved Instance. + FixedPrice *float64 `locationName:"fixedPrice" type:"float"` + + // The tenancy of the instance. + InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` + + // The instance type on which the Reserved Instance can be used. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // Indicates whether the offering is available through the Reserved Instance + // Marketplace (resale) or AWS. If it's a Reserved Instance Marketplace offering, + // this is true. + Marketplace *bool `locationName:"marketplace" type:"boolean"` + + // The Reserved Instance offering type. + OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` + + // The pricing details of the Reserved Instance offering. + PricingDetails []*PricingDetail `locationName:"pricingDetailsSet" locationNameList:"item" type:"list"` + + // The Reserved Instance product platform description. + ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` + + // The recurring charge tag assigned to the resource. + RecurringCharges []*RecurringCharge `locationName:"recurringCharges" locationNameList:"item" type:"list"` + + // The ID of the Reserved Instance offering. + ReservedInstancesOfferingId *string `locationName:"reservedInstancesOfferingId" type:"string"` + + // The usage price of the Reserved Instance, per hour. + UsagePrice *float64 `locationName:"usagePrice" type:"float"` +} + +// String returns the string representation +func (s ReservedInstancesOffering) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReservedInstancesOffering) GoString() string { + return s.String() +} + +type ResetImageAttributeInput struct { + _ struct{} `type:"structure"` + + // The attribute to reset (currently you can only reset the launch permission + // attribute). + Attribute *string `type:"string" required:"true" enum:"ResetImageAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the AMI. + ImageId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s ResetImageAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetImageAttributeInput) GoString() string { + return s.String() +} + +type ResetImageAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ResetImageAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetImageAttributeOutput) GoString() string { + return s.String() +} + +type ResetInstanceAttributeInput struct { + _ struct{} `type:"structure"` + + // The attribute to reset. + Attribute *string `locationName:"attribute" type:"string" required:"true" enum:"InstanceAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string" required:"true"` +} + +// String returns the string representation +func (s ResetInstanceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetInstanceAttributeInput) GoString() string { + return s.String() +} + +type ResetInstanceAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ResetInstanceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetInstanceAttributeOutput) GoString() string { + return s.String() +} + +type ResetNetworkInterfaceAttributeInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` + + // The source/destination checking attribute. Resets the value to true. + SourceDestCheck *string `locationName:"sourceDestCheck" type:"string"` +} + +// String returns the string representation +func (s ResetNetworkInterfaceAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetNetworkInterfaceAttributeInput) GoString() string { + return s.String() +} + +type ResetNetworkInterfaceAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ResetNetworkInterfaceAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetNetworkInterfaceAttributeOutput) GoString() string { + return s.String() +} + +type ResetSnapshotAttributeInput struct { + _ struct{} `type:"structure"` + + // The attribute to reset. Currently, only the attribute for permission to create + // volumes can be reset. + Attribute *string `type:"string" required:"true" enum:"SnapshotAttributeName"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The ID of the snapshot. + SnapshotId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s ResetSnapshotAttributeInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetSnapshotAttributeInput) GoString() string { + return s.String() +} + +type ResetSnapshotAttributeOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s ResetSnapshotAttributeOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResetSnapshotAttributeOutput) GoString() string { + return s.String() +} + +type RestoreAddressToClassicInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string" required:"true"` +} + +// String returns the string representation +func (s RestoreAddressToClassicInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RestoreAddressToClassicInput) GoString() string { + return s.String() +} + +type RestoreAddressToClassicOutput struct { + _ struct{} `type:"structure"` + + // The Elastic IP address. + PublicIp *string `locationName:"publicIp" type:"string"` + + // The move status for the IP address. + Status *string `locationName:"status" type:"string" enum:"Status"` +} + +// String returns the string representation +func (s RestoreAddressToClassicOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RestoreAddressToClassicOutput) GoString() string { + return s.String() +} + +type RevokeSecurityGroupEgressInput struct { + _ struct{} `type:"structure"` + + // The CIDR IP address range. We recommend that you specify the CIDR range in + // a set of IP permissions instead. + CidrIp *string `locationName:"cidrIp" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The start of port range for the TCP and UDP protocols, or an ICMP type number. + // We recommend that you specify the port range in a set of IP permissions instead. + FromPort *int64 `locationName:"fromPort" type:"integer"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string" required:"true"` + + // A set of IP permissions. You can't specify a destination security group and + // a CIDR IP address range. + IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` + + // The IP protocol name or number. We recommend that you specify the protocol + // in a set of IP permissions instead. + IpProtocol *string `locationName:"ipProtocol" type:"string"` + + // The name of a destination security group. To revoke outbound access to a + // destination security group, we recommend that you use a set of IP permissions + // instead. + SourceSecurityGroupName *string `locationName:"sourceSecurityGroupName" type:"string"` + + // The AWS account number for a destination security group. To revoke outbound + // access to a destination security group, we recommend that you use a set of + // IP permissions instead. + SourceSecurityGroupOwnerId *string `locationName:"sourceSecurityGroupOwnerId" type:"string"` + + // The end of port range for the TCP and UDP protocols, or an ICMP type number. + // We recommend that you specify the port range in a set of IP permissions instead. + ToPort *int64 `locationName:"toPort" type:"integer"` +} + +// String returns the string representation +func (s RevokeSecurityGroupEgressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RevokeSecurityGroupEgressInput) GoString() string { + return s.String() +} + +type RevokeSecurityGroupEgressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s RevokeSecurityGroupEgressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RevokeSecurityGroupEgressOutput) GoString() string { + return s.String() +} + +type RevokeSecurityGroupIngressInput struct { + _ struct{} `type:"structure"` + + // The CIDR IP address range. You can't specify this parameter when specifying + // a source security group. + CidrIp *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // The start of port range for the TCP and UDP protocols, or an ICMP type number. + // For the ICMP type number, use -1 to specify all ICMP types. + FromPort *int64 `type:"integer"` + + // The ID of the security group. Required for a security group in a nondefault + // VPC. + GroupId *string `type:"string"` + + // [EC2-Classic, default VPC] The name of the security group. + GroupName *string `type:"string"` + + // A set of IP permissions. You can't specify a source security group and a + // CIDR IP address range. + IpPermissions []*IpPermission `locationNameList:"item" type:"list"` + + // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). + // Use -1 to specify all. + IpProtocol *string `type:"string"` + + // [EC2-Classic, default VPC] The name of the source security group. You can't + // specify this parameter in combination with the following parameters: the + // CIDR IP address range, the start of the port range, the IP protocol, and + // the end of the port range. For EC2-VPC, the source security group must be + // in the same VPC. + SourceSecurityGroupName *string `type:"string"` + + // [EC2-Classic, default VPC] The AWS account ID of the source security group. + // For EC2-VPC, the source security group must be in the same VPC. You can't + // specify this parameter in combination with the following parameters: the + // CIDR IP address range, the IP protocol, the start of the port range, and + // the end of the port range. To revoke a specific rule for an IP protocol and + // port range, use a set of IP permissions instead. + SourceSecurityGroupOwnerId *string `type:"string"` + + // The end of port range for the TCP and UDP protocols, or an ICMP code number. + // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. + ToPort *int64 `type:"integer"` +} + +// String returns the string representation +func (s RevokeSecurityGroupIngressInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RevokeSecurityGroupIngressInput) GoString() string { + return s.String() +} + +type RevokeSecurityGroupIngressOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s RevokeSecurityGroupIngressOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RevokeSecurityGroupIngressOutput) GoString() string { + return s.String() +} + +// Describes a route in a route table. +type Route struct { + _ struct{} `type:"structure"` + + // The CIDR block used for the destination match. + DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string"` + + // The prefix of the AWS service. + DestinationPrefixListId *string `locationName:"destinationPrefixListId" type:"string"` + + // The ID of a gateway attached to your VPC. + GatewayId *string `locationName:"gatewayId" type:"string"` + + // The ID of a NAT instance in your VPC. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The AWS account ID of the owner of the instance. + InstanceOwnerId *string `locationName:"instanceOwnerId" type:"string"` + + // The ID of a NAT gateway. + NatGatewayId *string `locationName:"natGatewayId" type:"string"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` + + // Describes how the route was created. + // + // CreateRouteTable indicates that route was automatically created when the + // route table was created. CreateRoute indicates that the route was manually + // added to the route table. EnableVgwRoutePropagation indicates that the route + // was propagated by route propagation. + Origin *string `locationName:"origin" type:"string" enum:"RouteOrigin"` + + // The state of the route. The blackhole state indicates that the route's target + // isn't available (for example, the specified gateway isn't attached to the + // VPC, or the specified NAT instance has been terminated). + State *string `locationName:"state" type:"string" enum:"RouteState"` + + // The ID of the VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` +} + +// String returns the string representation +func (s Route) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Route) GoString() string { + return s.String() +} + +// Describes a route table. +type RouteTable struct { + _ struct{} `type:"structure"` + + // The associations between the route table and one or more subnets. + Associations []*RouteTableAssociation `locationName:"associationSet" locationNameList:"item" type:"list"` + + // Any virtual private gateway (VGW) propagating routes. + PropagatingVgws []*PropagatingVgw `locationName:"propagatingVgwSet" locationNameList:"item" type:"list"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string"` + + // The routes in the route table. + Routes []*Route `locationName:"routeSet" locationNameList:"item" type:"list"` + + // Any tags assigned to the route table. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s RouteTable) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RouteTable) GoString() string { + return s.String() +} + +// Describes an association between a route table and a subnet. +type RouteTableAssociation struct { + _ struct{} `type:"structure"` + + // Indicates whether this is the main route table. + Main *bool `locationName:"main" type:"boolean"` + + // The ID of the association between a route table and a subnet. + RouteTableAssociationId *string `locationName:"routeTableAssociationId" type:"string"` + + // The ID of the route table. + RouteTableId *string `locationName:"routeTableId" type:"string"` + + // The ID of the subnet. A subnet ID is not returned for an implicit association. + SubnetId *string `locationName:"subnetId" type:"string"` +} + +// String returns the string representation +func (s RouteTableAssociation) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RouteTableAssociation) GoString() string { + return s.String() +} + +type RunInstancesInput struct { + _ struct{} `type:"structure"` + + // Reserved. + AdditionalInfo *string `locationName:"additionalInfo" type:"string"` + + // The block device mapping. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"BlockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` + + // Unique, case-sensitive identifier you provide to ensure the idempotency of + // the request. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + // + // Constraints: Maximum 64 ASCII characters + ClientToken *string `locationName:"clientToken" type:"string"` + + // If you set this parameter to true, you can't terminate the instance using + // the Amazon EC2 console, CLI, or API; otherwise, you can. If you set this + // parameter to true and then later want to be able to terminate the instance, + // you must first change the value of the disableApiTermination attribute to + // false using ModifyInstanceAttribute. Alternatively, if you set InstanceInitiatedShutdownBehavior + // to terminate, you can terminate the instance by running the shutdown command + // from the instance. + // + // Default: false + DisableApiTermination *bool `locationName:"disableApiTermination" type:"boolean"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Indicates whether the instance is optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS-optimized + // instance. + // + // Default: false + EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` + + // The IAM instance profile. + IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` + + // The ID of the AMI, which you can get by calling DescribeImages. + ImageId *string `type:"string" required:"true"` + + // Indicates whether an instance stops or terminates when you initiate shutdown + // from the instance (using the operating system command for system shutdown). + // + // Default: stop + InstanceInitiatedShutdownBehavior *string `locationName:"instanceInitiatedShutdownBehavior" type:"string" enum:"ShutdownBehavior"` + + // The instance type. For more information, see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Default: m1.small + InstanceType *string `type:"string" enum:"InstanceType"` + + // The ID of the kernel. + // + // We recommend that you use PV-GRUB instead of kernels and RAM disks. For + // more information, see PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html) + // in the Amazon Elastic Compute Cloud User Guide. + KernelId *string `type:"string"` + + // The name of the key pair. You can create a key pair using CreateKeyPair or + // ImportKeyPair. + // + // If you do not specify a key pair, you can't connect to the instance unless + // you choose an AMI that is configured to allow users another way to log in. + KeyName *string `type:"string"` + + // The maximum number of instances to launch. If you specify more instances + // than Amazon EC2 can launch in the target Availability Zone, Amazon EC2 launches + // the largest possible number of instances above MinCount. + // + // Constraints: Between 1 and the maximum number you're allowed for the specified + // instance type. For more information about the default limits, and how to + // request an increase, see How many instances can I run in Amazon EC2 (http://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2) + // in the Amazon EC2 General FAQ. + MaxCount *int64 `type:"integer" required:"true"` + + // The minimum number of instances to launch. If you specify a minimum that + // is more instances than Amazon EC2 can launch in the target Availability Zone, + // Amazon EC2 launches no instances. + // + // Constraints: Between 1 and the maximum number you're allowed for the specified + // instance type. For more information about the default limits, and how to + // request an increase, see How many instances can I run in Amazon EC2 (http://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2) + // in the Amazon EC2 General FAQ. + MinCount *int64 `type:"integer" required:"true"` + + // The monitoring for the instance. + Monitoring *RunInstancesMonitoringEnabled `type:"structure"` + + // One or more network interfaces. + NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterface" locationNameList:"item" type:"list"` + + // The placement for the instance. + Placement *Placement `type:"structure"` + + // [EC2-VPC] The primary IP address. You must specify a value from the IP address + // range of the subnet. + // + // Only one private IP address can be designated as primary. Therefore, you + // can't specify this parameter if PrivateIpAddresses.n.Primary is set to true + // and PrivateIpAddresses.n.PrivateIpAddress is set to an IP address. + // + // Default: We select an IP address from the IP address range of the subnet. + PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` + + // The ID of the RAM disk. + // + // We recommend that you use PV-GRUB instead of kernels and RAM disks. For + // more information, see PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html) + // in the Amazon Elastic Compute Cloud User Guide. + RamdiskId *string `type:"string"` + + // One or more security group IDs. You can create a security group using CreateSecurityGroup. + // + // Default: Amazon EC2 uses the default security group. + SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` + + // [EC2-Classic, default VPC] One or more security group names. For a nondefault + // VPC, you must use security group IDs instead. + // + // Default: Amazon EC2 uses the default security group. + SecurityGroups []*string `locationName:"SecurityGroup" locationNameList:"SecurityGroup" type:"list"` + + // [EC2-VPC] The ID of the subnet to launch the instance into. + SubnetId *string `type:"string"` + + // Data to configure the instance, or a script to run during instance launch. + // For more information, see Running Commands on Your Linux Instance at Launch + // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) (Linux) + // and Adding User Data (http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-instance-metadata.html#instancedata-add-user-data) + // (Windows). For API calls, the text must be base64-encoded. Command line tools + // perform encoding for you. + UserData *string `type:"string"` +} + +// String returns the string representation +func (s RunInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RunInstancesInput) GoString() string { + return s.String() +} + +// Describes the monitoring for the instance. +type RunInstancesMonitoringEnabled struct { + _ struct{} `type:"structure"` + + // Indicates whether monitoring is enabled for the instance. + Enabled *bool `locationName:"enabled" type:"boolean" required:"true"` +} + +// String returns the string representation +func (s RunInstancesMonitoringEnabled) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RunInstancesMonitoringEnabled) GoString() string { + return s.String() +} + +// Contains the parameters for RunScheduledInstances. +type RunScheduledInstancesInput struct { + _ struct{} `type:"structure"` + + // Unique, case-sensitive identifier that ensures the idempotency of the request. + // For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `type:"boolean"` + + // The number of instances. + // + // Default: 1 + InstanceCount *int64 `type:"integer"` + + // The launch specification. + LaunchSpecification *ScheduledInstancesLaunchSpecification `type:"structure" required:"true"` + + // The Scheduled Instance ID. + ScheduledInstanceId *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s RunScheduledInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RunScheduledInstancesInput) GoString() string { + return s.String() +} + +// Contains the output of RunScheduledInstances. +type RunScheduledInstancesOutput struct { + _ struct{} `type:"structure"` + + // The IDs of the newly launched instances. + InstanceIdSet []*string `locationName:"instanceIdSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s RunScheduledInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RunScheduledInstancesOutput) GoString() string { + return s.String() +} + +// Describes the storage parameters for S3 and S3 buckets for an instance store-backed +// AMI. +type S3Storage struct { + _ struct{} `type:"structure"` + + // The access key ID of the owner of the bucket. Before you specify a value + // for your access key ID, review and follow the guidance in Best Practices + // for Managing AWS Access Keys (http://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html). + AWSAccessKeyId *string `type:"string"` + + // The bucket in which to store the AMI. You can specify a bucket that you already + // own or a new bucket that Amazon EC2 creates on your behalf. If you specify + // a bucket that belongs to someone else, Amazon EC2 returns an error. + Bucket *string `locationName:"bucket" type:"string"` + + // The beginning of the file name of the AMI. + Prefix *string `locationName:"prefix" type:"string"` + + // A Base64-encoded Amazon S3 upload policy that gives Amazon EC2 permission + // to upload items into Amazon S3 on your behalf. + UploadPolicy []byte `locationName:"uploadPolicy" type:"blob"` + + // The signature of the Base64 encoded JSON document. + UploadPolicySignature *string `locationName:"uploadPolicySignature" type:"string"` +} + +// String returns the string representation +func (s S3Storage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s S3Storage) GoString() string { + return s.String() +} + +// Describes a Scheduled Instance. +type ScheduledInstance struct { + _ struct{} `type:"structure"` + + // The Availability Zone. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The date when the Scheduled Instance was purchased. + CreateDate *time.Time `locationName:"createDate" type:"timestamp" timestampFormat:"iso8601"` + + // The hourly price for a single instance. + HourlyPrice *string `locationName:"hourlyPrice" type:"string"` + + // The number of instances. + InstanceCount *int64 `locationName:"instanceCount" type:"integer"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string"` + + // The network platform (EC2-Classic or EC2-VPC). + NetworkPlatform *string `locationName:"networkPlatform" type:"string"` + + // The time for the next schedule to start. + NextSlotStartTime *time.Time `locationName:"nextSlotStartTime" type:"timestamp" timestampFormat:"iso8601"` + + // The platform (Linux/UNIX or Windows). + Platform *string `locationName:"platform" type:"string"` + + // The time that the previous schedule ended or will end. + PreviousSlotEndTime *time.Time `locationName:"previousSlotEndTime" type:"timestamp" timestampFormat:"iso8601"` + + // The schedule recurrence. + Recurrence *ScheduledInstanceRecurrence `locationName:"recurrence" type:"structure"` + + // The Scheduled Instance ID. + ScheduledInstanceId *string `locationName:"scheduledInstanceId" type:"string"` + + // The number of hours in the schedule. + SlotDurationInHours *int64 `locationName:"slotDurationInHours" type:"integer"` + + // The end date for the Scheduled Instance. + TermEndDate *time.Time `locationName:"termEndDate" type:"timestamp" timestampFormat:"iso8601"` + + // The start date for the Scheduled Instance. + TermStartDate *time.Time `locationName:"termStartDate" type:"timestamp" timestampFormat:"iso8601"` + + // The total number of hours for a single instance for the entire term. + TotalScheduledInstanceHours *int64 `locationName:"totalScheduledInstanceHours" type:"integer"` +} + +// String returns the string representation +func (s ScheduledInstance) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstance) GoString() string { + return s.String() +} + +// Describes a schedule that is available for your Scheduled Instances. +type ScheduledInstanceAvailability struct { + _ struct{} `type:"structure"` + + // The Availability Zone. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The number of available instances. + AvailableInstanceCount *int64 `locationName:"availableInstanceCount" type:"integer"` + + // The time period for the first schedule to start. + FirstSlotStartTime *time.Time `locationName:"firstSlotStartTime" type:"timestamp" timestampFormat:"iso8601"` + + // The hourly price for a single instance. + HourlyPrice *string `locationName:"hourlyPrice" type:"string"` + + // The instance type. You can specify one of the C3, C4, M4, or R3 instance + // types. + InstanceType *string `locationName:"instanceType" type:"string"` + + // The maximum term. The only possible value is 365 days. + MaxTermDurationInDays *int64 `locationName:"maxTermDurationInDays" type:"integer"` + + // The minimum term. The only possible value is 365 days. + MinTermDurationInDays *int64 `locationName:"minTermDurationInDays" type:"integer"` + + // The network platform (EC2-Classic or EC2-VPC). + NetworkPlatform *string `locationName:"networkPlatform" type:"string"` + + // The platform (Linux/UNIX or Windows). + Platform *string `locationName:"platform" type:"string"` + + // The purchase token. This token expires in two hours. + PurchaseToken *string `locationName:"purchaseToken" type:"string"` + + // The schedule recurrence. + Recurrence *ScheduledInstanceRecurrence `locationName:"recurrence" type:"structure"` + + // The number of hours in the schedule. + SlotDurationInHours *int64 `locationName:"slotDurationInHours" type:"integer"` + + // The total number of hours for a single instance for the entire term. + TotalScheduledInstanceHours *int64 `locationName:"totalScheduledInstanceHours" type:"integer"` +} + +// String returns the string representation +func (s ScheduledInstanceAvailability) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstanceAvailability) GoString() string { + return s.String() +} + +// Describes the recurring schedule for a Scheduled Instance. +type ScheduledInstanceRecurrence struct { + _ struct{} `type:"structure"` + + // The frequency (Daily, Weekly, or Monthly). + Frequency *string `locationName:"frequency" type:"string"` + + // The interval quantity. The interval unit depends on the value of frequency. + // For example, every 2 weeks or every 2 months. + Interval *int64 `locationName:"interval" type:"integer"` + + // The days. For a monthly schedule, this is one or more days of the month (1-31). + // For a weekly schedule, this is one or more days of the week (1-7, where 1 + // is Sunday). + OccurrenceDaySet []*int64 `locationName:"occurrenceDaySet" locationNameList:"item" type:"list"` + + // Indicates whether the occurrence is relative to the end of the specified + // week or month. + OccurrenceRelativeToEnd *bool `locationName:"occurrenceRelativeToEnd" type:"boolean"` + + // The unit for occurrenceDaySet (DayOfWeek or DayOfMonth). + OccurrenceUnit *string `locationName:"occurrenceUnit" type:"string"` +} + +// String returns the string representation +func (s ScheduledInstanceRecurrence) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstanceRecurrence) GoString() string { + return s.String() +} + +// Describes the recurring schedule for a Scheduled Instance. +type ScheduledInstanceRecurrenceRequest struct { + _ struct{} `type:"structure"` + + // The frequency (Daily, Weekly, or Monthly). + Frequency *string `type:"string"` + + // The interval quantity. The interval unit depends on the value of Frequency. + // For example, every 2 weeks or every 2 months. + Interval *int64 `type:"integer"` + + // The days. For a monthly schedule, this is one or more days of the month (1-31). + // For a weekly schedule, this is one or more days of the week (1-7, where 1 + // is Sunday). You can't specify this value with a daily schedule. If the occurrence + // is relative to the end of the month, you can specify only a single day. + OccurrenceDays []*int64 `locationName:"OccurrenceDay" locationNameList:"OccurenceDay" type:"list"` + + // Indicates whether the occurrence is relative to the end of the specified + // week or month. You can't specify this value with a daily schedule. + OccurrenceRelativeToEnd *bool `type:"boolean"` + + // The unit for OccurrenceDays (DayOfWeek or DayOfMonth). This value is required + // for a monthly schedule. You can't specify DayOfWeek with a weekly schedule. + // You can't specify this value with a daily schedule. + OccurrenceUnit *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstanceRecurrenceRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstanceRecurrenceRequest) GoString() string { + return s.String() +} + +// Describes a block device mapping for a Scheduled Instance. +type ScheduledInstancesBlockDeviceMapping struct { + _ struct{} `type:"structure"` + + // The device name exposed to the instance (for example, /dev/sdh or xvdh). + DeviceName *string `type:"string"` + + // Parameters used to set up EBS volumes automatically when the instance is + // launched. + Ebs *ScheduledInstancesEbs `type:"structure"` + + // Suppresses the specified device included in the block device mapping of the + // AMI. + NoDevice *string `type:"string"` + + // The virtual device name (ephemeralN). Instance store volumes are numbered + // starting from 0. An instance type with two available instance store volumes + // can specify mappings for ephemeral0 and ephemeral1.The number of available + // instance store volumes depends on the instance type. After you connect to + // the instance, you must mount the volume. + // + // Constraints: For M3 instances, you must specify instance store volumes in + // the block device mapping for the instance. When you launch an M3 instance, + // we ignore any instance store volumes specified in the block device mapping + // for the AMI. + VirtualName *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesBlockDeviceMapping) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesBlockDeviceMapping) GoString() string { + return s.String() +} + +// Describes an EBS volume for a Scheduled Instance. +type ScheduledInstancesEbs struct { + _ struct{} `type:"structure"` + + // Indicates whether the volume is deleted on instance termination. + DeleteOnTermination *bool `type:"boolean"` + + // Indicates whether the volume is encrypted. You can attached encrypted volumes + // only to instances that support them. + Encrypted *bool `type:"boolean"` + + // The number of I/O operations per second (IOPS) that the volume supports. + // For Provisioned IOPS (SSD) volumes, this represents the number of IOPS that + // are provisioned for the volume. For General Purpose (SSD) volumes, this represents + // the baseline performance of the volume and the rate at which the volume accumulates + // I/O credits for bursting. For more information about General Purpose (SSD) + // baseline performance, I/O credits, and bursting, see Amazon EBS Volume Types + // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes and + // 3 to 10000 for General Purpose (SSD) volumes. + // + // Condition: This parameter is required for requests to create io1 volumes; + // it is not used in requests to create standard or gp2 volumes. + Iops *int64 `type:"integer"` + + // The ID of the snapshot. + SnapshotId *string `type:"string"` + + // The size of the volume, in GiB. + // + // Default: If you're creating the volume from a snapshot and don't specify + // a volume size, the default is the snapshot size. + VolumeSize *int64 `type:"integer"` + + // The volume type. gp2 for General Purpose (SSD) volumes, io1 for Provisioned + // IOPS (SSD) volumes, and standard for Magnetic volumes. + // + // Default: standard + VolumeType *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesEbs) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesEbs) GoString() string { + return s.String() +} + +// Describes an IAM instance profile for a Scheduled Instance. +type ScheduledInstancesIamInstanceProfile struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN). + Arn *string `type:"string"` + + // The name. + Name *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesIamInstanceProfile) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesIamInstanceProfile) GoString() string { + return s.String() +} + +// Describes the launch specification for a Scheduled Instance. +type ScheduledInstancesLaunchSpecification struct { + _ struct{} `type:"structure"` + + // One or more block device mapping entries. + BlockDeviceMappings []*ScheduledInstancesBlockDeviceMapping `locationName:"BlockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` + + // Indicates whether the instances are optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS-optimized + // instance. + // + // Default: false + EbsOptimized *bool `type:"boolean"` + + // The IAM instance profile. + IamInstanceProfile *ScheduledInstancesIamInstanceProfile `type:"structure"` + + // The ID of the Amazon Machine Image (AMI). + ImageId *string `type:"string" required:"true"` + + // The instance type. + InstanceType *string `type:"string"` + + // The ID of the kernel. + KernelId *string `type:"string"` + + // The name of the key pair. + KeyName *string `type:"string"` + + // Enable or disable monitoring for the instances. + Monitoring *ScheduledInstancesMonitoring `type:"structure"` + + // One or more network interfaces. + NetworkInterfaces []*ScheduledInstancesNetworkInterface `locationName:"NetworkInterface" locationNameList:"NetworkInterface" type:"list"` + + // The placement information. + Placement *ScheduledInstancesPlacement `type:"structure"` + + // The ID of the RAM disk. + RamdiskId *string `type:"string"` + + // The IDs of one or more security groups. + SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` + + // The ID of the subnet in which to launch the instances. + SubnetId *string `type:"string"` + + // The base64-encoded MIME user data. + UserData *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesLaunchSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesLaunchSpecification) GoString() string { + return s.String() +} + +// Describes whether monitoring is enabled for a Scheduled Instance. +type ScheduledInstancesMonitoring struct { + _ struct{} `type:"structure"` + + // Indicates whether monitoring is enabled. + Enabled *bool `type:"boolean"` +} + +// String returns the string representation +func (s ScheduledInstancesMonitoring) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesMonitoring) GoString() string { + return s.String() +} + +// Describes a network interface for a Scheduled Instance. +type ScheduledInstancesNetworkInterface struct { + _ struct{} `type:"structure"` + + // Indicates whether to assign a public IP address to instances launched in + // a VPC. The public IP address can only be assigned to a network interface + // for eth0, and can only be assigned to a new network interface, not an existing + // one. You cannot specify more than one network interface in the request. If + // launching into a default subnet, the default value is true. + AssociatePublicIpAddress *bool `type:"boolean"` + + // Indicates whether to delete the interface when the instance is terminated. + DeleteOnTermination *bool `type:"boolean"` + + // The description. + Description *string `type:"string"` + + // The index of the device for the network interface attachment. + DeviceIndex *int64 `type:"integer"` + + // The IDs of one or more security groups. + Groups []*string `locationName:"Group" locationNameList:"SecurityGroupId" type:"list"` + + // The ID of the network interface. + NetworkInterfaceId *string `type:"string"` + + // The IP address of the network interface within the subnet. + PrivateIpAddress *string `type:"string"` + + // The private IP addresses. + PrivateIpAddressConfigs []*ScheduledInstancesPrivateIpAddressConfig `locationName:"PrivateIpAddressConfig" locationNameList:"PrivateIpAddressConfigSet" type:"list"` + + // The number of secondary private IP addresses. + SecondaryPrivateIpAddressCount *int64 `type:"integer"` + + // The ID of the subnet. + SubnetId *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesNetworkInterface) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesNetworkInterface) GoString() string { + return s.String() +} + +// Describes the placement for a Scheduled Instance. +type ScheduledInstancesPlacement struct { + _ struct{} `type:"structure"` + + // The Availability Zone. + AvailabilityZone *string `type:"string"` + + // The name of the placement group. + GroupName *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesPlacement) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesPlacement) GoString() string { + return s.String() +} + +// Describes a private IP address for a Scheduled Instance. +type ScheduledInstancesPrivateIpAddressConfig struct { + _ struct{} `type:"structure"` + + // Indicates whether this is a primary IP address. Otherwise, this is a secondary + // IP address. + Primary *bool `type:"boolean"` + + // The IP address. + PrivateIpAddress *string `type:"string"` +} + +// String returns the string representation +func (s ScheduledInstancesPrivateIpAddressConfig) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScheduledInstancesPrivateIpAddressConfig) GoString() string { + return s.String() +} + +// Describes a security group +type SecurityGroup struct { + _ struct{} `type:"structure"` + + // A description of the security group. + Description *string `locationName:"groupDescription" type:"string"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string"` + + // The name of the security group. + GroupName *string `locationName:"groupName" type:"string"` + + // One or more inbound rules associated with the security group. + IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` + + // [EC2-VPC] One or more outbound rules associated with the security group. + IpPermissionsEgress []*IpPermission `locationName:"ipPermissionsEgress" locationNameList:"item" type:"list"` + + // The AWS account ID of the owner of the security group. + OwnerId *string `locationName:"ownerId" type:"string"` + + // Any tags assigned to the security group. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // [EC2-VPC] The ID of the VPC for the security group. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s SecurityGroup) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SecurityGroup) GoString() string { + return s.String() +} + +// Describes the time period for a Scheduled Instance to start its first schedule. +// The time period must span less than one day. +type SlotDateTimeRangeRequest struct { + _ struct{} `type:"structure"` + + // The earliest date and time, in UTC, for the Scheduled Instance to start. + EarliestTime *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // The latest date and time, in UTC, for the Scheduled Instance to start. This + // value must be later than or equal to the earliest date and at most three + // months in the future. + LatestTime *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` +} + +// String returns the string representation +func (s SlotDateTimeRangeRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SlotDateTimeRangeRequest) GoString() string { + return s.String() +} + +// Describes the time period for a Scheduled Instance to start its first schedule. +type SlotStartTimeRangeRequest struct { + _ struct{} `type:"structure"` + + // The earliest date and time, in UTC, for the Scheduled Instance to start. + EarliestTime *time.Time `type:"timestamp" timestampFormat:"iso8601"` + + // The latest date and time, in UTC, for the Scheduled Instance to start. + LatestTime *time.Time `type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s SlotStartTimeRangeRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SlotStartTimeRangeRequest) GoString() string { + return s.String() +} + +// Describes a snapshot. +type Snapshot struct { + _ struct{} `type:"structure"` + + // The data encryption key identifier for the snapshot. This value is a unique + // identifier that corresponds to the data encryption key that was used to encrypt + // the original volume or snapshot copy. Because data encryption keys are inherited + // by volumes created from snapshots, and vice versa, if snapshots share the + // same data encryption key identifier, then they belong to the same volume/snapshot + // lineage. This parameter is only returned by the DescribeSnapshots API operation. + DataEncryptionKeyId *string `locationName:"dataEncryptionKeyId" type:"string"` + + // The description for the snapshot. + Description *string `locationName:"description" type:"string"` + + // Indicates whether the snapshot is encrypted. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // The full ARN of the AWS Key Management Service (AWS KMS) customer master + // key (CMK) that was used to protect the volume encryption key for the parent + // volume. + KmsKeyId *string `locationName:"kmsKeyId" type:"string"` + + // The AWS account alias (for example, amazon, self) or AWS account ID that + // owns the snapshot. + OwnerAlias *string `locationName:"ownerAlias" type:"string"` + + // The AWS account ID of the EBS snapshot owner. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The progress of the snapshot, as a percentage. + Progress *string `locationName:"progress" type:"string"` + + // The ID of the snapshot. Each snapshot receives a unique identifier when it + // is created. + SnapshotId *string `locationName:"snapshotId" type:"string"` + + // The time stamp when the snapshot was initiated. + StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` + + // The snapshot state. + State *string `locationName:"status" type:"string" enum:"SnapshotState"` + + // Encrypted Amazon EBS snapshots are copied asynchronously. If a snapshot copy + // operation fails (for example, if the proper AWS Key Management Service (AWS + // KMS) permissions are not obtained) this field displays error state details + // to help you diagnose why the error occurred. This parameter is only returned + // by the DescribeSnapshots API operation. + StateMessage *string `locationName:"statusMessage" type:"string"` + + // Any tags assigned to the snapshot. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the volume that was used to create the snapshot. + VolumeId *string `locationName:"volumeId" type:"string"` + + // The size of the volume, in GiB. + VolumeSize *int64 `locationName:"volumeSize" type:"integer"` +} + +// String returns the string representation +func (s Snapshot) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Snapshot) GoString() string { + return s.String() +} + +// Describes the snapshot created from the imported disk. +type SnapshotDetail struct { + _ struct{} `type:"structure"` + + // A description for the snapshot. + Description *string `locationName:"description" type:"string"` + + // The block device mapping for the snapshot. + DeviceName *string `locationName:"deviceName" type:"string"` + + // The size of the disk in the snapshot, in GiB. + DiskImageSize *float64 `locationName:"diskImageSize" type:"double"` + + // The format of the disk image from which the snapshot is created. + Format *string `locationName:"format" type:"string"` + + // The percentage of progress for the task. + Progress *string `locationName:"progress" type:"string"` + + // The snapshot ID of the disk being imported. + SnapshotId *string `locationName:"snapshotId" type:"string"` + + // A brief status of the snapshot creation. + Status *string `locationName:"status" type:"string"` + + // A detailed status message for the snapshot creation. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // The URL used to access the disk image. + Url *string `locationName:"url" type:"string"` + + // Describes the S3 bucket for the disk image. + UserBucket *UserBucketDetails `locationName:"userBucket" type:"structure"` +} + +// String returns the string representation +func (s SnapshotDetail) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SnapshotDetail) GoString() string { + return s.String() +} + +// The disk container object for the import snapshot request. +type SnapshotDiskContainer struct { + _ struct{} `type:"structure"` + + // The description of the disk image being imported. + Description *string `type:"string"` + + // The format of the disk image being imported. + // + // Valid values: RAW | VHD | VMDK | OVA + Format *string `type:"string"` + + // The URL to the Amazon S3-based disk image being imported. It can either be + // a https URL (https://..) or an Amazon S3 URL (s3://..). + Url *string `type:"string"` + + // Describes the S3 bucket for the disk image. + UserBucket *UserBucket `type:"structure"` +} + +// String returns the string representation +func (s SnapshotDiskContainer) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SnapshotDiskContainer) GoString() string { + return s.String() +} + +// Details about the import snapshot task. +type SnapshotTaskDetail struct { + _ struct{} `type:"structure"` + + // The description of the snapshot. + Description *string `locationName:"description" type:"string"` + + // The size of the disk in the snapshot, in GiB. + DiskImageSize *float64 `locationName:"diskImageSize" type:"double"` + + // The format of the disk image from which the snapshot is created. + Format *string `locationName:"format" type:"string"` + + // The percentage of completion for the import snapshot task. + Progress *string `locationName:"progress" type:"string"` + + // The snapshot ID of the disk being imported. + SnapshotId *string `locationName:"snapshotId" type:"string"` + + // A brief status for the import snapshot task. + Status *string `locationName:"status" type:"string"` + + // A detailed status message for the import snapshot task. + StatusMessage *string `locationName:"statusMessage" type:"string"` + + // The URL of the disk image from which the snapshot is created. + Url *string `locationName:"url" type:"string"` + + // The S3 bucket for the disk image. + UserBucket *UserBucketDetails `locationName:"userBucket" type:"structure"` +} + +// String returns the string representation +func (s SnapshotTaskDetail) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SnapshotTaskDetail) GoString() string { + return s.String() +} + +// Describes the data feed for a Spot instance. +type SpotDatafeedSubscription struct { + _ struct{} `type:"structure"` + + // The Amazon S3 bucket where the Spot instance data feed is located. + Bucket *string `locationName:"bucket" type:"string"` + + // The fault codes for the Spot instance request, if any. + Fault *SpotInstanceStateFault `locationName:"fault" type:"structure"` + + // The AWS account ID of the account. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The prefix that is prepended to data feed files. + Prefix *string `locationName:"prefix" type:"string"` + + // The state of the Spot instance data feed subscription. + State *string `locationName:"state" type:"string" enum:"DatafeedSubscriptionState"` +} + +// String returns the string representation +func (s SpotDatafeedSubscription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotDatafeedSubscription) GoString() string { + return s.String() +} + +// Describes the launch specification for one or more Spot instances. +type SpotFleetLaunchSpecification struct { + _ struct{} `type:"structure"` + + // Deprecated. + AddressingType *string `locationName:"addressingType" type:"string"` + + // One or more block device mapping entries. + BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` + + // Indicates whether the instances are optimized for EBS I/O. This optimization + // provides dedicated throughput to Amazon EBS and an optimized configuration + // stack to provide optimal EBS I/O performance. This optimization isn't available + // with all instance types. Additional usage charges apply when using an EBS + // Optimized instance. + // + // Default: false + EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` + + // The IAM instance profile. + IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` + + // The ID of the AMI. + ImageId *string `locationName:"imageId" type:"string"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // The ID of the kernel. + KernelId *string `locationName:"kernelId" type:"string"` + + // The name of the key pair. + KeyName *string `locationName:"keyName" type:"string"` + + // Enable or disable monitoring for the instances. + Monitoring *SpotFleetMonitoring `locationName:"monitoring" type:"structure"` + + // One or more network interfaces. + NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` + + // The placement information. + Placement *SpotPlacement `locationName:"placement" type:"structure"` + + // The ID of the RAM disk. + RamdiskId *string `locationName:"ramdiskId" type:"string"` + + // One or more security groups. When requesting instances in a VPC, you must + // specify the IDs of the security groups. When requesting instances in EC2-Classic, + // you can specify the names or the IDs of the security groups. + SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` + + // The bid price per unit hour for the specified instance type. If this value + // is not specified, the default is the Spot bid price specified for the fleet. + // To determine the bid price per unit hour, divide the Spot bid price by the + // value of WeightedCapacity. + SpotPrice *string `locationName:"spotPrice" type:"string"` + + // The ID of the subnet in which to launch the instances. To specify multiple + // subnets, separate them using commas; for example, "subnet-a61dafcf, subnet-65ea5f08". + SubnetId *string `locationName:"subnetId" type:"string"` + + // The Base64-encoded MIME user data to make available to the instances. + UserData *string `locationName:"userData" type:"string"` + + // The number of units provided by the specified instance type. These are the + // same units that you chose to set the target capacity in terms (instances + // or a performance characteristic such as vCPUs, memory, or I/O). + // + // If the target capacity divided by this value is not a whole number, we round + // the number of instances to the next whole number. If this value is not specified, + // the default is 1. + WeightedCapacity *float64 `locationName:"weightedCapacity" type:"double"` +} + +// String returns the string representation +func (s SpotFleetLaunchSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotFleetLaunchSpecification) GoString() string { + return s.String() +} + +// Describes whether monitoring is enabled. +type SpotFleetMonitoring struct { + _ struct{} `type:"structure"` + + // Enables monitoring for the instance. + // + // Default: false + Enabled *bool `locationName:"enabled" type:"boolean"` +} + +// String returns the string representation +func (s SpotFleetMonitoring) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotFleetMonitoring) GoString() string { + return s.String() +} + +// Describes a Spot fleet request. +type SpotFleetRequestConfig struct { + _ struct{} `type:"structure"` + + // The creation date and time of the request. + CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // Information about the configuration of the Spot fleet request. + SpotFleetRequestConfig *SpotFleetRequestConfigData `locationName:"spotFleetRequestConfig" type:"structure" required:"true"` + + // The ID of the Spot fleet request. + SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` + + // The state of the Spot fleet request. + SpotFleetRequestState *string `locationName:"spotFleetRequestState" type:"string" required:"true" enum:"BatchState"` +} + +// String returns the string representation +func (s SpotFleetRequestConfig) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotFleetRequestConfig) GoString() string { + return s.String() +} + +// Describes the configuration of a Spot fleet request. +type SpotFleetRequestConfigData struct { + _ struct{} `type:"structure"` + + // Indicates how to allocate the target capacity across the Spot pools specified + // by the Spot fleet request. The default is lowestPrice. + AllocationStrategy *string `locationName:"allocationStrategy" type:"string" enum:"AllocationStrategy"` + + // A unique, case-sensitive identifier you provide to ensure idempotency of + // your listings. This helps avoid duplicate listings. For more information, + // see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). + ClientToken *string `locationName:"clientToken" type:"string"` + + // Indicates whether running Spot instances should be terminated if the target + // capacity of the Spot fleet request is decreased below the current size of + // the Spot fleet. + ExcessCapacityTerminationPolicy *string `locationName:"excessCapacityTerminationPolicy" type:"string" enum:"ExcessCapacityTerminationPolicy"` + + // Grants the Spot fleet permission to terminate Spot instances on your behalf + // when you cancel its Spot fleet request using CancelSpotFleetRequests or when + // the Spot fleet request expires, if you set terminateInstancesWithExpiration. + IamFleetRole *string `locationName:"iamFleetRole" type:"string" required:"true"` + + // Information about the launch specifications for the Spot fleet request. + LaunchSpecifications []*SpotFleetLaunchSpecification `locationName:"launchSpecifications" locationNameList:"item" min:"1" type:"list" required:"true"` + + // The bid price per unit hour. + SpotPrice *string `locationName:"spotPrice" type:"string" required:"true"` + + // The number of units to request. You can choose to set the target capacity + // in terms of instances or a performance characteristic that is important to + // your application workload, such as vCPUs, memory, or I/O. + TargetCapacity *int64 `locationName:"targetCapacity" type:"integer" required:"true"` + + // Indicates whether running Spot instances should be terminated when the Spot + // fleet request expires. + TerminateInstancesWithExpiration *bool `locationName:"terminateInstancesWithExpiration" type:"boolean"` + + // The start date and time of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + // The default is to start fulfilling the request immediately. + ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` + + // The end date and time of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + // At this point, no new Spot instance requests are placed or enabled to fulfill + // the request. + ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s SpotFleetRequestConfigData) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotFleetRequestConfigData) GoString() string { + return s.String() +} + +// Describes a Spot instance request. +type SpotInstanceRequest struct { + _ struct{} `type:"structure"` + + // If you specified a duration and your Spot instance request was fulfilled, + // this is the fixed hourly price in effect for the Spot instance while it runs. + ActualBlockHourlyPrice *string `locationName:"actualBlockHourlyPrice" type:"string"` + + // The Availability Zone group. If you specify the same Availability Zone group + // for all Spot instance requests, all Spot instances are launched in the same + // Availability Zone. + AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"` + + // The duration for the Spot instance, in minutes. + BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"` + + // The date and time when the Spot instance request was created, in UTC format + // (for example, YYYY-MM-DDTHH:MM:SSZ). + CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"` + + // The fault codes for the Spot instance request, if any. + Fault *SpotInstanceStateFault `locationName:"fault" type:"structure"` + + // The instance ID, if an instance has been launched to fulfill the Spot instance + // request. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The instance launch group. Launch groups are Spot instances that launch together + // and terminate together. + LaunchGroup *string `locationName:"launchGroup" type:"string"` + + // Additional information for launching instances. + LaunchSpecification *LaunchSpecification `locationName:"launchSpecification" type:"structure"` + + // The Availability Zone in which the bid is launched. + LaunchedAvailabilityZone *string `locationName:"launchedAvailabilityZone" type:"string"` + + // The product description associated with the Spot instance. + ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` + + // The ID of the Spot instance request. + SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` + + // The maximum hourly price (bid) for the Spot instance launched to fulfill + // the request. + SpotPrice *string `locationName:"spotPrice" type:"string"` + + // The state of the Spot instance request. Spot bid status information can help + // you track your Spot instance requests. For more information, see Spot Bid + // Status (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html) + // in the Amazon Elastic Compute Cloud User Guide. + State *string `locationName:"state" type:"string" enum:"SpotInstanceState"` + + // The status code and status message describing the Spot instance request. + Status *SpotInstanceStatus `locationName:"status" type:"structure"` + + // Any tags assigned to the resource. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The Spot instance request type. + Type *string `locationName:"type" type:"string" enum:"SpotInstanceType"` + + // The start date of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + // The request becomes active at this date and time. + ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` + + // The end date of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + // If this is a one-time request, it remains active until all instances launch, + // the request is canceled, or this date is reached. If the request is persistent, + // it remains active until it is canceled or this date is reached. + ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s SpotInstanceRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotInstanceRequest) GoString() string { + return s.String() +} + +// Describes a Spot instance state change. +type SpotInstanceStateFault struct { + _ struct{} `type:"structure"` + + // The reason code for the Spot instance state change. + Code *string `locationName:"code" type:"string"` + + // The message for the Spot instance state change. + Message *string `locationName:"message" type:"string"` +} + +// String returns the string representation +func (s SpotInstanceStateFault) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotInstanceStateFault) GoString() string { + return s.String() +} + +// Describes the status of a Spot instance request. +type SpotInstanceStatus struct { + _ struct{} `type:"structure"` + + // The status code. For a list of status codes, see Spot Bid Status Codes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html#spot-instance-bid-status-understand) + // in the Amazon Elastic Compute Cloud User Guide. + Code *string `locationName:"code" type:"string"` + + // The description for the status code. + Message *string `locationName:"message" type:"string"` + + // The date and time of the most recent status update, in UTC format (for example, + // YYYY-MM-DDTHH:MM:SSZ). + UpdateTime *time.Time `locationName:"updateTime" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s SpotInstanceStatus) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotInstanceStatus) GoString() string { + return s.String() +} + +// Describes Spot instance placement. +type SpotPlacement struct { + _ struct{} `type:"structure"` + + // The Availability Zones. To specify multiple Availability Zones, separate + // them using commas; for example, "us-west-2a, us-west-2b". + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The name of the placement group (for cluster instances). + GroupName *string `locationName:"groupName" type:"string"` +} + +// String returns the string representation +func (s SpotPlacement) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotPlacement) GoString() string { + return s.String() +} + +// Describes the maximum hourly price (bid) for any Spot instance launched to +// fulfill the request. +type SpotPrice struct { + _ struct{} `type:"structure"` + + // The Availability Zone. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The instance type. + InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` + + // A general description of the AMI. + ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` + + // The maximum price (bid) that you are willing to pay for a Spot instance. + SpotPrice *string `locationName:"spotPrice" type:"string"` + + // The date and time the request was created, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). + Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s SpotPrice) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SpotPrice) GoString() string { + return s.String() +} + +type StartInstancesInput struct { + _ struct{} `type:"structure"` + + // Reserved. + AdditionalInfo *string `locationName:"additionalInfo" type:"string"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s StartInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StartInstancesInput) GoString() string { + return s.String() +} + +type StartInstancesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more started instances. + StartingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s StartInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StartInstancesOutput) GoString() string { + return s.String() +} + +// Describes a state change. +type StateReason struct { + _ struct{} `type:"structure"` + + // The reason code for the state change. + Code *string `locationName:"code" type:"string"` + + // The message for the state change. + // + // Server.SpotInstanceTermination: A Spot instance was terminated due to an + // increase in the market price. + // + // Server.InternalError: An internal error occurred during instance launch, + // resulting in termination. + // + // Server.InsufficientInstanceCapacity: There was insufficient instance capacity + // to satisfy the launch request. + // + // Client.InternalError: A client error caused the instance to terminate on + // launch. + // + // Client.InstanceInitiatedShutdown: The instance was shut down using the shutdown + // -h command from the instance. + // + // Client.UserInitiatedShutdown: The instance was shut down using the Amazon + // EC2 API. + // + // Client.VolumeLimitExceeded: The limit on the number of EBS volumes or total + // storage was exceeded. Decrease usage or request an increase in your limits. + // + // Client.InvalidSnapshot.NotFound: The specified snapshot was not found. + Message *string `locationName:"message" type:"string"` +} + +// String returns the string representation +func (s StateReason) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StateReason) GoString() string { + return s.String() +} + +type StopInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // Forces the instances to stop. The instances do not have an opportunity to + // flush file system caches or file system metadata. If you use this option, + // you must perform file system check and repair procedures. This option is + // not recommended for Windows instances. + // + // Default: false + Force *bool `locationName:"force" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s StopInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StopInstancesInput) GoString() string { + return s.String() +} + +type StopInstancesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more stopped instances. + StoppingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s StopInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StopInstancesOutput) GoString() string { + return s.String() +} + +// Describes the storage location for an instance store-backed AMI. +type Storage struct { + _ struct{} `type:"structure"` + + // An Amazon S3 storage location. + S3 *S3Storage `type:"structure"` +} + +// String returns the string representation +func (s Storage) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Storage) GoString() string { + return s.String() +} + +// Describes a subnet. +type Subnet struct { + _ struct{} `type:"structure"` + + // The Availability Zone of the subnet. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The number of unused IP addresses in the subnet. Note that the IP addresses + // for any stopped instances are considered unavailable. + AvailableIpAddressCount *int64 `locationName:"availableIpAddressCount" type:"integer"` + + // The CIDR block assigned to the subnet. + CidrBlock *string `locationName:"cidrBlock" type:"string"` + + // Indicates whether this is the default subnet for the Availability Zone. + DefaultForAz *bool `locationName:"defaultForAz" type:"boolean"` + + // Indicates whether instances launched in this subnet receive a public IP address. + MapPublicIpOnLaunch *bool `locationName:"mapPublicIpOnLaunch" type:"boolean"` + + // The current state of the subnet. + State *string `locationName:"state" type:"string" enum:"SubnetState"` + + // The ID of the subnet. + SubnetId *string `locationName:"subnetId" type:"string"` + + // Any tags assigned to the subnet. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC the subnet is in. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s Subnet) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Subnet) GoString() string { + return s.String() +} + +// Describes a tag. +type Tag struct { + _ struct{} `type:"structure"` + + // The key of the tag. + // + // Constraints: Tag keys are case-sensitive and accept a maximum of 127 Unicode + // characters. May not begin with aws: + Key *string `locationName:"key" type:"string"` + + // The value of the tag. + // + // Constraints: Tag values are case-sensitive and accept a maximum of 255 Unicode + // characters. + Value *string `locationName:"value" type:"string"` +} + +// String returns the string representation +func (s Tag) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Tag) GoString() string { + return s.String() +} + +// Describes a tag. +type TagDescription struct { + _ struct{} `type:"structure"` + + // The tag key. + Key *string `locationName:"key" type:"string"` + + // The ID of the resource. For example, ami-1a2b3c4d. + ResourceId *string `locationName:"resourceId" type:"string"` + + // The resource type. + ResourceType *string `locationName:"resourceType" type:"string" enum:"ResourceType"` + + // The tag value. + Value *string `locationName:"value" type:"string"` +} + +// String returns the string representation +func (s TagDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagDescription) GoString() string { + return s.String() +} + +type TerminateInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s TerminateInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TerminateInstancesInput) GoString() string { + return s.String() +} + +type TerminateInstancesOutput struct { + _ struct{} `type:"structure"` + + // Information about one or more terminated instances. + TerminatingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s TerminateInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TerminateInstancesOutput) GoString() string { + return s.String() +} + +type UnassignPrivateIpAddressesInput struct { + _ struct{} `type:"structure"` + + // The ID of the network interface. + NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` + + // The secondary private IP addresses to unassign from the network interface. + // You can specify this option multiple times to unassign more than one IP address. + PrivateIpAddresses []*string `locationName:"privateIpAddress" locationNameList:"PrivateIpAddress" type:"list" required:"true"` +} + +// String returns the string representation +func (s UnassignPrivateIpAddressesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnassignPrivateIpAddressesInput) GoString() string { + return s.String() +} + +type UnassignPrivateIpAddressesOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s UnassignPrivateIpAddressesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnassignPrivateIpAddressesOutput) GoString() string { + return s.String() +} + +type UnmonitorInstancesInput struct { + _ struct{} `type:"structure"` + + // Checks whether you have the required permissions for the action, without + // actually making the request, and provides an error response. If you have + // the required permissions, the error response is DryRunOperation. Otherwise, + // it is UnauthorizedOperation. + DryRun *bool `locationName:"dryRun" type:"boolean"` + + // One or more instance IDs. + InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` +} + +// String returns the string representation +func (s UnmonitorInstancesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnmonitorInstancesInput) GoString() string { + return s.String() +} + +type UnmonitorInstancesOutput struct { + _ struct{} `type:"structure"` + + // Monitoring information for one or more instances. + InstanceMonitorings []*InstanceMonitoring `locationName:"instancesSet" locationNameList:"item" type:"list"` +} + +// String returns the string representation +func (s UnmonitorInstancesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnmonitorInstancesOutput) GoString() string { + return s.String() +} + +// Information about items that were not successfully processed in a batch call. +type UnsuccessfulItem struct { + _ struct{} `type:"structure"` + + // Information about the error. + Error *UnsuccessfulItemError `locationName:"error" type:"structure" required:"true"` + + // The ID of the resource. + ResourceId *string `locationName:"resourceId" type:"string"` +} + +// String returns the string representation +func (s UnsuccessfulItem) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnsuccessfulItem) GoString() string { + return s.String() +} + +// Information about the error that occurred. For more information about errors, +// see Error Codes (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html). +type UnsuccessfulItemError struct { + _ struct{} `type:"structure"` + + // The error code. + Code *string `locationName:"code" type:"string" required:"true"` + + // The error message accompanying the error code. + Message *string `locationName:"message" type:"string" required:"true"` +} + +// String returns the string representation +func (s UnsuccessfulItemError) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UnsuccessfulItemError) GoString() string { + return s.String() +} + +// Describes the S3 bucket for the disk image. +type UserBucket struct { + _ struct{} `type:"structure"` + + // The name of the S3 bucket where the disk image is located. + S3Bucket *string `type:"string"` + + // The key for the disk image. + S3Key *string `type:"string"` +} + +// String returns the string representation +func (s UserBucket) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UserBucket) GoString() string { + return s.String() +} + +// Describes the S3 bucket for the disk image. +type UserBucketDetails struct { + _ struct{} `type:"structure"` + + // The S3 bucket from which the disk image was created. + S3Bucket *string `locationName:"s3Bucket" type:"string"` + + // The key from which the disk image was created. + S3Key *string `locationName:"s3Key" type:"string"` +} + +// String returns the string representation +func (s UserBucketDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UserBucketDetails) GoString() string { + return s.String() +} + +// Describes the user data to be made available to an instance. +type UserData struct { + _ struct{} `type:"structure"` + + // The Base64-encoded MIME user data for the instance. + Data *string `locationName:"data" type:"string"` +} + +// String returns the string representation +func (s UserData) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UserData) GoString() string { + return s.String() +} + +// Describes a security group and AWS account ID pair. +type UserIdGroupPair struct { + _ struct{} `type:"structure"` + + // The ID of the security group. + GroupId *string `locationName:"groupId" type:"string"` + + // The name of the security group. In a request, use this parameter for a security + // group in EC2-Classic or a default VPC only. For a security group in a nondefault + // VPC, use GroupId. + GroupName *string `locationName:"groupName" type:"string"` + + // The ID of an AWS account. EC2-Classic only. + UserId *string `locationName:"userId" type:"string"` +} + +// String returns the string representation +func (s UserIdGroupPair) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UserIdGroupPair) GoString() string { + return s.String() +} + +// Describes telemetry for a VPN tunnel. +type VgwTelemetry struct { + _ struct{} `type:"structure"` + + // The number of accepted routes. + AcceptedRouteCount *int64 `locationName:"acceptedRouteCount" type:"integer"` + + // The date and time of the last change in status. + LastStatusChange *time.Time `locationName:"lastStatusChange" type:"timestamp" timestampFormat:"iso8601"` + + // The Internet-routable IP address of the virtual private gateway's outside + // interface. + OutsideIpAddress *string `locationName:"outsideIpAddress" type:"string"` + + // The status of the VPN tunnel. + Status *string `locationName:"status" type:"string" enum:"TelemetryStatus"` + + // If an error occurs, a description of the error. + StatusMessage *string `locationName:"statusMessage" type:"string"` +} + +// String returns the string representation +func (s VgwTelemetry) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VgwTelemetry) GoString() string { + return s.String() +} + +// Describes a volume. +type Volume struct { + _ struct{} `type:"structure"` + + // Information about the volume attachments. + Attachments []*VolumeAttachment `locationName:"attachmentSet" locationNameList:"item" type:"list"` + + // The Availability Zone for the volume. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The time stamp when volume creation was initiated. + CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"` + + // Indicates whether the volume will be encrypted. + Encrypted *bool `locationName:"encrypted" type:"boolean"` + + // The number of I/O operations per second (IOPS) that the volume supports. + // For Provisioned IOPS (SSD) volumes, this represents the number of IOPS that + // are provisioned for the volume. For General Purpose (SSD) volumes, this represents + // the baseline performance of the volume and the rate at which the volume accumulates + // I/O credits for bursting. For more information on General Purpose (SSD) baseline + // performance, I/O credits, and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes and + // 3 to 10000 for General Purpose (SSD) volumes. + // + // Condition: This parameter is required for requests to create io1 volumes; + // it is not used in requests to create standard or gp2 volumes. + Iops *int64 `locationName:"iops" type:"integer"` + + // The full ARN of the AWS Key Management Service (AWS KMS) customer master + // key (CMK) that was used to protect the volume encryption key for the volume. + KmsKeyId *string `locationName:"kmsKeyId" type:"string"` + + // The size of the volume, in GiBs. + Size *int64 `locationName:"size" type:"integer"` + + // The snapshot from which the volume was created, if applicable. + SnapshotId *string `locationName:"snapshotId" type:"string"` + + // The volume state. + State *string `locationName:"status" type:"string" enum:"VolumeState"` + + // Any tags assigned to the volume. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the volume. + VolumeId *string `locationName:"volumeId" type:"string"` + + // The volume type. This can be gp2 for General Purpose (SSD) volumes, io1 for + // Provisioned IOPS (SSD) volumes, or standard for Magnetic volumes. + VolumeType *string `locationName:"volumeType" type:"string" enum:"VolumeType"` +} + +// String returns the string representation +func (s Volume) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Volume) GoString() string { + return s.String() +} + +// Describes volume attachment details. +type VolumeAttachment struct { + _ struct{} `type:"structure"` + + // The time stamp when the attachment initiated. + AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` + + // Indicates whether the EBS volume is deleted on instance termination. + DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` + + // The device name. + Device *string `locationName:"device" type:"string"` + + // The ID of the instance. + InstanceId *string `locationName:"instanceId" type:"string"` + + // The attachment state of the volume. + State *string `locationName:"status" type:"string" enum:"VolumeAttachmentState"` + + // The ID of the volume. + VolumeId *string `locationName:"volumeId" type:"string"` +} + +// String returns the string representation +func (s VolumeAttachment) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeAttachment) GoString() string { + return s.String() +} + +// Describes an EBS volume. +type VolumeDetail struct { + _ struct{} `type:"structure"` + + // The size of the volume, in GiB. + Size *int64 `locationName:"size" type:"long" required:"true"` +} + +// String returns the string representation +func (s VolumeDetail) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeDetail) GoString() string { + return s.String() +} + +// Describes a volume status operation code. +type VolumeStatusAction struct { + _ struct{} `type:"structure"` + + // The code identifying the operation, for example, enable-volume-io. + Code *string `locationName:"code" type:"string"` + + // A description of the operation. + Description *string `locationName:"description" type:"string"` + + // The ID of the event associated with this operation. + EventId *string `locationName:"eventId" type:"string"` + + // The event type associated with this operation. + EventType *string `locationName:"eventType" type:"string"` +} + +// String returns the string representation +func (s VolumeStatusAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeStatusAction) GoString() string { + return s.String() +} + +// Describes a volume status. +type VolumeStatusDetails struct { + _ struct{} `type:"structure"` + + // The name of the volume status. + Name *string `locationName:"name" type:"string" enum:"VolumeStatusName"` + + // The intended status of the volume status. + Status *string `locationName:"status" type:"string"` +} + +// String returns the string representation +func (s VolumeStatusDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeStatusDetails) GoString() string { + return s.String() +} + +// Describes a volume status event. +type VolumeStatusEvent struct { + _ struct{} `type:"structure"` + + // A description of the event. + Description *string `locationName:"description" type:"string"` + + // The ID of this event. + EventId *string `locationName:"eventId" type:"string"` + + // The type of this event. + EventType *string `locationName:"eventType" type:"string"` + + // The latest end time of the event. + NotAfter *time.Time `locationName:"notAfter" type:"timestamp" timestampFormat:"iso8601"` + + // The earliest start time of the event. + NotBefore *time.Time `locationName:"notBefore" type:"timestamp" timestampFormat:"iso8601"` +} + +// String returns the string representation +func (s VolumeStatusEvent) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeStatusEvent) GoString() string { + return s.String() +} + +// Describes the status of a volume. +type VolumeStatusInfo struct { + _ struct{} `type:"structure"` + + // The details of the volume status. + Details []*VolumeStatusDetails `locationName:"details" locationNameList:"item" type:"list"` + + // The status of the volume. + Status *string `locationName:"status" type:"string" enum:"VolumeStatusInfoStatus"` +} + +// String returns the string representation +func (s VolumeStatusInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeStatusInfo) GoString() string { + return s.String() +} + +// Describes the volume status. +type VolumeStatusItem struct { + _ struct{} `type:"structure"` + + // The details of the operation. + Actions []*VolumeStatusAction `locationName:"actionsSet" locationNameList:"item" type:"list"` + + // The Availability Zone of the volume. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // A list of events associated with the volume. + Events []*VolumeStatusEvent `locationName:"eventsSet" locationNameList:"item" type:"list"` + + // The volume ID. + VolumeId *string `locationName:"volumeId" type:"string"` + + // The volume status. + VolumeStatus *VolumeStatusInfo `locationName:"volumeStatus" type:"structure"` +} + +// String returns the string representation +func (s VolumeStatusItem) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VolumeStatusItem) GoString() string { + return s.String() +} + +// Describes a VPC. +type Vpc struct { + _ struct{} `type:"structure"` + + // The CIDR block for the VPC. + CidrBlock *string `locationName:"cidrBlock" type:"string"` + + // The ID of the set of DHCP options you've associated with the VPC (or default + // if the default options are associated with the VPC). + DhcpOptionsId *string `locationName:"dhcpOptionsId" type:"string"` + + // The allowed tenancy of instances launched into the VPC. + InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` + + // Indicates whether the VPC is the default VPC. + IsDefault *bool `locationName:"isDefault" type:"boolean"` + + // The current state of the VPC. + State *string `locationName:"state" type:"string" enum:"VpcState"` + + // Any tags assigned to the VPC. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s Vpc) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Vpc) GoString() string { + return s.String() +} + +// Describes an attachment between a virtual private gateway and a VPC. +type VpcAttachment struct { + _ struct{} `type:"structure"` + + // The current state of the attachment. + State *string `locationName:"state" type:"string" enum:"AttachmentStatus"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s VpcAttachment) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcAttachment) GoString() string { + return s.String() +} + +// Describes whether a VPC is enabled for ClassicLink. +type VpcClassicLink struct { + _ struct{} `type:"structure"` + + // Indicates whether the VPC is enabled for ClassicLink. + ClassicLinkEnabled *bool `locationName:"classicLinkEnabled" type:"boolean"` + + // Any tags assigned to the VPC. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s VpcClassicLink) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcClassicLink) GoString() string { + return s.String() +} + +// Describes a VPC endpoint. +type VpcEndpoint struct { + _ struct{} `type:"structure"` + + // The date and time the VPC endpoint was created. + CreationTimestamp *time.Time `locationName:"creationTimestamp" type:"timestamp" timestampFormat:"iso8601"` + + // The policy document associated with the endpoint. + PolicyDocument *string `locationName:"policyDocument" type:"string"` + + // One or more route tables associated with the endpoint. + RouteTableIds []*string `locationName:"routeTableIdSet" locationNameList:"item" type:"list"` + + // The name of the AWS service to which the endpoint is associated. + ServiceName *string `locationName:"serviceName" type:"string"` + + // The state of the VPC endpoint. + State *string `locationName:"state" type:"string" enum:"State"` + + // The ID of the VPC endpoint. + VpcEndpointId *string `locationName:"vpcEndpointId" type:"string"` + + // The ID of the VPC to which the endpoint is associated. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s VpcEndpoint) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcEndpoint) GoString() string { + return s.String() +} + +// Describes a VPC peering connection. +type VpcPeeringConnection struct { + _ struct{} `type:"structure"` + + // The information of the peer VPC. + AccepterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"accepterVpcInfo" type:"structure"` + + // The time that an unaccepted VPC peering connection will expire. + ExpirationTime *time.Time `locationName:"expirationTime" type:"timestamp" timestampFormat:"iso8601"` + + // The information of the requester VPC. + RequesterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"requesterVpcInfo" type:"structure"` + + // The status of the VPC peering connection. + Status *VpcPeeringConnectionStateReason `locationName:"status" type:"structure"` + + // Any tags assigned to the resource. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The ID of the VPC peering connection. + VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` +} + +// String returns the string representation +func (s VpcPeeringConnection) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcPeeringConnection) GoString() string { + return s.String() +} + +// Describes the status of a VPC peering connection. +type VpcPeeringConnectionStateReason struct { + _ struct{} `type:"structure"` + + // The status of the VPC peering connection. + Code *string `locationName:"code" type:"string" enum:"VpcPeeringConnectionStateReasonCode"` + + // A message that provides more information about the status, if applicable. + Message *string `locationName:"message" type:"string"` +} + +// String returns the string representation +func (s VpcPeeringConnectionStateReason) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcPeeringConnectionStateReason) GoString() string { + return s.String() +} + +// Describes a VPC in a VPC peering connection. +type VpcPeeringConnectionVpcInfo struct { + _ struct{} `type:"structure"` + + // The CIDR block for the VPC. + CidrBlock *string `locationName:"cidrBlock" type:"string"` + + // The AWS account ID of the VPC owner. + OwnerId *string `locationName:"ownerId" type:"string"` + + // The ID of the VPC. + VpcId *string `locationName:"vpcId" type:"string"` +} + +// String returns the string representation +func (s VpcPeeringConnectionVpcInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpcPeeringConnectionVpcInfo) GoString() string { + return s.String() +} + +// Describes a VPN connection. +type VpnConnection struct { + _ struct{} `type:"structure"` + + // The configuration information for the VPN connection's customer gateway (in + // the native XML format). This element is always present in the CreateVpnConnection + // response; however, it's present in the DescribeVpnConnections response only + // if the VPN connection is in the pending or available state. + CustomerGatewayConfiguration *string `locationName:"customerGatewayConfiguration" type:"string"` + + // The ID of the customer gateway at your end of the VPN connection. + CustomerGatewayId *string `locationName:"customerGatewayId" type:"string"` + + // The VPN connection options. + Options *VpnConnectionOptions `locationName:"options" type:"structure"` + + // The static routes associated with the VPN connection. + Routes []*VpnStaticRoute `locationName:"routes" locationNameList:"item" type:"list"` + + // The current state of the VPN connection. + State *string `locationName:"state" type:"string" enum:"VpnState"` + + // Any tags assigned to the VPN connection. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The type of VPN connection. + Type *string `locationName:"type" type:"string" enum:"GatewayType"` + + // Information about the VPN tunnel. + VgwTelemetry []*VgwTelemetry `locationName:"vgwTelemetry" locationNameList:"item" type:"list"` + + // The ID of the VPN connection. + VpnConnectionId *string `locationName:"vpnConnectionId" type:"string"` + + // The ID of the virtual private gateway at the AWS side of the VPN connection. + VpnGatewayId *string `locationName:"vpnGatewayId" type:"string"` +} + +// String returns the string representation +func (s VpnConnection) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpnConnection) GoString() string { + return s.String() +} + +// Describes VPN connection options. +type VpnConnectionOptions struct { + _ struct{} `type:"structure"` + + // Indicates whether the VPN connection uses static routes only. Static routes + // must be used for devices that don't support BGP. + StaticRoutesOnly *bool `locationName:"staticRoutesOnly" type:"boolean"` +} + +// String returns the string representation +func (s VpnConnectionOptions) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpnConnectionOptions) GoString() string { + return s.String() +} + +// Describes VPN connection options. +type VpnConnectionOptionsSpecification struct { + _ struct{} `type:"structure"` + + // Indicates whether the VPN connection uses static routes only. Static routes + // must be used for devices that don't support BGP. + StaticRoutesOnly *bool `locationName:"staticRoutesOnly" type:"boolean"` +} + +// String returns the string representation +func (s VpnConnectionOptionsSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpnConnectionOptionsSpecification) GoString() string { + return s.String() +} + +// Describes a virtual private gateway. +type VpnGateway struct { + _ struct{} `type:"structure"` + + // The Availability Zone where the virtual private gateway was created, if applicable. + // This field may be empty or not returned. + AvailabilityZone *string `locationName:"availabilityZone" type:"string"` + + // The current state of the virtual private gateway. + State *string `locationName:"state" type:"string" enum:"VpnState"` + + // Any tags assigned to the virtual private gateway. + Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` + + // The type of VPN connection the virtual private gateway supports. + Type *string `locationName:"type" type:"string" enum:"GatewayType"` + + // Any VPCs attached to the virtual private gateway. + VpcAttachments []*VpcAttachment `locationName:"attachments" locationNameList:"item" type:"list"` + + // The ID of the virtual private gateway. + VpnGatewayId *string `locationName:"vpnGatewayId" type:"string"` +} + +// String returns the string representation +func (s VpnGateway) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpnGateway) GoString() string { + return s.String() +} + +// Describes a static route for a VPN connection. +type VpnStaticRoute struct { + _ struct{} `type:"structure"` + + // The CIDR block associated with the local subnet of the customer data center. + DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string"` + + // Indicates how the routes were provided. + Source *string `locationName:"source" type:"string" enum:"VpnStaticRouteSource"` + + // The current state of the static route. + State *string `locationName:"state" type:"string" enum:"VpnState"` +} + +// String returns the string representation +func (s VpnStaticRoute) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s VpnStaticRoute) GoString() string { + return s.String() +} + +const ( + // @enum AccountAttributeName + AccountAttributeNameSupportedPlatforms = "supported-platforms" + // @enum AccountAttributeName + AccountAttributeNameDefaultVpc = "default-vpc" +) + +const ( + // @enum Affinity + AffinityDefault = "default" + // @enum Affinity + AffinityHost = "host" +) + +const ( + // @enum AllocationState + AllocationStateAvailable = "available" + // @enum AllocationState + AllocationStateUnderAssessment = "under-assessment" + // @enum AllocationState + AllocationStatePermanentFailure = "permanent-failure" + // @enum AllocationState + AllocationStateReleased = "released" + // @enum AllocationState + AllocationStateReleasedPermanentFailure = "released-permanent-failure" +) + +const ( + // @enum AllocationStrategy + AllocationStrategyLowestPrice = "lowestPrice" + // @enum AllocationStrategy + AllocationStrategyDiversified = "diversified" +) + +const ( + // @enum ArchitectureValues + ArchitectureValuesI386 = "i386" + // @enum ArchitectureValues + ArchitectureValuesX8664 = "x86_64" +) + +const ( + // @enum AttachmentStatus + AttachmentStatusAttaching = "attaching" + // @enum AttachmentStatus + AttachmentStatusAttached = "attached" + // @enum AttachmentStatus + AttachmentStatusDetaching = "detaching" + // @enum AttachmentStatus + AttachmentStatusDetached = "detached" +) + +const ( + // @enum AutoPlacement + AutoPlacementOn = "on" + // @enum AutoPlacement + AutoPlacementOff = "off" +) + +const ( + // @enum AvailabilityZoneState + AvailabilityZoneStateAvailable = "available" + // @enum AvailabilityZoneState + AvailabilityZoneStateInformation = "information" + // @enum AvailabilityZoneState + AvailabilityZoneStateImpaired = "impaired" + // @enum AvailabilityZoneState + AvailabilityZoneStateUnavailable = "unavailable" +) + +const ( + // @enum BatchState + BatchStateSubmitted = "submitted" + // @enum BatchState + BatchStateActive = "active" + // @enum BatchState + BatchStateCancelled = "cancelled" + // @enum BatchState + BatchStateFailed = "failed" + // @enum BatchState + BatchStateCancelledRunning = "cancelled_running" + // @enum BatchState + BatchStateCancelledTerminating = "cancelled_terminating" + // @enum BatchState + BatchStateModifying = "modifying" +) + +const ( + // @enum BundleTaskState + BundleTaskStatePending = "pending" + // @enum BundleTaskState + BundleTaskStateWaitingForShutdown = "waiting-for-shutdown" + // @enum BundleTaskState + BundleTaskStateBundling = "bundling" + // @enum BundleTaskState + BundleTaskStateStoring = "storing" + // @enum BundleTaskState + BundleTaskStateCancelling = "cancelling" + // @enum BundleTaskState + BundleTaskStateComplete = "complete" + // @enum BundleTaskState + BundleTaskStateFailed = "failed" +) + +const ( + // @enum CancelBatchErrorCode + CancelBatchErrorCodeFleetRequestIdDoesNotExist = "fleetRequestIdDoesNotExist" + // @enum CancelBatchErrorCode + CancelBatchErrorCodeFleetRequestIdMalformed = "fleetRequestIdMalformed" + // @enum CancelBatchErrorCode + CancelBatchErrorCodeFleetRequestNotInCancellableState = "fleetRequestNotInCancellableState" + // @enum CancelBatchErrorCode + CancelBatchErrorCodeUnexpectedError = "unexpectedError" +) + +const ( + // @enum CancelSpotInstanceRequestState + CancelSpotInstanceRequestStateActive = "active" + // @enum CancelSpotInstanceRequestState + CancelSpotInstanceRequestStateOpen = "open" + // @enum CancelSpotInstanceRequestState + CancelSpotInstanceRequestStateClosed = "closed" + // @enum CancelSpotInstanceRequestState + CancelSpotInstanceRequestStateCancelled = "cancelled" + // @enum CancelSpotInstanceRequestState + CancelSpotInstanceRequestStateCompleted = "completed" +) + +const ( + // @enum ContainerFormat + ContainerFormatOva = "ova" +) + +const ( + // @enum ConversionTaskState + ConversionTaskStateActive = "active" + // @enum ConversionTaskState + ConversionTaskStateCancelling = "cancelling" + // @enum ConversionTaskState + ConversionTaskStateCancelled = "cancelled" + // @enum ConversionTaskState + ConversionTaskStateCompleted = "completed" +) + +const ( + // @enum CurrencyCodeValues + CurrencyCodeValuesUsd = "USD" +) + +const ( + // @enum DatafeedSubscriptionState + DatafeedSubscriptionStateActive = "Active" + // @enum DatafeedSubscriptionState + DatafeedSubscriptionStateInactive = "Inactive" +) + +const ( + // @enum DeviceType + DeviceTypeEbs = "ebs" + // @enum DeviceType + DeviceTypeInstanceStore = "instance-store" +) + +const ( + // @enum DiskImageFormat + DiskImageFormatVmdk = "VMDK" + // @enum DiskImageFormat + DiskImageFormatRaw = "RAW" + // @enum DiskImageFormat + DiskImageFormatVhd = "VHD" +) + +const ( + // @enum DomainType + DomainTypeVpc = "vpc" + // @enum DomainType + DomainTypeStandard = "standard" +) + +const ( + // @enum EventCode + EventCodeInstanceReboot = "instance-reboot" + // @enum EventCode + EventCodeSystemReboot = "system-reboot" + // @enum EventCode + EventCodeSystemMaintenance = "system-maintenance" + // @enum EventCode + EventCodeInstanceRetirement = "instance-retirement" + // @enum EventCode + EventCodeInstanceStop = "instance-stop" +) + +const ( + // @enum EventType + EventTypeInstanceChange = "instanceChange" + // @enum EventType + EventTypeFleetRequestChange = "fleetRequestChange" + // @enum EventType + EventTypeError = "error" +) + +const ( + // @enum ExcessCapacityTerminationPolicy + ExcessCapacityTerminationPolicyNoTermination = "noTermination" + // @enum ExcessCapacityTerminationPolicy + ExcessCapacityTerminationPolicyDefault = "default" +) + +const ( + // @enum ExportEnvironment + ExportEnvironmentCitrix = "citrix" + // @enum ExportEnvironment + ExportEnvironmentVmware = "vmware" + // @enum ExportEnvironment + ExportEnvironmentMicrosoft = "microsoft" +) + +const ( + // @enum ExportTaskState + ExportTaskStateActive = "active" + // @enum ExportTaskState + ExportTaskStateCancelling = "cancelling" + // @enum ExportTaskState + ExportTaskStateCancelled = "cancelled" + // @enum ExportTaskState + ExportTaskStateCompleted = "completed" +) + +const ( + // @enum FlowLogsResourceType + FlowLogsResourceTypeVpc = "VPC" + // @enum FlowLogsResourceType + FlowLogsResourceTypeSubnet = "Subnet" + // @enum FlowLogsResourceType + FlowLogsResourceTypeNetworkInterface = "NetworkInterface" +) + +const ( + // @enum GatewayType + GatewayTypeIpsec1 = "ipsec.1" +) + +const ( + // @enum HostTenancy + HostTenancyDedicated = "dedicated" + // @enum HostTenancy + HostTenancyHost = "host" +) + +const ( + // @enum HypervisorType + HypervisorTypeOvm = "ovm" + // @enum HypervisorType + HypervisorTypeXen = "xen" +) + +const ( + // @enum ImageAttributeName + ImageAttributeNameDescription = "description" + // @enum ImageAttributeName + ImageAttributeNameKernel = "kernel" + // @enum ImageAttributeName + ImageAttributeNameRamdisk = "ramdisk" + // @enum ImageAttributeName + ImageAttributeNameLaunchPermission = "launchPermission" + // @enum ImageAttributeName + ImageAttributeNameProductCodes = "productCodes" + // @enum ImageAttributeName + ImageAttributeNameBlockDeviceMapping = "blockDeviceMapping" + // @enum ImageAttributeName + ImageAttributeNameSriovNetSupport = "sriovNetSupport" +) + +const ( + // @enum ImageState + ImageStatePending = "pending" + // @enum ImageState + ImageStateAvailable = "available" + // @enum ImageState + ImageStateInvalid = "invalid" + // @enum ImageState + ImageStateDeregistered = "deregistered" + // @enum ImageState + ImageStateTransient = "transient" + // @enum ImageState + ImageStateFailed = "failed" + // @enum ImageState + ImageStateError = "error" +) + +const ( + // @enum ImageTypeValues + ImageTypeValuesMachine = "machine" + // @enum ImageTypeValues + ImageTypeValuesKernel = "kernel" + // @enum ImageTypeValues + ImageTypeValuesRamdisk = "ramdisk" +) + +const ( + // @enum InstanceAttributeName + InstanceAttributeNameInstanceType = "instanceType" + // @enum InstanceAttributeName + InstanceAttributeNameKernel = "kernel" + // @enum InstanceAttributeName + InstanceAttributeNameRamdisk = "ramdisk" + // @enum InstanceAttributeName + InstanceAttributeNameUserData = "userData" + // @enum InstanceAttributeName + InstanceAttributeNameDisableApiTermination = "disableApiTermination" + // @enum InstanceAttributeName + InstanceAttributeNameInstanceInitiatedShutdownBehavior = "instanceInitiatedShutdownBehavior" + // @enum InstanceAttributeName + InstanceAttributeNameRootDeviceName = "rootDeviceName" + // @enum InstanceAttributeName + InstanceAttributeNameBlockDeviceMapping = "blockDeviceMapping" + // @enum InstanceAttributeName + InstanceAttributeNameProductCodes = "productCodes" + // @enum InstanceAttributeName + InstanceAttributeNameSourceDestCheck = "sourceDestCheck" + // @enum InstanceAttributeName + InstanceAttributeNameGroupSet = "groupSet" + // @enum InstanceAttributeName + InstanceAttributeNameEbsOptimized = "ebsOptimized" + // @enum InstanceAttributeName + InstanceAttributeNameSriovNetSupport = "sriovNetSupport" +) + +const ( + // @enum InstanceLifecycleType + InstanceLifecycleTypeSpot = "spot" +) + +const ( + // @enum InstanceStateName + InstanceStateNamePending = "pending" + // @enum InstanceStateName + InstanceStateNameRunning = "running" + // @enum InstanceStateName + InstanceStateNameShuttingDown = "shutting-down" + // @enum InstanceStateName + InstanceStateNameTerminated = "terminated" + // @enum InstanceStateName + InstanceStateNameStopping = "stopping" + // @enum InstanceStateName + InstanceStateNameStopped = "stopped" +) + +const ( + // @enum InstanceType + InstanceTypeT1Micro = "t1.micro" + // @enum InstanceType + InstanceTypeM1Small = "m1.small" + // @enum InstanceType + InstanceTypeM1Medium = "m1.medium" + // @enum InstanceType + InstanceTypeM1Large = "m1.large" + // @enum InstanceType + InstanceTypeM1Xlarge = "m1.xlarge" + // @enum InstanceType + InstanceTypeM3Medium = "m3.medium" + // @enum InstanceType + InstanceTypeM3Large = "m3.large" + // @enum InstanceType + InstanceTypeM3Xlarge = "m3.xlarge" + // @enum InstanceType + InstanceTypeM32xlarge = "m3.2xlarge" + // @enum InstanceType + InstanceTypeM4Large = "m4.large" + // @enum InstanceType + InstanceTypeM4Xlarge = "m4.xlarge" + // @enum InstanceType + InstanceTypeM42xlarge = "m4.2xlarge" + // @enum InstanceType + InstanceTypeM44xlarge = "m4.4xlarge" + // @enum InstanceType + InstanceTypeM410xlarge = "m4.10xlarge" + // @enum InstanceType + InstanceTypeT2Nano = "t2.nano" + // @enum InstanceType + InstanceTypeT2Micro = "t2.micro" + // @enum InstanceType + InstanceTypeT2Small = "t2.small" + // @enum InstanceType + InstanceTypeT2Medium = "t2.medium" + // @enum InstanceType + InstanceTypeT2Large = "t2.large" + // @enum InstanceType + InstanceTypeM2Xlarge = "m2.xlarge" + // @enum InstanceType + InstanceTypeM22xlarge = "m2.2xlarge" + // @enum InstanceType + InstanceTypeM24xlarge = "m2.4xlarge" + // @enum InstanceType + InstanceTypeCr18xlarge = "cr1.8xlarge" + // @enum InstanceType + InstanceTypeI2Xlarge = "i2.xlarge" + // @enum InstanceType + InstanceTypeI22xlarge = "i2.2xlarge" + // @enum InstanceType + InstanceTypeI24xlarge = "i2.4xlarge" + // @enum InstanceType + InstanceTypeI28xlarge = "i2.8xlarge" + // @enum InstanceType + InstanceTypeHi14xlarge = "hi1.4xlarge" + // @enum InstanceType + InstanceTypeHs18xlarge = "hs1.8xlarge" + // @enum InstanceType + InstanceTypeC1Medium = "c1.medium" + // @enum InstanceType + InstanceTypeC1Xlarge = "c1.xlarge" + // @enum InstanceType + InstanceTypeC3Large = "c3.large" + // @enum InstanceType + InstanceTypeC3Xlarge = "c3.xlarge" + // @enum InstanceType + InstanceTypeC32xlarge = "c3.2xlarge" + // @enum InstanceType + InstanceTypeC34xlarge = "c3.4xlarge" + // @enum InstanceType + InstanceTypeC38xlarge = "c3.8xlarge" + // @enum InstanceType + InstanceTypeC4Large = "c4.large" + // @enum InstanceType + InstanceTypeC4Xlarge = "c4.xlarge" + // @enum InstanceType + InstanceTypeC42xlarge = "c4.2xlarge" + // @enum InstanceType + InstanceTypeC44xlarge = "c4.4xlarge" + // @enum InstanceType + InstanceTypeC48xlarge = "c4.8xlarge" + // @enum InstanceType + InstanceTypeCc14xlarge = "cc1.4xlarge" + // @enum InstanceType + InstanceTypeCc28xlarge = "cc2.8xlarge" + // @enum InstanceType + InstanceTypeG22xlarge = "g2.2xlarge" + // @enum InstanceType + InstanceTypeCg14xlarge = "cg1.4xlarge" + // @enum InstanceType + InstanceTypeR3Large = "r3.large" + // @enum InstanceType + InstanceTypeR3Xlarge = "r3.xlarge" + // @enum InstanceType + InstanceTypeR32xlarge = "r3.2xlarge" + // @enum InstanceType + InstanceTypeR34xlarge = "r3.4xlarge" + // @enum InstanceType + InstanceTypeR38xlarge = "r3.8xlarge" + // @enum InstanceType + InstanceTypeD2Xlarge = "d2.xlarge" + // @enum InstanceType + InstanceTypeD22xlarge = "d2.2xlarge" + // @enum InstanceType + InstanceTypeD24xlarge = "d2.4xlarge" + // @enum InstanceType + InstanceTypeD28xlarge = "d2.8xlarge" +) + +const ( + // @enum ListingState + ListingStateAvailable = "available" + // @enum ListingState + ListingStateSold = "sold" + // @enum ListingState + ListingStateCancelled = "cancelled" + // @enum ListingState + ListingStatePending = "pending" +) + +const ( + // @enum ListingStatus + ListingStatusActive = "active" + // @enum ListingStatus + ListingStatusPending = "pending" + // @enum ListingStatus + ListingStatusCancelled = "cancelled" + // @enum ListingStatus + ListingStatusClosed = "closed" +) + +const ( + // @enum MonitoringState + MonitoringStateDisabled = "disabled" + // @enum MonitoringState + MonitoringStateDisabling = "disabling" + // @enum MonitoringState + MonitoringStateEnabled = "enabled" + // @enum MonitoringState + MonitoringStatePending = "pending" +) + +const ( + // @enum MoveStatus + MoveStatusMovingToVpc = "movingToVpc" + // @enum MoveStatus + MoveStatusRestoringToClassic = "restoringToClassic" +) + +const ( + // @enum NatGatewayState + NatGatewayStatePending = "pending" + // @enum NatGatewayState + NatGatewayStateFailed = "failed" + // @enum NatGatewayState + NatGatewayStateAvailable = "available" + // @enum NatGatewayState + NatGatewayStateDeleting = "deleting" + // @enum NatGatewayState + NatGatewayStateDeleted = "deleted" +) + +const ( + // @enum NetworkInterfaceAttribute + NetworkInterfaceAttributeDescription = "description" + // @enum NetworkInterfaceAttribute + NetworkInterfaceAttributeGroupSet = "groupSet" + // @enum NetworkInterfaceAttribute + NetworkInterfaceAttributeSourceDestCheck = "sourceDestCheck" + // @enum NetworkInterfaceAttribute + NetworkInterfaceAttributeAttachment = "attachment" +) + +const ( + // @enum NetworkInterfaceStatus + NetworkInterfaceStatusAvailable = "available" + // @enum NetworkInterfaceStatus + NetworkInterfaceStatusAttaching = "attaching" + // @enum NetworkInterfaceStatus + NetworkInterfaceStatusInUse = "in-use" + // @enum NetworkInterfaceStatus + NetworkInterfaceStatusDetaching = "detaching" +) + +const ( + // @enum NetworkInterfaceType + NetworkInterfaceTypeInterface = "interface" + // @enum NetworkInterfaceType + NetworkInterfaceTypeNatGateway = "natGateway" +) + +const ( + // @enum OfferingTypeValues + OfferingTypeValuesHeavyUtilization = "Heavy Utilization" + // @enum OfferingTypeValues + OfferingTypeValuesMediumUtilization = "Medium Utilization" + // @enum OfferingTypeValues + OfferingTypeValuesLightUtilization = "Light Utilization" + // @enum OfferingTypeValues + OfferingTypeValuesNoUpfront = "No Upfront" + // @enum OfferingTypeValues + OfferingTypeValuesPartialUpfront = "Partial Upfront" + // @enum OfferingTypeValues + OfferingTypeValuesAllUpfront = "All Upfront" +) + +const ( + // @enum OperationType + OperationTypeAdd = "add" + // @enum OperationType + OperationTypeRemove = "remove" +) + +const ( + // @enum PermissionGroup + PermissionGroupAll = "all" +) + +const ( + // @enum PlacementGroupState + PlacementGroupStatePending = "pending" + // @enum PlacementGroupState + PlacementGroupStateAvailable = "available" + // @enum PlacementGroupState + PlacementGroupStateDeleting = "deleting" + // @enum PlacementGroupState + PlacementGroupStateDeleted = "deleted" +) + +const ( + // @enum PlacementStrategy + PlacementStrategyCluster = "cluster" +) + +const ( + // @enum PlatformValues + PlatformValuesWindows = "Windows" +) + +const ( + // @enum ProductCodeValues + ProductCodeValuesDevpay = "devpay" + // @enum ProductCodeValues + ProductCodeValuesMarketplace = "marketplace" +) + +const ( + // @enum RIProductDescription + RIProductDescriptionLinuxUnix = "Linux/UNIX" + // @enum RIProductDescription + RIProductDescriptionLinuxUnixamazonVpc = "Linux/UNIX (Amazon VPC)" + // @enum RIProductDescription + RIProductDescriptionWindows = "Windows" + // @enum RIProductDescription + RIProductDescriptionWindowsAmazonVpc = "Windows (Amazon VPC)" +) + +const ( + // @enum RecurringChargeFrequency + RecurringChargeFrequencyHourly = "Hourly" +) + +const ( + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesInstanceStuckInState = "instance-stuck-in-state" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesUnresponsive = "unresponsive" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesNotAcceptingCredentials = "not-accepting-credentials" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesPasswordNotAvailable = "password-not-available" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesPerformanceNetwork = "performance-network" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesPerformanceInstanceStore = "performance-instance-store" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesPerformanceEbsVolume = "performance-ebs-volume" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesPerformanceOther = "performance-other" + // @enum ReportInstanceReasonCodes + ReportInstanceReasonCodesOther = "other" +) + +const ( + // @enum ReportStatusType + ReportStatusTypeOk = "ok" + // @enum ReportStatusType + ReportStatusTypeImpaired = "impaired" +) + +const ( + // @enum ReservedInstanceState + ReservedInstanceStatePaymentPending = "payment-pending" + // @enum ReservedInstanceState + ReservedInstanceStateActive = "active" + // @enum ReservedInstanceState + ReservedInstanceStatePaymentFailed = "payment-failed" + // @enum ReservedInstanceState + ReservedInstanceStateRetired = "retired" +) + +const ( + // @enum ResetImageAttributeName + ResetImageAttributeNameLaunchPermission = "launchPermission" +) + +const ( + // @enum ResourceType + ResourceTypeCustomerGateway = "customer-gateway" + // @enum ResourceType + ResourceTypeDhcpOptions = "dhcp-options" + // @enum ResourceType + ResourceTypeImage = "image" + // @enum ResourceType + ResourceTypeInstance = "instance" + // @enum ResourceType + ResourceTypeInternetGateway = "internet-gateway" + // @enum ResourceType + ResourceTypeNetworkAcl = "network-acl" + // @enum ResourceType + ResourceTypeNetworkInterface = "network-interface" + // @enum ResourceType + ResourceTypeReservedInstances = "reserved-instances" + // @enum ResourceType + ResourceTypeRouteTable = "route-table" + // @enum ResourceType + ResourceTypeSnapshot = "snapshot" + // @enum ResourceType + ResourceTypeSpotInstancesRequest = "spot-instances-request" + // @enum ResourceType + ResourceTypeSubnet = "subnet" + // @enum ResourceType + ResourceTypeSecurityGroup = "security-group" + // @enum ResourceType + ResourceTypeVolume = "volume" + // @enum ResourceType + ResourceTypeVpc = "vpc" + // @enum ResourceType + ResourceTypeVpnConnection = "vpn-connection" + // @enum ResourceType + ResourceTypeVpnGateway = "vpn-gateway" +) + +const ( + // @enum RouteOrigin + RouteOriginCreateRouteTable = "CreateRouteTable" + // @enum RouteOrigin + RouteOriginCreateRoute = "CreateRoute" + // @enum RouteOrigin + RouteOriginEnableVgwRoutePropagation = "EnableVgwRoutePropagation" +) + +const ( + // @enum RouteState + RouteStateActive = "active" + // @enum RouteState + RouteStateBlackhole = "blackhole" +) + +const ( + // @enum RuleAction + RuleActionAllow = "allow" + // @enum RuleAction + RuleActionDeny = "deny" +) + +const ( + // @enum ShutdownBehavior + ShutdownBehaviorStop = "stop" + // @enum ShutdownBehavior + ShutdownBehaviorTerminate = "terminate" +) + +const ( + // @enum SnapshotAttributeName + SnapshotAttributeNameProductCodes = "productCodes" + // @enum SnapshotAttributeName + SnapshotAttributeNameCreateVolumePermission = "createVolumePermission" +) + +const ( + // @enum SnapshotState + SnapshotStatePending = "pending" + // @enum SnapshotState + SnapshotStateCompleted = "completed" + // @enum SnapshotState + SnapshotStateError = "error" +) + +const ( + // @enum SpotInstanceState + SpotInstanceStateOpen = "open" + // @enum SpotInstanceState + SpotInstanceStateActive = "active" + // @enum SpotInstanceState + SpotInstanceStateClosed = "closed" + // @enum SpotInstanceState + SpotInstanceStateCancelled = "cancelled" + // @enum SpotInstanceState + SpotInstanceStateFailed = "failed" +) + +const ( + // @enum SpotInstanceType + SpotInstanceTypeOneTime = "one-time" + // @enum SpotInstanceType + SpotInstanceTypePersistent = "persistent" +) + +const ( + // @enum State + StatePending = "Pending" + // @enum State + StateAvailable = "Available" + // @enum State + StateDeleting = "Deleting" + // @enum State + StateDeleted = "Deleted" +) + +const ( + // @enum Status + StatusMoveInProgress = "MoveInProgress" + // @enum Status + StatusInVpc = "InVpc" + // @enum Status + StatusInClassic = "InClassic" +) + +const ( + // @enum StatusName + StatusNameReachability = "reachability" +) + +const ( + // @enum StatusType + StatusTypePassed = "passed" + // @enum StatusType + StatusTypeFailed = "failed" + // @enum StatusType + StatusTypeInsufficientData = "insufficient-data" + // @enum StatusType + StatusTypeInitializing = "initializing" +) + +const ( + // @enum SubnetState + SubnetStatePending = "pending" + // @enum SubnetState + SubnetStateAvailable = "available" +) + +const ( + // @enum SummaryStatus + SummaryStatusOk = "ok" + // @enum SummaryStatus + SummaryStatusImpaired = "impaired" + // @enum SummaryStatus + SummaryStatusInsufficientData = "insufficient-data" + // @enum SummaryStatus + SummaryStatusNotApplicable = "not-applicable" + // @enum SummaryStatus + SummaryStatusInitializing = "initializing" +) + +const ( + // @enum TelemetryStatus + TelemetryStatusUp = "UP" + // @enum TelemetryStatus + TelemetryStatusDown = "DOWN" +) + +const ( + // @enum Tenancy + TenancyDefault = "default" + // @enum Tenancy + TenancyDedicated = "dedicated" + // @enum Tenancy + TenancyHost = "host" +) + +const ( + // @enum TrafficType + TrafficTypeAccept = "ACCEPT" + // @enum TrafficType + TrafficTypeReject = "REJECT" + // @enum TrafficType + TrafficTypeAll = "ALL" +) + +const ( + // @enum VirtualizationType + VirtualizationTypeHvm = "hvm" + // @enum VirtualizationType + VirtualizationTypeParavirtual = "paravirtual" +) + +const ( + // @enum VolumeAttachmentState + VolumeAttachmentStateAttaching = "attaching" + // @enum VolumeAttachmentState + VolumeAttachmentStateAttached = "attached" + // @enum VolumeAttachmentState + VolumeAttachmentStateDetaching = "detaching" + // @enum VolumeAttachmentState + VolumeAttachmentStateDetached = "detached" +) + +const ( + // @enum VolumeAttributeName + VolumeAttributeNameAutoEnableIo = "autoEnableIO" + // @enum VolumeAttributeName + VolumeAttributeNameProductCodes = "productCodes" +) + +const ( + // @enum VolumeState + VolumeStateCreating = "creating" + // @enum VolumeState + VolumeStateAvailable = "available" + // @enum VolumeState + VolumeStateInUse = "in-use" + // @enum VolumeState + VolumeStateDeleting = "deleting" + // @enum VolumeState + VolumeStateDeleted = "deleted" + // @enum VolumeState + VolumeStateError = "error" +) + +const ( + // @enum VolumeStatusInfoStatus + VolumeStatusInfoStatusOk = "ok" + // @enum VolumeStatusInfoStatus + VolumeStatusInfoStatusImpaired = "impaired" + // @enum VolumeStatusInfoStatus + VolumeStatusInfoStatusInsufficientData = "insufficient-data" +) + +const ( + // @enum VolumeStatusName + VolumeStatusNameIoEnabled = "io-enabled" + // @enum VolumeStatusName + VolumeStatusNameIoPerformance = "io-performance" +) + +const ( + // @enum VolumeType + VolumeTypeStandard = "standard" + // @enum VolumeType + VolumeTypeIo1 = "io1" + // @enum VolumeType + VolumeTypeGp2 = "gp2" +) + +const ( + // @enum VpcAttributeName + VpcAttributeNameEnableDnsSupport = "enableDnsSupport" + // @enum VpcAttributeName + VpcAttributeNameEnableDnsHostnames = "enableDnsHostnames" +) + +const ( + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeInitiatingRequest = "initiating-request" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodePendingAcceptance = "pending-acceptance" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeActive = "active" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeDeleted = "deleted" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeRejected = "rejected" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeFailed = "failed" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeExpired = "expired" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeProvisioning = "provisioning" + // @enum VpcPeeringConnectionStateReasonCode + VpcPeeringConnectionStateReasonCodeDeleting = "deleting" +) + +const ( + // @enum VpcState + VpcStatePending = "pending" + // @enum VpcState + VpcStateAvailable = "available" +) + +const ( + // @enum VpnState + VpnStatePending = "pending" + // @enum VpnState + VpnStateAvailable = "available" + // @enum VpnState + VpnStateDeleting = "deleting" + // @enum VpnState + VpnStateDeleted = "deleted" +) + +const ( + // @enum VpnStaticRouteSource + VpnStaticRouteSourceStatic = "Static" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go b/vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go new file mode 100644 index 000000000..9e94fe671 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go @@ -0,0 +1,55 @@ +package ec2 + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/endpoints" +) + +func init() { + initRequest = func(r *request.Request) { + if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter + r.Handlers.Build.PushFront(fillPresignedURL) + } + } +} + +func fillPresignedURL(r *request.Request) { + if !r.ParamsFilled() { + return + } + + origParams := r.Params.(*CopySnapshotInput) + + // Stop if PresignedURL/DestinationRegion is set + if origParams.PresignedUrl != nil || origParams.DestinationRegion != nil { + return + } + + origParams.DestinationRegion = r.Config.Region + newParams := awsutil.CopyOf(r.Params).(*CopySnapshotInput) + + // Create a new request based on the existing request. We will use this to + // presign the CopySnapshot request against the source region. + cfg := r.Config.Copy(aws.NewConfig(). + WithEndpoint(""). + WithRegion(aws.StringValue(origParams.SourceRegion))) + + clientInfo := r.ClientInfo + clientInfo.Endpoint, clientInfo.SigningRegion = endpoints.EndpointForRegion( + clientInfo.ServiceName, aws.StringValue(cfg.Region), aws.BoolValue(cfg.DisableSSL)) + + // Presign a CopySnapshot request with modified params + req := request.New(*cfg, clientInfo, r.Handlers, r.Retryer, r.Operation, newParams, r.Data) + url, err := req.Presign(5 * time.Minute) // 5 minutes should be enough. + if err != nil { // bubble error back up to original request + r.Error = err + return + } + + // We have our URL, set it on params + origParams.PresignedUrl = &url +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go b/vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go new file mode 100644 index 000000000..3091c64d5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go @@ -0,0 +1,832 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package ec2iface provides an interface for the Amazon Elastic Compute Cloud. +package ec2iface + +import ( + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/ec2" +) + +// EC2API is the interface type for ec2.EC2. +type EC2API interface { + AcceptVpcPeeringConnectionRequest(*ec2.AcceptVpcPeeringConnectionInput) (*request.Request, *ec2.AcceptVpcPeeringConnectionOutput) + + AcceptVpcPeeringConnection(*ec2.AcceptVpcPeeringConnectionInput) (*ec2.AcceptVpcPeeringConnectionOutput, error) + + AllocateAddressRequest(*ec2.AllocateAddressInput) (*request.Request, *ec2.AllocateAddressOutput) + + AllocateAddress(*ec2.AllocateAddressInput) (*ec2.AllocateAddressOutput, error) + + AllocateHostsRequest(*ec2.AllocateHostsInput) (*request.Request, *ec2.AllocateHostsOutput) + + AllocateHosts(*ec2.AllocateHostsInput) (*ec2.AllocateHostsOutput, error) + + AssignPrivateIpAddressesRequest(*ec2.AssignPrivateIpAddressesInput) (*request.Request, *ec2.AssignPrivateIpAddressesOutput) + + AssignPrivateIpAddresses(*ec2.AssignPrivateIpAddressesInput) (*ec2.AssignPrivateIpAddressesOutput, error) + + AssociateAddressRequest(*ec2.AssociateAddressInput) (*request.Request, *ec2.AssociateAddressOutput) + + AssociateAddress(*ec2.AssociateAddressInput) (*ec2.AssociateAddressOutput, error) + + AssociateDhcpOptionsRequest(*ec2.AssociateDhcpOptionsInput) (*request.Request, *ec2.AssociateDhcpOptionsOutput) + + AssociateDhcpOptions(*ec2.AssociateDhcpOptionsInput) (*ec2.AssociateDhcpOptionsOutput, error) + + AssociateRouteTableRequest(*ec2.AssociateRouteTableInput) (*request.Request, *ec2.AssociateRouteTableOutput) + + AssociateRouteTable(*ec2.AssociateRouteTableInput) (*ec2.AssociateRouteTableOutput, error) + + AttachClassicLinkVpcRequest(*ec2.AttachClassicLinkVpcInput) (*request.Request, *ec2.AttachClassicLinkVpcOutput) + + AttachClassicLinkVpc(*ec2.AttachClassicLinkVpcInput) (*ec2.AttachClassicLinkVpcOutput, error) + + AttachInternetGatewayRequest(*ec2.AttachInternetGatewayInput) (*request.Request, *ec2.AttachInternetGatewayOutput) + + AttachInternetGateway(*ec2.AttachInternetGatewayInput) (*ec2.AttachInternetGatewayOutput, error) + + AttachNetworkInterfaceRequest(*ec2.AttachNetworkInterfaceInput) (*request.Request, *ec2.AttachNetworkInterfaceOutput) + + AttachNetworkInterface(*ec2.AttachNetworkInterfaceInput) (*ec2.AttachNetworkInterfaceOutput, error) + + AttachVolumeRequest(*ec2.AttachVolumeInput) (*request.Request, *ec2.VolumeAttachment) + + AttachVolume(*ec2.AttachVolumeInput) (*ec2.VolumeAttachment, error) + + AttachVpnGatewayRequest(*ec2.AttachVpnGatewayInput) (*request.Request, *ec2.AttachVpnGatewayOutput) + + AttachVpnGateway(*ec2.AttachVpnGatewayInput) (*ec2.AttachVpnGatewayOutput, error) + + AuthorizeSecurityGroupEgressRequest(*ec2.AuthorizeSecurityGroupEgressInput) (*request.Request, *ec2.AuthorizeSecurityGroupEgressOutput) + + AuthorizeSecurityGroupEgress(*ec2.AuthorizeSecurityGroupEgressInput) (*ec2.AuthorizeSecurityGroupEgressOutput, error) + + AuthorizeSecurityGroupIngressRequest(*ec2.AuthorizeSecurityGroupIngressInput) (*request.Request, *ec2.AuthorizeSecurityGroupIngressOutput) + + AuthorizeSecurityGroupIngress(*ec2.AuthorizeSecurityGroupIngressInput) (*ec2.AuthorizeSecurityGroupIngressOutput, error) + + BundleInstanceRequest(*ec2.BundleInstanceInput) (*request.Request, *ec2.BundleInstanceOutput) + + BundleInstance(*ec2.BundleInstanceInput) (*ec2.BundleInstanceOutput, error) + + CancelBundleTaskRequest(*ec2.CancelBundleTaskInput) (*request.Request, *ec2.CancelBundleTaskOutput) + + CancelBundleTask(*ec2.CancelBundleTaskInput) (*ec2.CancelBundleTaskOutput, error) + + CancelConversionTaskRequest(*ec2.CancelConversionTaskInput) (*request.Request, *ec2.CancelConversionTaskOutput) + + CancelConversionTask(*ec2.CancelConversionTaskInput) (*ec2.CancelConversionTaskOutput, error) + + CancelExportTaskRequest(*ec2.CancelExportTaskInput) (*request.Request, *ec2.CancelExportTaskOutput) + + CancelExportTask(*ec2.CancelExportTaskInput) (*ec2.CancelExportTaskOutput, error) + + CancelImportTaskRequest(*ec2.CancelImportTaskInput) (*request.Request, *ec2.CancelImportTaskOutput) + + CancelImportTask(*ec2.CancelImportTaskInput) (*ec2.CancelImportTaskOutput, error) + + CancelReservedInstancesListingRequest(*ec2.CancelReservedInstancesListingInput) (*request.Request, *ec2.CancelReservedInstancesListingOutput) + + CancelReservedInstancesListing(*ec2.CancelReservedInstancesListingInput) (*ec2.CancelReservedInstancesListingOutput, error) + + CancelSpotFleetRequestsRequest(*ec2.CancelSpotFleetRequestsInput) (*request.Request, *ec2.CancelSpotFleetRequestsOutput) + + CancelSpotFleetRequests(*ec2.CancelSpotFleetRequestsInput) (*ec2.CancelSpotFleetRequestsOutput, error) + + CancelSpotInstanceRequestsRequest(*ec2.CancelSpotInstanceRequestsInput) (*request.Request, *ec2.CancelSpotInstanceRequestsOutput) + + CancelSpotInstanceRequests(*ec2.CancelSpotInstanceRequestsInput) (*ec2.CancelSpotInstanceRequestsOutput, error) + + ConfirmProductInstanceRequest(*ec2.ConfirmProductInstanceInput) (*request.Request, *ec2.ConfirmProductInstanceOutput) + + ConfirmProductInstance(*ec2.ConfirmProductInstanceInput) (*ec2.ConfirmProductInstanceOutput, error) + + CopyImageRequest(*ec2.CopyImageInput) (*request.Request, *ec2.CopyImageOutput) + + CopyImage(*ec2.CopyImageInput) (*ec2.CopyImageOutput, error) + + CopySnapshotRequest(*ec2.CopySnapshotInput) (*request.Request, *ec2.CopySnapshotOutput) + + CopySnapshot(*ec2.CopySnapshotInput) (*ec2.CopySnapshotOutput, error) + + CreateCustomerGatewayRequest(*ec2.CreateCustomerGatewayInput) (*request.Request, *ec2.CreateCustomerGatewayOutput) + + CreateCustomerGateway(*ec2.CreateCustomerGatewayInput) (*ec2.CreateCustomerGatewayOutput, error) + + CreateDhcpOptionsRequest(*ec2.CreateDhcpOptionsInput) (*request.Request, *ec2.CreateDhcpOptionsOutput) + + CreateDhcpOptions(*ec2.CreateDhcpOptionsInput) (*ec2.CreateDhcpOptionsOutput, error) + + CreateFlowLogsRequest(*ec2.CreateFlowLogsInput) (*request.Request, *ec2.CreateFlowLogsOutput) + + CreateFlowLogs(*ec2.CreateFlowLogsInput) (*ec2.CreateFlowLogsOutput, error) + + CreateImageRequest(*ec2.CreateImageInput) (*request.Request, *ec2.CreateImageOutput) + + CreateImage(*ec2.CreateImageInput) (*ec2.CreateImageOutput, error) + + CreateInstanceExportTaskRequest(*ec2.CreateInstanceExportTaskInput) (*request.Request, *ec2.CreateInstanceExportTaskOutput) + + CreateInstanceExportTask(*ec2.CreateInstanceExportTaskInput) (*ec2.CreateInstanceExportTaskOutput, error) + + CreateInternetGatewayRequest(*ec2.CreateInternetGatewayInput) (*request.Request, *ec2.CreateInternetGatewayOutput) + + CreateInternetGateway(*ec2.CreateInternetGatewayInput) (*ec2.CreateInternetGatewayOutput, error) + + CreateKeyPairRequest(*ec2.CreateKeyPairInput) (*request.Request, *ec2.CreateKeyPairOutput) + + CreateKeyPair(*ec2.CreateKeyPairInput) (*ec2.CreateKeyPairOutput, error) + + CreateNatGatewayRequest(*ec2.CreateNatGatewayInput) (*request.Request, *ec2.CreateNatGatewayOutput) + + CreateNatGateway(*ec2.CreateNatGatewayInput) (*ec2.CreateNatGatewayOutput, error) + + CreateNetworkAclRequest(*ec2.CreateNetworkAclInput) (*request.Request, *ec2.CreateNetworkAclOutput) + + CreateNetworkAcl(*ec2.CreateNetworkAclInput) (*ec2.CreateNetworkAclOutput, error) + + CreateNetworkAclEntryRequest(*ec2.CreateNetworkAclEntryInput) (*request.Request, *ec2.CreateNetworkAclEntryOutput) + + CreateNetworkAclEntry(*ec2.CreateNetworkAclEntryInput) (*ec2.CreateNetworkAclEntryOutput, error) + + CreateNetworkInterfaceRequest(*ec2.CreateNetworkInterfaceInput) (*request.Request, *ec2.CreateNetworkInterfaceOutput) + + CreateNetworkInterface(*ec2.CreateNetworkInterfaceInput) (*ec2.CreateNetworkInterfaceOutput, error) + + CreatePlacementGroupRequest(*ec2.CreatePlacementGroupInput) (*request.Request, *ec2.CreatePlacementGroupOutput) + + CreatePlacementGroup(*ec2.CreatePlacementGroupInput) (*ec2.CreatePlacementGroupOutput, error) + + CreateReservedInstancesListingRequest(*ec2.CreateReservedInstancesListingInput) (*request.Request, *ec2.CreateReservedInstancesListingOutput) + + CreateReservedInstancesListing(*ec2.CreateReservedInstancesListingInput) (*ec2.CreateReservedInstancesListingOutput, error) + + CreateRouteRequest(*ec2.CreateRouteInput) (*request.Request, *ec2.CreateRouteOutput) + + CreateRoute(*ec2.CreateRouteInput) (*ec2.CreateRouteOutput, error) + + CreateRouteTableRequest(*ec2.CreateRouteTableInput) (*request.Request, *ec2.CreateRouteTableOutput) + + CreateRouteTable(*ec2.CreateRouteTableInput) (*ec2.CreateRouteTableOutput, error) + + CreateSecurityGroupRequest(*ec2.CreateSecurityGroupInput) (*request.Request, *ec2.CreateSecurityGroupOutput) + + CreateSecurityGroup(*ec2.CreateSecurityGroupInput) (*ec2.CreateSecurityGroupOutput, error) + + CreateSnapshotRequest(*ec2.CreateSnapshotInput) (*request.Request, *ec2.Snapshot) + + CreateSnapshot(*ec2.CreateSnapshotInput) (*ec2.Snapshot, error) + + CreateSpotDatafeedSubscriptionRequest(*ec2.CreateSpotDatafeedSubscriptionInput) (*request.Request, *ec2.CreateSpotDatafeedSubscriptionOutput) + + CreateSpotDatafeedSubscription(*ec2.CreateSpotDatafeedSubscriptionInput) (*ec2.CreateSpotDatafeedSubscriptionOutput, error) + + CreateSubnetRequest(*ec2.CreateSubnetInput) (*request.Request, *ec2.CreateSubnetOutput) + + CreateSubnet(*ec2.CreateSubnetInput) (*ec2.CreateSubnetOutput, error) + + CreateTagsRequest(*ec2.CreateTagsInput) (*request.Request, *ec2.CreateTagsOutput) + + CreateTags(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) + + CreateVolumeRequest(*ec2.CreateVolumeInput) (*request.Request, *ec2.Volume) + + CreateVolume(*ec2.CreateVolumeInput) (*ec2.Volume, error) + + CreateVpcRequest(*ec2.CreateVpcInput) (*request.Request, *ec2.CreateVpcOutput) + + CreateVpc(*ec2.CreateVpcInput) (*ec2.CreateVpcOutput, error) + + CreateVpcEndpointRequest(*ec2.CreateVpcEndpointInput) (*request.Request, *ec2.CreateVpcEndpointOutput) + + CreateVpcEndpoint(*ec2.CreateVpcEndpointInput) (*ec2.CreateVpcEndpointOutput, error) + + CreateVpcPeeringConnectionRequest(*ec2.CreateVpcPeeringConnectionInput) (*request.Request, *ec2.CreateVpcPeeringConnectionOutput) + + CreateVpcPeeringConnection(*ec2.CreateVpcPeeringConnectionInput) (*ec2.CreateVpcPeeringConnectionOutput, error) + + CreateVpnConnectionRequest(*ec2.CreateVpnConnectionInput) (*request.Request, *ec2.CreateVpnConnectionOutput) + + CreateVpnConnection(*ec2.CreateVpnConnectionInput) (*ec2.CreateVpnConnectionOutput, error) + + CreateVpnConnectionRouteRequest(*ec2.CreateVpnConnectionRouteInput) (*request.Request, *ec2.CreateVpnConnectionRouteOutput) + + CreateVpnConnectionRoute(*ec2.CreateVpnConnectionRouteInput) (*ec2.CreateVpnConnectionRouteOutput, error) + + CreateVpnGatewayRequest(*ec2.CreateVpnGatewayInput) (*request.Request, *ec2.CreateVpnGatewayOutput) + + CreateVpnGateway(*ec2.CreateVpnGatewayInput) (*ec2.CreateVpnGatewayOutput, error) + + DeleteCustomerGatewayRequest(*ec2.DeleteCustomerGatewayInput) (*request.Request, *ec2.DeleteCustomerGatewayOutput) + + DeleteCustomerGateway(*ec2.DeleteCustomerGatewayInput) (*ec2.DeleteCustomerGatewayOutput, error) + + DeleteDhcpOptionsRequest(*ec2.DeleteDhcpOptionsInput) (*request.Request, *ec2.DeleteDhcpOptionsOutput) + + DeleteDhcpOptions(*ec2.DeleteDhcpOptionsInput) (*ec2.DeleteDhcpOptionsOutput, error) + + DeleteFlowLogsRequest(*ec2.DeleteFlowLogsInput) (*request.Request, *ec2.DeleteFlowLogsOutput) + + DeleteFlowLogs(*ec2.DeleteFlowLogsInput) (*ec2.DeleteFlowLogsOutput, error) + + DeleteInternetGatewayRequest(*ec2.DeleteInternetGatewayInput) (*request.Request, *ec2.DeleteInternetGatewayOutput) + + DeleteInternetGateway(*ec2.DeleteInternetGatewayInput) (*ec2.DeleteInternetGatewayOutput, error) + + DeleteKeyPairRequest(*ec2.DeleteKeyPairInput) (*request.Request, *ec2.DeleteKeyPairOutput) + + DeleteKeyPair(*ec2.DeleteKeyPairInput) (*ec2.DeleteKeyPairOutput, error) + + DeleteNatGatewayRequest(*ec2.DeleteNatGatewayInput) (*request.Request, *ec2.DeleteNatGatewayOutput) + + DeleteNatGateway(*ec2.DeleteNatGatewayInput) (*ec2.DeleteNatGatewayOutput, error) + + DeleteNetworkAclRequest(*ec2.DeleteNetworkAclInput) (*request.Request, *ec2.DeleteNetworkAclOutput) + + DeleteNetworkAcl(*ec2.DeleteNetworkAclInput) (*ec2.DeleteNetworkAclOutput, error) + + DeleteNetworkAclEntryRequest(*ec2.DeleteNetworkAclEntryInput) (*request.Request, *ec2.DeleteNetworkAclEntryOutput) + + DeleteNetworkAclEntry(*ec2.DeleteNetworkAclEntryInput) (*ec2.DeleteNetworkAclEntryOutput, error) + + DeleteNetworkInterfaceRequest(*ec2.DeleteNetworkInterfaceInput) (*request.Request, *ec2.DeleteNetworkInterfaceOutput) + + DeleteNetworkInterface(*ec2.DeleteNetworkInterfaceInput) (*ec2.DeleteNetworkInterfaceOutput, error) + + DeletePlacementGroupRequest(*ec2.DeletePlacementGroupInput) (*request.Request, *ec2.DeletePlacementGroupOutput) + + DeletePlacementGroup(*ec2.DeletePlacementGroupInput) (*ec2.DeletePlacementGroupOutput, error) + + DeleteRouteRequest(*ec2.DeleteRouteInput) (*request.Request, *ec2.DeleteRouteOutput) + + DeleteRoute(*ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error) + + DeleteRouteTableRequest(*ec2.DeleteRouteTableInput) (*request.Request, *ec2.DeleteRouteTableOutput) + + DeleteRouteTable(*ec2.DeleteRouteTableInput) (*ec2.DeleteRouteTableOutput, error) + + DeleteSecurityGroupRequest(*ec2.DeleteSecurityGroupInput) (*request.Request, *ec2.DeleteSecurityGroupOutput) + + DeleteSecurityGroup(*ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) + + DeleteSnapshotRequest(*ec2.DeleteSnapshotInput) (*request.Request, *ec2.DeleteSnapshotOutput) + + DeleteSnapshot(*ec2.DeleteSnapshotInput) (*ec2.DeleteSnapshotOutput, error) + + DeleteSpotDatafeedSubscriptionRequest(*ec2.DeleteSpotDatafeedSubscriptionInput) (*request.Request, *ec2.DeleteSpotDatafeedSubscriptionOutput) + + DeleteSpotDatafeedSubscription(*ec2.DeleteSpotDatafeedSubscriptionInput) (*ec2.DeleteSpotDatafeedSubscriptionOutput, error) + + DeleteSubnetRequest(*ec2.DeleteSubnetInput) (*request.Request, *ec2.DeleteSubnetOutput) + + DeleteSubnet(*ec2.DeleteSubnetInput) (*ec2.DeleteSubnetOutput, error) + + DeleteTagsRequest(*ec2.DeleteTagsInput) (*request.Request, *ec2.DeleteTagsOutput) + + DeleteTags(*ec2.DeleteTagsInput) (*ec2.DeleteTagsOutput, error) + + DeleteVolumeRequest(*ec2.DeleteVolumeInput) (*request.Request, *ec2.DeleteVolumeOutput) + + DeleteVolume(*ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) + + DeleteVpcRequest(*ec2.DeleteVpcInput) (*request.Request, *ec2.DeleteVpcOutput) + + DeleteVpc(*ec2.DeleteVpcInput) (*ec2.DeleteVpcOutput, error) + + DeleteVpcEndpointsRequest(*ec2.DeleteVpcEndpointsInput) (*request.Request, *ec2.DeleteVpcEndpointsOutput) + + DeleteVpcEndpoints(*ec2.DeleteVpcEndpointsInput) (*ec2.DeleteVpcEndpointsOutput, error) + + DeleteVpcPeeringConnectionRequest(*ec2.DeleteVpcPeeringConnectionInput) (*request.Request, *ec2.DeleteVpcPeeringConnectionOutput) + + DeleteVpcPeeringConnection(*ec2.DeleteVpcPeeringConnectionInput) (*ec2.DeleteVpcPeeringConnectionOutput, error) + + DeleteVpnConnectionRequest(*ec2.DeleteVpnConnectionInput) (*request.Request, *ec2.DeleteVpnConnectionOutput) + + DeleteVpnConnection(*ec2.DeleteVpnConnectionInput) (*ec2.DeleteVpnConnectionOutput, error) + + DeleteVpnConnectionRouteRequest(*ec2.DeleteVpnConnectionRouteInput) (*request.Request, *ec2.DeleteVpnConnectionRouteOutput) + + DeleteVpnConnectionRoute(*ec2.DeleteVpnConnectionRouteInput) (*ec2.DeleteVpnConnectionRouteOutput, error) + + DeleteVpnGatewayRequest(*ec2.DeleteVpnGatewayInput) (*request.Request, *ec2.DeleteVpnGatewayOutput) + + DeleteVpnGateway(*ec2.DeleteVpnGatewayInput) (*ec2.DeleteVpnGatewayOutput, error) + + DeregisterImageRequest(*ec2.DeregisterImageInput) (*request.Request, *ec2.DeregisterImageOutput) + + DeregisterImage(*ec2.DeregisterImageInput) (*ec2.DeregisterImageOutput, error) + + DescribeAccountAttributesRequest(*ec2.DescribeAccountAttributesInput) (*request.Request, *ec2.DescribeAccountAttributesOutput) + + DescribeAccountAttributes(*ec2.DescribeAccountAttributesInput) (*ec2.DescribeAccountAttributesOutput, error) + + DescribeAddressesRequest(*ec2.DescribeAddressesInput) (*request.Request, *ec2.DescribeAddressesOutput) + + DescribeAddresses(*ec2.DescribeAddressesInput) (*ec2.DescribeAddressesOutput, error) + + DescribeAvailabilityZonesRequest(*ec2.DescribeAvailabilityZonesInput) (*request.Request, *ec2.DescribeAvailabilityZonesOutput) + + DescribeAvailabilityZones(*ec2.DescribeAvailabilityZonesInput) (*ec2.DescribeAvailabilityZonesOutput, error) + + DescribeBundleTasksRequest(*ec2.DescribeBundleTasksInput) (*request.Request, *ec2.DescribeBundleTasksOutput) + + DescribeBundleTasks(*ec2.DescribeBundleTasksInput) (*ec2.DescribeBundleTasksOutput, error) + + DescribeClassicLinkInstancesRequest(*ec2.DescribeClassicLinkInstancesInput) (*request.Request, *ec2.DescribeClassicLinkInstancesOutput) + + DescribeClassicLinkInstances(*ec2.DescribeClassicLinkInstancesInput) (*ec2.DescribeClassicLinkInstancesOutput, error) + + DescribeConversionTasksRequest(*ec2.DescribeConversionTasksInput) (*request.Request, *ec2.DescribeConversionTasksOutput) + + DescribeConversionTasks(*ec2.DescribeConversionTasksInput) (*ec2.DescribeConversionTasksOutput, error) + + DescribeCustomerGatewaysRequest(*ec2.DescribeCustomerGatewaysInput) (*request.Request, *ec2.DescribeCustomerGatewaysOutput) + + DescribeCustomerGateways(*ec2.DescribeCustomerGatewaysInput) (*ec2.DescribeCustomerGatewaysOutput, error) + + DescribeDhcpOptionsRequest(*ec2.DescribeDhcpOptionsInput) (*request.Request, *ec2.DescribeDhcpOptionsOutput) + + DescribeDhcpOptions(*ec2.DescribeDhcpOptionsInput) (*ec2.DescribeDhcpOptionsOutput, error) + + DescribeExportTasksRequest(*ec2.DescribeExportTasksInput) (*request.Request, *ec2.DescribeExportTasksOutput) + + DescribeExportTasks(*ec2.DescribeExportTasksInput) (*ec2.DescribeExportTasksOutput, error) + + DescribeFlowLogsRequest(*ec2.DescribeFlowLogsInput) (*request.Request, *ec2.DescribeFlowLogsOutput) + + DescribeFlowLogs(*ec2.DescribeFlowLogsInput) (*ec2.DescribeFlowLogsOutput, error) + + DescribeHostsRequest(*ec2.DescribeHostsInput) (*request.Request, *ec2.DescribeHostsOutput) + + DescribeHosts(*ec2.DescribeHostsInput) (*ec2.DescribeHostsOutput, error) + + DescribeIdFormatRequest(*ec2.DescribeIdFormatInput) (*request.Request, *ec2.DescribeIdFormatOutput) + + DescribeIdFormat(*ec2.DescribeIdFormatInput) (*ec2.DescribeIdFormatOutput, error) + + DescribeImageAttributeRequest(*ec2.DescribeImageAttributeInput) (*request.Request, *ec2.DescribeImageAttributeOutput) + + DescribeImageAttribute(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) + + DescribeImagesRequest(*ec2.DescribeImagesInput) (*request.Request, *ec2.DescribeImagesOutput) + + DescribeImages(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) + + DescribeImportImageTasksRequest(*ec2.DescribeImportImageTasksInput) (*request.Request, *ec2.DescribeImportImageTasksOutput) + + DescribeImportImageTasks(*ec2.DescribeImportImageTasksInput) (*ec2.DescribeImportImageTasksOutput, error) + + DescribeImportSnapshotTasksRequest(*ec2.DescribeImportSnapshotTasksInput) (*request.Request, *ec2.DescribeImportSnapshotTasksOutput) + + DescribeImportSnapshotTasks(*ec2.DescribeImportSnapshotTasksInput) (*ec2.DescribeImportSnapshotTasksOutput, error) + + DescribeInstanceAttributeRequest(*ec2.DescribeInstanceAttributeInput) (*request.Request, *ec2.DescribeInstanceAttributeOutput) + + DescribeInstanceAttribute(*ec2.DescribeInstanceAttributeInput) (*ec2.DescribeInstanceAttributeOutput, error) + + DescribeInstanceStatusRequest(*ec2.DescribeInstanceStatusInput) (*request.Request, *ec2.DescribeInstanceStatusOutput) + + DescribeInstanceStatus(*ec2.DescribeInstanceStatusInput) (*ec2.DescribeInstanceStatusOutput, error) + + DescribeInstanceStatusPages(*ec2.DescribeInstanceStatusInput, func(*ec2.DescribeInstanceStatusOutput, bool) bool) error + + DescribeInstancesRequest(*ec2.DescribeInstancesInput) (*request.Request, *ec2.DescribeInstancesOutput) + + DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) + + DescribeInstancesPages(*ec2.DescribeInstancesInput, func(*ec2.DescribeInstancesOutput, bool) bool) error + + DescribeInternetGatewaysRequest(*ec2.DescribeInternetGatewaysInput) (*request.Request, *ec2.DescribeInternetGatewaysOutput) + + DescribeInternetGateways(*ec2.DescribeInternetGatewaysInput) (*ec2.DescribeInternetGatewaysOutput, error) + + DescribeKeyPairsRequest(*ec2.DescribeKeyPairsInput) (*request.Request, *ec2.DescribeKeyPairsOutput) + + DescribeKeyPairs(*ec2.DescribeKeyPairsInput) (*ec2.DescribeKeyPairsOutput, error) + + DescribeMovingAddressesRequest(*ec2.DescribeMovingAddressesInput) (*request.Request, *ec2.DescribeMovingAddressesOutput) + + DescribeMovingAddresses(*ec2.DescribeMovingAddressesInput) (*ec2.DescribeMovingAddressesOutput, error) + + DescribeNatGatewaysRequest(*ec2.DescribeNatGatewaysInput) (*request.Request, *ec2.DescribeNatGatewaysOutput) + + DescribeNatGateways(*ec2.DescribeNatGatewaysInput) (*ec2.DescribeNatGatewaysOutput, error) + + DescribeNetworkAclsRequest(*ec2.DescribeNetworkAclsInput) (*request.Request, *ec2.DescribeNetworkAclsOutput) + + DescribeNetworkAcls(*ec2.DescribeNetworkAclsInput) (*ec2.DescribeNetworkAclsOutput, error) + + DescribeNetworkInterfaceAttributeRequest(*ec2.DescribeNetworkInterfaceAttributeInput) (*request.Request, *ec2.DescribeNetworkInterfaceAttributeOutput) + + DescribeNetworkInterfaceAttribute(*ec2.DescribeNetworkInterfaceAttributeInput) (*ec2.DescribeNetworkInterfaceAttributeOutput, error) + + DescribeNetworkInterfacesRequest(*ec2.DescribeNetworkInterfacesInput) (*request.Request, *ec2.DescribeNetworkInterfacesOutput) + + DescribeNetworkInterfaces(*ec2.DescribeNetworkInterfacesInput) (*ec2.DescribeNetworkInterfacesOutput, error) + + DescribePlacementGroupsRequest(*ec2.DescribePlacementGroupsInput) (*request.Request, *ec2.DescribePlacementGroupsOutput) + + DescribePlacementGroups(*ec2.DescribePlacementGroupsInput) (*ec2.DescribePlacementGroupsOutput, error) + + DescribePrefixListsRequest(*ec2.DescribePrefixListsInput) (*request.Request, *ec2.DescribePrefixListsOutput) + + DescribePrefixLists(*ec2.DescribePrefixListsInput) (*ec2.DescribePrefixListsOutput, error) + + DescribeRegionsRequest(*ec2.DescribeRegionsInput) (*request.Request, *ec2.DescribeRegionsOutput) + + DescribeRegions(*ec2.DescribeRegionsInput) (*ec2.DescribeRegionsOutput, error) + + DescribeReservedInstancesRequest(*ec2.DescribeReservedInstancesInput) (*request.Request, *ec2.DescribeReservedInstancesOutput) + + DescribeReservedInstances(*ec2.DescribeReservedInstancesInput) (*ec2.DescribeReservedInstancesOutput, error) + + DescribeReservedInstancesListingsRequest(*ec2.DescribeReservedInstancesListingsInput) (*request.Request, *ec2.DescribeReservedInstancesListingsOutput) + + DescribeReservedInstancesListings(*ec2.DescribeReservedInstancesListingsInput) (*ec2.DescribeReservedInstancesListingsOutput, error) + + DescribeReservedInstancesModificationsRequest(*ec2.DescribeReservedInstancesModificationsInput) (*request.Request, *ec2.DescribeReservedInstancesModificationsOutput) + + DescribeReservedInstancesModifications(*ec2.DescribeReservedInstancesModificationsInput) (*ec2.DescribeReservedInstancesModificationsOutput, error) + + DescribeReservedInstancesModificationsPages(*ec2.DescribeReservedInstancesModificationsInput, func(*ec2.DescribeReservedInstancesModificationsOutput, bool) bool) error + + DescribeReservedInstancesOfferingsRequest(*ec2.DescribeReservedInstancesOfferingsInput) (*request.Request, *ec2.DescribeReservedInstancesOfferingsOutput) + + DescribeReservedInstancesOfferings(*ec2.DescribeReservedInstancesOfferingsInput) (*ec2.DescribeReservedInstancesOfferingsOutput, error) + + DescribeReservedInstancesOfferingsPages(*ec2.DescribeReservedInstancesOfferingsInput, func(*ec2.DescribeReservedInstancesOfferingsOutput, bool) bool) error + + DescribeRouteTablesRequest(*ec2.DescribeRouteTablesInput) (*request.Request, *ec2.DescribeRouteTablesOutput) + + DescribeRouteTables(*ec2.DescribeRouteTablesInput) (*ec2.DescribeRouteTablesOutput, error) + + DescribeScheduledInstanceAvailabilityRequest(*ec2.DescribeScheduledInstanceAvailabilityInput) (*request.Request, *ec2.DescribeScheduledInstanceAvailabilityOutput) + + DescribeScheduledInstanceAvailability(*ec2.DescribeScheduledInstanceAvailabilityInput) (*ec2.DescribeScheduledInstanceAvailabilityOutput, error) + + DescribeScheduledInstancesRequest(*ec2.DescribeScheduledInstancesInput) (*request.Request, *ec2.DescribeScheduledInstancesOutput) + + DescribeScheduledInstances(*ec2.DescribeScheduledInstancesInput) (*ec2.DescribeScheduledInstancesOutput, error) + + DescribeSecurityGroupsRequest(*ec2.DescribeSecurityGroupsInput) (*request.Request, *ec2.DescribeSecurityGroupsOutput) + + DescribeSecurityGroups(*ec2.DescribeSecurityGroupsInput) (*ec2.DescribeSecurityGroupsOutput, error) + + DescribeSnapshotAttributeRequest(*ec2.DescribeSnapshotAttributeInput) (*request.Request, *ec2.DescribeSnapshotAttributeOutput) + + DescribeSnapshotAttribute(*ec2.DescribeSnapshotAttributeInput) (*ec2.DescribeSnapshotAttributeOutput, error) + + DescribeSnapshotsRequest(*ec2.DescribeSnapshotsInput) (*request.Request, *ec2.DescribeSnapshotsOutput) + + DescribeSnapshots(*ec2.DescribeSnapshotsInput) (*ec2.DescribeSnapshotsOutput, error) + + DescribeSnapshotsPages(*ec2.DescribeSnapshotsInput, func(*ec2.DescribeSnapshotsOutput, bool) bool) error + + DescribeSpotDatafeedSubscriptionRequest(*ec2.DescribeSpotDatafeedSubscriptionInput) (*request.Request, *ec2.DescribeSpotDatafeedSubscriptionOutput) + + DescribeSpotDatafeedSubscription(*ec2.DescribeSpotDatafeedSubscriptionInput) (*ec2.DescribeSpotDatafeedSubscriptionOutput, error) + + DescribeSpotFleetInstancesRequest(*ec2.DescribeSpotFleetInstancesInput) (*request.Request, *ec2.DescribeSpotFleetInstancesOutput) + + DescribeSpotFleetInstances(*ec2.DescribeSpotFleetInstancesInput) (*ec2.DescribeSpotFleetInstancesOutput, error) + + DescribeSpotFleetRequestHistoryRequest(*ec2.DescribeSpotFleetRequestHistoryInput) (*request.Request, *ec2.DescribeSpotFleetRequestHistoryOutput) + + DescribeSpotFleetRequestHistory(*ec2.DescribeSpotFleetRequestHistoryInput) (*ec2.DescribeSpotFleetRequestHistoryOutput, error) + + DescribeSpotFleetRequestsRequest(*ec2.DescribeSpotFleetRequestsInput) (*request.Request, *ec2.DescribeSpotFleetRequestsOutput) + + DescribeSpotFleetRequests(*ec2.DescribeSpotFleetRequestsInput) (*ec2.DescribeSpotFleetRequestsOutput, error) + + DescribeSpotInstanceRequestsRequest(*ec2.DescribeSpotInstanceRequestsInput) (*request.Request, *ec2.DescribeSpotInstanceRequestsOutput) + + DescribeSpotInstanceRequests(*ec2.DescribeSpotInstanceRequestsInput) (*ec2.DescribeSpotInstanceRequestsOutput, error) + + DescribeSpotPriceHistoryRequest(*ec2.DescribeSpotPriceHistoryInput) (*request.Request, *ec2.DescribeSpotPriceHistoryOutput) + + DescribeSpotPriceHistory(*ec2.DescribeSpotPriceHistoryInput) (*ec2.DescribeSpotPriceHistoryOutput, error) + + DescribeSpotPriceHistoryPages(*ec2.DescribeSpotPriceHistoryInput, func(*ec2.DescribeSpotPriceHistoryOutput, bool) bool) error + + DescribeSubnetsRequest(*ec2.DescribeSubnetsInput) (*request.Request, *ec2.DescribeSubnetsOutput) + + DescribeSubnets(*ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) + + DescribeTagsRequest(*ec2.DescribeTagsInput) (*request.Request, *ec2.DescribeTagsOutput) + + DescribeTags(*ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error) + + DescribeTagsPages(*ec2.DescribeTagsInput, func(*ec2.DescribeTagsOutput, bool) bool) error + + DescribeVolumeAttributeRequest(*ec2.DescribeVolumeAttributeInput) (*request.Request, *ec2.DescribeVolumeAttributeOutput) + + DescribeVolumeAttribute(*ec2.DescribeVolumeAttributeInput) (*ec2.DescribeVolumeAttributeOutput, error) + + DescribeVolumeStatusRequest(*ec2.DescribeVolumeStatusInput) (*request.Request, *ec2.DescribeVolumeStatusOutput) + + DescribeVolumeStatus(*ec2.DescribeVolumeStatusInput) (*ec2.DescribeVolumeStatusOutput, error) + + DescribeVolumeStatusPages(*ec2.DescribeVolumeStatusInput, func(*ec2.DescribeVolumeStatusOutput, bool) bool) error + + DescribeVolumesRequest(*ec2.DescribeVolumesInput) (*request.Request, *ec2.DescribeVolumesOutput) + + DescribeVolumes(*ec2.DescribeVolumesInput) (*ec2.DescribeVolumesOutput, error) + + DescribeVolumesPages(*ec2.DescribeVolumesInput, func(*ec2.DescribeVolumesOutput, bool) bool) error + + DescribeVpcAttributeRequest(*ec2.DescribeVpcAttributeInput) (*request.Request, *ec2.DescribeVpcAttributeOutput) + + DescribeVpcAttribute(*ec2.DescribeVpcAttributeInput) (*ec2.DescribeVpcAttributeOutput, error) + + DescribeVpcClassicLinkRequest(*ec2.DescribeVpcClassicLinkInput) (*request.Request, *ec2.DescribeVpcClassicLinkOutput) + + DescribeVpcClassicLink(*ec2.DescribeVpcClassicLinkInput) (*ec2.DescribeVpcClassicLinkOutput, error) + + DescribeVpcClassicLinkDnsSupportRequest(*ec2.DescribeVpcClassicLinkDnsSupportInput) (*request.Request, *ec2.DescribeVpcClassicLinkDnsSupportOutput) + + DescribeVpcClassicLinkDnsSupport(*ec2.DescribeVpcClassicLinkDnsSupportInput) (*ec2.DescribeVpcClassicLinkDnsSupportOutput, error) + + DescribeVpcEndpointServicesRequest(*ec2.DescribeVpcEndpointServicesInput) (*request.Request, *ec2.DescribeVpcEndpointServicesOutput) + + DescribeVpcEndpointServices(*ec2.DescribeVpcEndpointServicesInput) (*ec2.DescribeVpcEndpointServicesOutput, error) + + DescribeVpcEndpointsRequest(*ec2.DescribeVpcEndpointsInput) (*request.Request, *ec2.DescribeVpcEndpointsOutput) + + DescribeVpcEndpoints(*ec2.DescribeVpcEndpointsInput) (*ec2.DescribeVpcEndpointsOutput, error) + + DescribeVpcPeeringConnectionsRequest(*ec2.DescribeVpcPeeringConnectionsInput) (*request.Request, *ec2.DescribeVpcPeeringConnectionsOutput) + + DescribeVpcPeeringConnections(*ec2.DescribeVpcPeeringConnectionsInput) (*ec2.DescribeVpcPeeringConnectionsOutput, error) + + DescribeVpcsRequest(*ec2.DescribeVpcsInput) (*request.Request, *ec2.DescribeVpcsOutput) + + DescribeVpcs(*ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) + + DescribeVpnConnectionsRequest(*ec2.DescribeVpnConnectionsInput) (*request.Request, *ec2.DescribeVpnConnectionsOutput) + + DescribeVpnConnections(*ec2.DescribeVpnConnectionsInput) (*ec2.DescribeVpnConnectionsOutput, error) + + DescribeVpnGatewaysRequest(*ec2.DescribeVpnGatewaysInput) (*request.Request, *ec2.DescribeVpnGatewaysOutput) + + DescribeVpnGateways(*ec2.DescribeVpnGatewaysInput) (*ec2.DescribeVpnGatewaysOutput, error) + + DetachClassicLinkVpcRequest(*ec2.DetachClassicLinkVpcInput) (*request.Request, *ec2.DetachClassicLinkVpcOutput) + + DetachClassicLinkVpc(*ec2.DetachClassicLinkVpcInput) (*ec2.DetachClassicLinkVpcOutput, error) + + DetachInternetGatewayRequest(*ec2.DetachInternetGatewayInput) (*request.Request, *ec2.DetachInternetGatewayOutput) + + DetachInternetGateway(*ec2.DetachInternetGatewayInput) (*ec2.DetachInternetGatewayOutput, error) + + DetachNetworkInterfaceRequest(*ec2.DetachNetworkInterfaceInput) (*request.Request, *ec2.DetachNetworkInterfaceOutput) + + DetachNetworkInterface(*ec2.DetachNetworkInterfaceInput) (*ec2.DetachNetworkInterfaceOutput, error) + + DetachVolumeRequest(*ec2.DetachVolumeInput) (*request.Request, *ec2.VolumeAttachment) + + DetachVolume(*ec2.DetachVolumeInput) (*ec2.VolumeAttachment, error) + + DetachVpnGatewayRequest(*ec2.DetachVpnGatewayInput) (*request.Request, *ec2.DetachVpnGatewayOutput) + + DetachVpnGateway(*ec2.DetachVpnGatewayInput) (*ec2.DetachVpnGatewayOutput, error) + + DisableVgwRoutePropagationRequest(*ec2.DisableVgwRoutePropagationInput) (*request.Request, *ec2.DisableVgwRoutePropagationOutput) + + DisableVgwRoutePropagation(*ec2.DisableVgwRoutePropagationInput) (*ec2.DisableVgwRoutePropagationOutput, error) + + DisableVpcClassicLinkRequest(*ec2.DisableVpcClassicLinkInput) (*request.Request, *ec2.DisableVpcClassicLinkOutput) + + DisableVpcClassicLink(*ec2.DisableVpcClassicLinkInput) (*ec2.DisableVpcClassicLinkOutput, error) + + DisableVpcClassicLinkDnsSupportRequest(*ec2.DisableVpcClassicLinkDnsSupportInput) (*request.Request, *ec2.DisableVpcClassicLinkDnsSupportOutput) + + DisableVpcClassicLinkDnsSupport(*ec2.DisableVpcClassicLinkDnsSupportInput) (*ec2.DisableVpcClassicLinkDnsSupportOutput, error) + + DisassociateAddressRequest(*ec2.DisassociateAddressInput) (*request.Request, *ec2.DisassociateAddressOutput) + + DisassociateAddress(*ec2.DisassociateAddressInput) (*ec2.DisassociateAddressOutput, error) + + DisassociateRouteTableRequest(*ec2.DisassociateRouteTableInput) (*request.Request, *ec2.DisassociateRouteTableOutput) + + DisassociateRouteTable(*ec2.DisassociateRouteTableInput) (*ec2.DisassociateRouteTableOutput, error) + + EnableVgwRoutePropagationRequest(*ec2.EnableVgwRoutePropagationInput) (*request.Request, *ec2.EnableVgwRoutePropagationOutput) + + EnableVgwRoutePropagation(*ec2.EnableVgwRoutePropagationInput) (*ec2.EnableVgwRoutePropagationOutput, error) + + EnableVolumeIORequest(*ec2.EnableVolumeIOInput) (*request.Request, *ec2.EnableVolumeIOOutput) + + EnableVolumeIO(*ec2.EnableVolumeIOInput) (*ec2.EnableVolumeIOOutput, error) + + EnableVpcClassicLinkRequest(*ec2.EnableVpcClassicLinkInput) (*request.Request, *ec2.EnableVpcClassicLinkOutput) + + EnableVpcClassicLink(*ec2.EnableVpcClassicLinkInput) (*ec2.EnableVpcClassicLinkOutput, error) + + EnableVpcClassicLinkDnsSupportRequest(*ec2.EnableVpcClassicLinkDnsSupportInput) (*request.Request, *ec2.EnableVpcClassicLinkDnsSupportOutput) + + EnableVpcClassicLinkDnsSupport(*ec2.EnableVpcClassicLinkDnsSupportInput) (*ec2.EnableVpcClassicLinkDnsSupportOutput, error) + + GetConsoleOutputRequest(*ec2.GetConsoleOutputInput) (*request.Request, *ec2.GetConsoleOutputOutput) + + GetConsoleOutput(*ec2.GetConsoleOutputInput) (*ec2.GetConsoleOutputOutput, error) + + GetPasswordDataRequest(*ec2.GetPasswordDataInput) (*request.Request, *ec2.GetPasswordDataOutput) + + GetPasswordData(*ec2.GetPasswordDataInput) (*ec2.GetPasswordDataOutput, error) + + ImportImageRequest(*ec2.ImportImageInput) (*request.Request, *ec2.ImportImageOutput) + + ImportImage(*ec2.ImportImageInput) (*ec2.ImportImageOutput, error) + + ImportInstanceRequest(*ec2.ImportInstanceInput) (*request.Request, *ec2.ImportInstanceOutput) + + ImportInstance(*ec2.ImportInstanceInput) (*ec2.ImportInstanceOutput, error) + + ImportKeyPairRequest(*ec2.ImportKeyPairInput) (*request.Request, *ec2.ImportKeyPairOutput) + + ImportKeyPair(*ec2.ImportKeyPairInput) (*ec2.ImportKeyPairOutput, error) + + ImportSnapshotRequest(*ec2.ImportSnapshotInput) (*request.Request, *ec2.ImportSnapshotOutput) + + ImportSnapshot(*ec2.ImportSnapshotInput) (*ec2.ImportSnapshotOutput, error) + + ImportVolumeRequest(*ec2.ImportVolumeInput) (*request.Request, *ec2.ImportVolumeOutput) + + ImportVolume(*ec2.ImportVolumeInput) (*ec2.ImportVolumeOutput, error) + + ModifyHostsRequest(*ec2.ModifyHostsInput) (*request.Request, *ec2.ModifyHostsOutput) + + ModifyHosts(*ec2.ModifyHostsInput) (*ec2.ModifyHostsOutput, error) + + ModifyIdFormatRequest(*ec2.ModifyIdFormatInput) (*request.Request, *ec2.ModifyIdFormatOutput) + + ModifyIdFormat(*ec2.ModifyIdFormatInput) (*ec2.ModifyIdFormatOutput, error) + + ModifyImageAttributeRequest(*ec2.ModifyImageAttributeInput) (*request.Request, *ec2.ModifyImageAttributeOutput) + + ModifyImageAttribute(*ec2.ModifyImageAttributeInput) (*ec2.ModifyImageAttributeOutput, error) + + ModifyInstanceAttributeRequest(*ec2.ModifyInstanceAttributeInput) (*request.Request, *ec2.ModifyInstanceAttributeOutput) + + ModifyInstanceAttribute(*ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error) + + ModifyInstancePlacementRequest(*ec2.ModifyInstancePlacementInput) (*request.Request, *ec2.ModifyInstancePlacementOutput) + + ModifyInstancePlacement(*ec2.ModifyInstancePlacementInput) (*ec2.ModifyInstancePlacementOutput, error) + + ModifyNetworkInterfaceAttributeRequest(*ec2.ModifyNetworkInterfaceAttributeInput) (*request.Request, *ec2.ModifyNetworkInterfaceAttributeOutput) + + ModifyNetworkInterfaceAttribute(*ec2.ModifyNetworkInterfaceAttributeInput) (*ec2.ModifyNetworkInterfaceAttributeOutput, error) + + ModifyReservedInstancesRequest(*ec2.ModifyReservedInstancesInput) (*request.Request, *ec2.ModifyReservedInstancesOutput) + + ModifyReservedInstances(*ec2.ModifyReservedInstancesInput) (*ec2.ModifyReservedInstancesOutput, error) + + ModifySnapshotAttributeRequest(*ec2.ModifySnapshotAttributeInput) (*request.Request, *ec2.ModifySnapshotAttributeOutput) + + ModifySnapshotAttribute(*ec2.ModifySnapshotAttributeInput) (*ec2.ModifySnapshotAttributeOutput, error) + + ModifySpotFleetRequestRequest(*ec2.ModifySpotFleetRequestInput) (*request.Request, *ec2.ModifySpotFleetRequestOutput) + + ModifySpotFleetRequest(*ec2.ModifySpotFleetRequestInput) (*ec2.ModifySpotFleetRequestOutput, error) + + ModifySubnetAttributeRequest(*ec2.ModifySubnetAttributeInput) (*request.Request, *ec2.ModifySubnetAttributeOutput) + + ModifySubnetAttribute(*ec2.ModifySubnetAttributeInput) (*ec2.ModifySubnetAttributeOutput, error) + + ModifyVolumeAttributeRequest(*ec2.ModifyVolumeAttributeInput) (*request.Request, *ec2.ModifyVolumeAttributeOutput) + + ModifyVolumeAttribute(*ec2.ModifyVolumeAttributeInput) (*ec2.ModifyVolumeAttributeOutput, error) + + ModifyVpcAttributeRequest(*ec2.ModifyVpcAttributeInput) (*request.Request, *ec2.ModifyVpcAttributeOutput) + + ModifyVpcAttribute(*ec2.ModifyVpcAttributeInput) (*ec2.ModifyVpcAttributeOutput, error) + + ModifyVpcEndpointRequest(*ec2.ModifyVpcEndpointInput) (*request.Request, *ec2.ModifyVpcEndpointOutput) + + ModifyVpcEndpoint(*ec2.ModifyVpcEndpointInput) (*ec2.ModifyVpcEndpointOutput, error) + + MonitorInstancesRequest(*ec2.MonitorInstancesInput) (*request.Request, *ec2.MonitorInstancesOutput) + + MonitorInstances(*ec2.MonitorInstancesInput) (*ec2.MonitorInstancesOutput, error) + + MoveAddressToVpcRequest(*ec2.MoveAddressToVpcInput) (*request.Request, *ec2.MoveAddressToVpcOutput) + + MoveAddressToVpc(*ec2.MoveAddressToVpcInput) (*ec2.MoveAddressToVpcOutput, error) + + PurchaseReservedInstancesOfferingRequest(*ec2.PurchaseReservedInstancesOfferingInput) (*request.Request, *ec2.PurchaseReservedInstancesOfferingOutput) + + PurchaseReservedInstancesOffering(*ec2.PurchaseReservedInstancesOfferingInput) (*ec2.PurchaseReservedInstancesOfferingOutput, error) + + PurchaseScheduledInstancesRequest(*ec2.PurchaseScheduledInstancesInput) (*request.Request, *ec2.PurchaseScheduledInstancesOutput) + + PurchaseScheduledInstances(*ec2.PurchaseScheduledInstancesInput) (*ec2.PurchaseScheduledInstancesOutput, error) + + RebootInstancesRequest(*ec2.RebootInstancesInput) (*request.Request, *ec2.RebootInstancesOutput) + + RebootInstances(*ec2.RebootInstancesInput) (*ec2.RebootInstancesOutput, error) + + RegisterImageRequest(*ec2.RegisterImageInput) (*request.Request, *ec2.RegisterImageOutput) + + RegisterImage(*ec2.RegisterImageInput) (*ec2.RegisterImageOutput, error) + + RejectVpcPeeringConnectionRequest(*ec2.RejectVpcPeeringConnectionInput) (*request.Request, *ec2.RejectVpcPeeringConnectionOutput) + + RejectVpcPeeringConnection(*ec2.RejectVpcPeeringConnectionInput) (*ec2.RejectVpcPeeringConnectionOutput, error) + + ReleaseAddressRequest(*ec2.ReleaseAddressInput) (*request.Request, *ec2.ReleaseAddressOutput) + + ReleaseAddress(*ec2.ReleaseAddressInput) (*ec2.ReleaseAddressOutput, error) + + ReleaseHostsRequest(*ec2.ReleaseHostsInput) (*request.Request, *ec2.ReleaseHostsOutput) + + ReleaseHosts(*ec2.ReleaseHostsInput) (*ec2.ReleaseHostsOutput, error) + + ReplaceNetworkAclAssociationRequest(*ec2.ReplaceNetworkAclAssociationInput) (*request.Request, *ec2.ReplaceNetworkAclAssociationOutput) + + ReplaceNetworkAclAssociation(*ec2.ReplaceNetworkAclAssociationInput) (*ec2.ReplaceNetworkAclAssociationOutput, error) + + ReplaceNetworkAclEntryRequest(*ec2.ReplaceNetworkAclEntryInput) (*request.Request, *ec2.ReplaceNetworkAclEntryOutput) + + ReplaceNetworkAclEntry(*ec2.ReplaceNetworkAclEntryInput) (*ec2.ReplaceNetworkAclEntryOutput, error) + + ReplaceRouteRequest(*ec2.ReplaceRouteInput) (*request.Request, *ec2.ReplaceRouteOutput) + + ReplaceRoute(*ec2.ReplaceRouteInput) (*ec2.ReplaceRouteOutput, error) + + ReplaceRouteTableAssociationRequest(*ec2.ReplaceRouteTableAssociationInput) (*request.Request, *ec2.ReplaceRouteTableAssociationOutput) + + ReplaceRouteTableAssociation(*ec2.ReplaceRouteTableAssociationInput) (*ec2.ReplaceRouteTableAssociationOutput, error) + + ReportInstanceStatusRequest(*ec2.ReportInstanceStatusInput) (*request.Request, *ec2.ReportInstanceStatusOutput) + + ReportInstanceStatus(*ec2.ReportInstanceStatusInput) (*ec2.ReportInstanceStatusOutput, error) + + RequestSpotFleetRequest(*ec2.RequestSpotFleetInput) (*request.Request, *ec2.RequestSpotFleetOutput) + + RequestSpotFleet(*ec2.RequestSpotFleetInput) (*ec2.RequestSpotFleetOutput, error) + + RequestSpotInstancesRequest(*ec2.RequestSpotInstancesInput) (*request.Request, *ec2.RequestSpotInstancesOutput) + + RequestSpotInstances(*ec2.RequestSpotInstancesInput) (*ec2.RequestSpotInstancesOutput, error) + + ResetImageAttributeRequest(*ec2.ResetImageAttributeInput) (*request.Request, *ec2.ResetImageAttributeOutput) + + ResetImageAttribute(*ec2.ResetImageAttributeInput) (*ec2.ResetImageAttributeOutput, error) + + ResetInstanceAttributeRequest(*ec2.ResetInstanceAttributeInput) (*request.Request, *ec2.ResetInstanceAttributeOutput) + + ResetInstanceAttribute(*ec2.ResetInstanceAttributeInput) (*ec2.ResetInstanceAttributeOutput, error) + + ResetNetworkInterfaceAttributeRequest(*ec2.ResetNetworkInterfaceAttributeInput) (*request.Request, *ec2.ResetNetworkInterfaceAttributeOutput) + + ResetNetworkInterfaceAttribute(*ec2.ResetNetworkInterfaceAttributeInput) (*ec2.ResetNetworkInterfaceAttributeOutput, error) + + ResetSnapshotAttributeRequest(*ec2.ResetSnapshotAttributeInput) (*request.Request, *ec2.ResetSnapshotAttributeOutput) + + ResetSnapshotAttribute(*ec2.ResetSnapshotAttributeInput) (*ec2.ResetSnapshotAttributeOutput, error) + + RestoreAddressToClassicRequest(*ec2.RestoreAddressToClassicInput) (*request.Request, *ec2.RestoreAddressToClassicOutput) + + RestoreAddressToClassic(*ec2.RestoreAddressToClassicInput) (*ec2.RestoreAddressToClassicOutput, error) + + RevokeSecurityGroupEgressRequest(*ec2.RevokeSecurityGroupEgressInput) (*request.Request, *ec2.RevokeSecurityGroupEgressOutput) + + RevokeSecurityGroupEgress(*ec2.RevokeSecurityGroupEgressInput) (*ec2.RevokeSecurityGroupEgressOutput, error) + + RevokeSecurityGroupIngressRequest(*ec2.RevokeSecurityGroupIngressInput) (*request.Request, *ec2.RevokeSecurityGroupIngressOutput) + + RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) + + RunInstancesRequest(*ec2.RunInstancesInput) (*request.Request, *ec2.Reservation) + + RunInstances(*ec2.RunInstancesInput) (*ec2.Reservation, error) + + RunScheduledInstancesRequest(*ec2.RunScheduledInstancesInput) (*request.Request, *ec2.RunScheduledInstancesOutput) + + RunScheduledInstances(*ec2.RunScheduledInstancesInput) (*ec2.RunScheduledInstancesOutput, error) + + StartInstancesRequest(*ec2.StartInstancesInput) (*request.Request, *ec2.StartInstancesOutput) + + StartInstances(*ec2.StartInstancesInput) (*ec2.StartInstancesOutput, error) + + StopInstancesRequest(*ec2.StopInstancesInput) (*request.Request, *ec2.StopInstancesOutput) + + StopInstances(*ec2.StopInstancesInput) (*ec2.StopInstancesOutput, error) + + TerminateInstancesRequest(*ec2.TerminateInstancesInput) (*request.Request, *ec2.TerminateInstancesOutput) + + TerminateInstances(*ec2.TerminateInstancesInput) (*ec2.TerminateInstancesOutput, error) + + UnassignPrivateIpAddressesRequest(*ec2.UnassignPrivateIpAddressesInput) (*request.Request, *ec2.UnassignPrivateIpAddressesOutput) + + UnassignPrivateIpAddresses(*ec2.UnassignPrivateIpAddressesInput) (*ec2.UnassignPrivateIpAddressesOutput, error) + + UnmonitorInstancesRequest(*ec2.UnmonitorInstancesInput) (*request.Request, *ec2.UnmonitorInstancesOutput) + + UnmonitorInstances(*ec2.UnmonitorInstancesInput) (*ec2.UnmonitorInstancesOutput, error) +} + +var _ EC2API = (*ec2.EC2)(nil) diff --git a/vendor/github.com/aws/aws-sdk-go/service/ec2/service.go b/vendor/github.com/aws/aws-sdk-go/service/ec2/service.go new file mode 100644 index 000000000..9d5fa8160 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/ec2/service.go @@ -0,0 +1,89 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package ec2 + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/ec2query" + "github.com/aws/aws-sdk-go/private/signer/v4" +) + +// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity +// in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your +// need to invest in hardware up front, so you can develop and deploy applications +// faster. +//The service client's operations are safe to be used concurrently. +// It is not safe to mutate any of the client's properties though. +type EC2 struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// A ServiceName is the name of the service the client will make API calls to. +const ServiceName = "ec2" + +// New creates a new instance of the EC2 client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a EC2 client from just a session. +// svc := ec2.New(mySession) +// +// // Create a EC2 client with additional configuration +// svc := ec2.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2 { + c := p.ClientConfig(ServiceName, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *EC2 { + svc := &EC2{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2015-10-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBack(v4.Sign) + svc.Handlers.Build.PushBackNamed(ec2query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(ec2query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(ec2query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(ec2query.UnmarshalErrorHandler) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a EC2 operation and runs any +// custom request initialization. +func (c *EC2) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/ec2/waiters.go b/vendor/github.com/aws/aws-sdk-go/service/ec2/waiters.go new file mode 100644 index 000000000..1b28317a1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/ec2/waiters.go @@ -0,0 +1,761 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package ec2 + +import ( + "github.com/aws/aws-sdk-go/private/waiter" +) + +func (c *EC2) WaitUntilBundleTaskComplete(input *DescribeBundleTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeBundleTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "BundleTasks[].State", + Expected: "complete", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "BundleTasks[].State", + Expected: "failed", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilConversionTaskCancelled(input *DescribeConversionTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeConversionTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "ConversionTasks[].State", + Expected: "cancelled", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilConversionTaskCompleted(input *DescribeConversionTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeConversionTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "ConversionTasks[].State", + Expected: "completed", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "ConversionTasks[].State", + Expected: "cancelled", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "ConversionTasks[].State", + Expected: "cancelling", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilConversionTaskDeleted(input *DescribeConversionTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeConversionTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "ConversionTasks[].State", + Expected: "deleted", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilCustomerGatewayAvailable(input *DescribeCustomerGatewaysInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeCustomerGateways", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "CustomerGateways[].State", + Expected: "available", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "CustomerGateways[].State", + Expected: "deleted", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "CustomerGateways[].State", + Expected: "deleting", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilExportTaskCancelled(input *DescribeExportTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeExportTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "ExportTasks[].State", + Expected: "cancelled", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilExportTaskCompleted(input *DescribeExportTasksInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeExportTasks", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "ExportTasks[].State", + Expected: "completed", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilImageAvailable(input *DescribeImagesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeImages", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Images[].State", + Expected: "available", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Images[].State", + Expected: "failed", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilInstanceExists(input *DescribeInstancesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstances", + Delay: 5, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "status", + Argument: "", + Expected: 200, + }, + { + State: "retry", + Matcher: "error", + Argument: "", + Expected: "InvalidInstanceIDNotFound", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilInstanceRunning(input *DescribeInstancesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstances", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Reservations[].Instances[].State.Name", + Expected: "running", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "shutting-down", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "terminated", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "stopping", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilInstanceStatusOk(input *DescribeInstanceStatusInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstanceStatus", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "InstanceStatuses[].InstanceStatus.Status", + Expected: "ok", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilInstanceStopped(input *DescribeInstancesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstances", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Reservations[].Instances[].State.Name", + Expected: "stopped", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "pending", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "terminated", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilInstanceTerminated(input *DescribeInstancesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstances", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Reservations[].Instances[].State.Name", + Expected: "terminated", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "pending", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Reservations[].Instances[].State.Name", + Expected: "stopping", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilKeyPairExists(input *DescribeKeyPairsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeKeyPairs", + Delay: 5, + MaxAttempts: 6, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "length(KeyPairs[].KeyName) > `0`", + Expected: true, + }, + { + State: "retry", + Matcher: "error", + Argument: "", + Expected: "InvalidKeyPairNotFound", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilNetworkInterfaceAvailable(input *DescribeNetworkInterfacesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeNetworkInterfaces", + Delay: 20, + MaxAttempts: 10, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "NetworkInterfaces[].Status", + Expected: "available", + }, + { + State: "failure", + Matcher: "error", + Argument: "", + Expected: "InvalidNetworkInterfaceIDNotFound", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilPasswordDataAvailable(input *GetPasswordDataInput) error { + waiterCfg := waiter.Config{ + Operation: "GetPasswordData", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "path", + Argument: "length(PasswordData) > `0`", + Expected: true, + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilSnapshotCompleted(input *DescribeSnapshotsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeSnapshots", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Snapshots[].State", + Expected: "completed", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilSpotInstanceRequestFulfilled(input *DescribeSpotInstanceRequestsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeSpotInstanceRequests", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "SpotInstanceRequests[].Status.Code", + Expected: "fulfilled", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "SpotInstanceRequests[].Status.Code", + Expected: "schedule-expired", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "SpotInstanceRequests[].Status.Code", + Expected: "canceled-before-fulfillment", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "SpotInstanceRequests[].Status.Code", + Expected: "bad-parameters", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "SpotInstanceRequests[].Status.Code", + Expected: "system-error", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilSubnetAvailable(input *DescribeSubnetsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeSubnets", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Subnets[].State", + Expected: "available", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilSystemStatusOk(input *DescribeInstanceStatusInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeInstanceStatus", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "InstanceStatuses[].SystemStatus.Status", + Expected: "ok", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVolumeAvailable(input *DescribeVolumesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVolumes", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Volumes[].State", + Expected: "available", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Volumes[].State", + Expected: "deleted", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVolumeDeleted(input *DescribeVolumesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVolumes", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Volumes[].State", + Expected: "deleted", + }, + { + State: "success", + Matcher: "error", + Argument: "", + Expected: "InvalidVolumeNotFound", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVolumeInUse(input *DescribeVolumesInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVolumes", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Volumes[].State", + Expected: "in-use", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "Volumes[].State", + Expected: "deleted", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVpcAvailable(input *DescribeVpcsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVpcs", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "Vpcs[].State", + Expected: "available", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVpnConnectionAvailable(input *DescribeVpnConnectionsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVpnConnections", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "VpnConnections[].State", + Expected: "available", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "VpnConnections[].State", + Expected: "deleting", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "VpnConnections[].State", + Expected: "deleted", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} + +func (c *EC2) WaitUntilVpnConnectionDeleted(input *DescribeVpnConnectionsInput) error { + waiterCfg := waiter.Config{ + Operation: "DescribeVpnConnections", + Delay: 15, + MaxAttempts: 40, + Acceptors: []waiter.WaitAcceptor{ + { + State: "success", + Matcher: "pathAll", + Argument: "VpnConnections[].State", + Expected: "deleted", + }, + { + State: "failure", + Matcher: "pathAny", + Argument: "VpnConnections[].State", + Expected: "pending", + }, + }, + } + + w := waiter.Waiter{ + Client: c, + Input: input, + Config: waiterCfg, + } + return w.Wait() +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/api.go b/vendor/github.com/aws/aws-sdk-go/service/sts/api.go new file mode 100644 index 000000000..a6c09f7c7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/api.go @@ -0,0 +1,1094 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package sts provides a client for AWS Security Token Service. +package sts + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" +) + +const opAssumeRole = "AssumeRole" + +// AssumeRoleRequest generates a request for the AssumeRole operation. +func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) { + op := &request.Operation{ + Name: opAssumeRole, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) that you can use to access +// AWS resources that you might not normally have access to. Typically, you +// use AssumeRole for cross-account access or federation. +// +// Important: You cannot call AssumeRole by using AWS account credentials; +// access will be denied. You must use IAM user credentials or temporary security +// credentials to call AssumeRole. +// +// For cross-account access, imagine that you own multiple accounts and need +// to access resources in each account. You could create long-term credentials +// in each account to access those resources. However, managing all those credentials +// and remembering which one can access which account can be time consuming. +// Instead, you can create one set of long-term credentials in one account and +// then use temporary security credentials to access all the other accounts +// by assuming roles in those accounts. For more information about roles, see +// IAM Roles (Delegation and Federation) (http://docs.aws.amazon.com/IAM/latest/UserGuide/roles-toplevel.html) +// in the Using IAM. +// +// For federation, you can, for example, grant single sign-on access to the +// AWS Management Console. If you already have an identity and authentication +// system in your corporate network, you don't have to recreate user identities +// in AWS in order to grant those user identities access to AWS. Instead, after +// a user has been authenticated, you call AssumeRole (and specify the role +// with the appropriate permissions) to get temporary security credentials for +// that user. With those temporary security credentials, you construct a sign-in +// URL that users can use to access the console. For more information, see Common +// Scenarios for Temporary Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html#sts-introduction) +// in the Using IAM. +// +// The temporary security credentials are valid for the duration that you specified +// when calling AssumeRole, which can be from 900 seconds (15 minutes) to 3600 +// seconds (1 hour). The default is 1 hour. +// +// Optionally, you can pass an IAM access policy to this operation. If you +// choose not to pass a policy, the temporary security credentials that are +// returned by the operation have the permissions that are defined in the access +// policy of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// To assume a role, your AWS account must be trusted by the role. The trust +// relationship is defined in the role's trust policy when the role is created. +// You must also have a policy that allows you to call sts:AssumeRole. +// +// Using MFA with AssumeRole +// +// You can optionally include multi-factor authentication (MFA) information +// when you call AssumeRole. This is useful for cross-account scenarios in which +// you want to make sure that the user who is assuming the role has been authenticated +// using an AWS MFA device. In that scenario, the trust policy of the role being +// assumed includes a condition that tests for MFA authentication; if the caller +// does not include valid MFA information, the request to assume the role is +// denied. The condition in a trust policy that tests for MFA authentication +// might look like the following example. +// +// "Condition": {"Bool": {"aws:MultiFactorAuthPresent": true}} +// +// For more information, see Configuring MFA-Protected API Access (http://docs.aws.amazon.com/IAM/latest/UserGuide/MFAProtectedAPI.html) +// in the Using IAM guide. +// +// To use MFA with AssumeRole, you pass values for the SerialNumber and TokenCode +// parameters. The SerialNumber value identifies the user's hardware or virtual +// MFA device. The TokenCode is the time-based one-time password (TOTP) that +// the MFA devices produces. +func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) { + req, out := c.AssumeRoleRequest(input) + err := req.Send() + return out, err +} + +const opAssumeRoleWithSAML = "AssumeRoleWithSAML" + +// AssumeRoleWithSAMLRequest generates a request for the AssumeRoleWithSAML operation. +func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithSAML, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithSAMLInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleWithSAMLOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials for users who have been authenticated +// via a SAML authentication response. This operation provides a mechanism for +// tying an enterprise identity store or directory to role-based AWS access +// without user-specific credentials or configuration. +// +// The temporary security credentials returned by this operation consist of +// an access key ID, a secret access key, and a security token. Applications +// can use these temporary security credentials to sign calls to AWS services. +// The credentials are valid for the duration that you specified when calling +// AssumeRoleWithSAML, which can be up to 3600 seconds (1 hour) or until the +// time specified in the SAML authentication response's SessionNotOnOrAfter +// value, whichever is shorter. +// +// The maximum duration for a session is 1 hour, and the minimum duration is +// 15 minutes, even if values outside this range are specified. Optionally, +// you can pass an IAM access policy to this operation. If you choose not to +// pass a policy, the temporary security credentials that are returned by the +// operation have the permissions that are defined in the access policy of the +// role that is being assumed. If you pass a policy to this operation, the temporary +// security credentials that are returned by the operation have the permissions +// that are allowed by both the access policy of the role that is being assumed, +// and the policy that you pass. This gives you a way to further restrict the +// permissions for the resulting temporary security credentials. You cannot +// use the passed policy to grant permissions that are in excess of those allowed +// by the access policy of the role that is being assumed. For more information, +// see Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// Before your application can call AssumeRoleWithSAML, you must configure +// your SAML identity provider (IdP) to issue the claims required by AWS. Additionally, +// you must use AWS Identity and Access Management (IAM) to create a SAML provider +// entity in your AWS account that represents your identity provider, and create +// an IAM role that specifies this SAML provider in its trust policy. +// +// Calling AssumeRoleWithSAML does not require the use of AWS security credentials. +// The identity of the caller is validated by using keys in the metadata document +// that is uploaded for the SAML provider entity for your identity provider. +// +// For more information, see the following resources: +// +// About SAML 2.0-based Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_saml.html) +// in the Using IAM. Creating SAML Identity Providers (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html) +// in the Using IAM. Configuring a Relying Party and Claims (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_relying-party.html) +// in the Using IAM. Creating a Role for SAML 2.0 Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_saml.html) +// in the Using IAM. +func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) { + req, out := c.AssumeRoleWithSAMLRequest(input) + err := req.Send() + return out, err +} + +const opAssumeRoleWithWebIdentity = "AssumeRoleWithWebIdentity" + +// AssumeRoleWithWebIdentityRequest generates a request for the AssumeRoleWithWebIdentity operation. +func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithWebIdentity, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithWebIdentityInput{} + } + + req = c.newRequest(op, input, output) + output = &AssumeRoleWithWebIdentityOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials for users who have been authenticated +// in a mobile or web application with a web identity provider, such as Amazon +// Cognito, Login with Amazon, Facebook, Google, or any OpenID Connect-compatible +// identity provider. +// +// For mobile applications, we recommend that you use Amazon Cognito. You +// can use Amazon Cognito with the AWS SDK for iOS (http://aws.amazon.com/sdkforios/) +// and the AWS SDK for Android (http://aws.amazon.com/sdkforandroid/) to uniquely +// identify a user and supply the user with a consistent identity throughout +// the lifetime of an application. +// +// To learn more about Amazon Cognito, see Amazon Cognito Overview (http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html#d0e840) +// in the AWS SDK for Android Developer Guide guide and Amazon Cognito Overview +// (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html#d0e664) +// in the AWS SDK for iOS Developer Guide. +// +// Calling AssumeRoleWithWebIdentity does not require the use of AWS security +// credentials. Therefore, you can distribute an application (for example, on +// mobile devices) that requests temporary security credentials without including +// long-term AWS credentials in the application, and without deploying server-based +// proxy services that use long-term AWS credentials. Instead, the identity +// of the caller is validated by using a token from the web identity provider. +// +// The temporary security credentials returned by this API consist of an access +// key ID, a secret access key, and a security token. Applications can use these +// temporary security credentials to sign calls to AWS service APIs. The credentials +// are valid for the duration that you specified when calling AssumeRoleWithWebIdentity, +// which can be from 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, +// the temporary security credentials are valid for 1 hour. +// +// Optionally, you can pass an IAM access policy to this operation. If you +// choose not to pass a policy, the temporary security credentials that are +// returned by the operation have the permissions that are defined in the access +// policy of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the Using IAM. +// +// Before your application can call AssumeRoleWithWebIdentity, you must have +// an identity token from a supported identity provider and create a role that +// the application can assume. The role that your application assumes must trust +// the identity provider that is associated with the identity token. In other +// words, the identity provider must be specified in the role's trust policy. +// +// For more information about how to use web identity federation and the AssumeRoleWithWebIdentity +// API, see the following resources: +// +// Using Web Identity Federation APIs for Mobile Apps (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual) +// and Federation Through a Web-based Identity Provider (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// Web Identity Federation Playground (https://web-identity-federation-playground.s3.amazonaws.com/index.html). +// This interactive website lets you walk through the process of authenticating +// via Login with Amazon, Facebook, or Google, getting temporary security credentials, +// and then using those credentials to make a request to AWS. AWS SDK for iOS +// (http://aws.amazon.com/sdkforios/) and AWS SDK for Android (http://aws.amazon.com/sdkforandroid/). +// These toolkits contain sample apps that show how to invoke the identity providers, +// and then how to use the information from these providers to get and use temporary +// security credentials. Web Identity Federation with Mobile Applications (http://aws.amazon.com/articles/4617974389850313). +// This article discusses web identity federation and shows an example of how +// to use web identity federation to get access to content in Amazon S3. +func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) { + req, out := c.AssumeRoleWithWebIdentityRequest(input) + err := req.Send() + return out, err +} + +const opDecodeAuthorizationMessage = "DecodeAuthorizationMessage" + +// DecodeAuthorizationMessageRequest generates a request for the DecodeAuthorizationMessage operation. +func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) { + op := &request.Operation{ + Name: opDecodeAuthorizationMessage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DecodeAuthorizationMessageInput{} + } + + req = c.newRequest(op, input, output) + output = &DecodeAuthorizationMessageOutput{} + req.Data = output + return +} + +// Decodes additional information about the authorization status of a request +// from an encoded message returned in response to an AWS request. +// +// For example, if a user is not authorized to perform an action that he or +// she has requested, the request returns a Client.UnauthorizedOperation response +// (an HTTP 403 response). Some AWS actions additionally return an encoded message +// that can provide details about this authorization failure. +// +// Only certain AWS actions return an encoded authorization message. The documentation +// for an individual action indicates whether that action returns an encoded +// message in addition to returning an HTTP code. The message is encoded because +// the details of the authorization status can constitute privileged information +// that the user who requested the action should not see. To decode an authorization +// status message, a user must be granted permissions via an IAM policy to request +// the DecodeAuthorizationMessage (sts:DecodeAuthorizationMessage) action. +// +// The decoded message includes the following type of information: +// +// Whether the request was denied due to an explicit deny or due to the absence +// of an explicit allow. For more information, see Determining Whether a Request +// is Allowed or Denied (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow) +// in the Using IAM. The principal who made the request. The requested action. +// The requested resource. The values of condition keys in the context of the +// user's request. +func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) { + req, out := c.DecodeAuthorizationMessageRequest(input) + err := req.Send() + return out, err +} + +const opGetFederationToken = "GetFederationToken" + +// GetFederationTokenRequest generates a request for the GetFederationToken operation. +func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) { + op := &request.Operation{ + Name: opGetFederationToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetFederationTokenInput{} + } + + req = c.newRequest(op, input, output) + output = &GetFederationTokenOutput{} + req.Data = output + return +} + +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) for a federated user. +// A typical use is in a proxy application that gets temporary security credentials +// on behalf of distributed applications inside a corporate network. Because +// you must call the GetFederationToken action using the long-term security +// credentials of an IAM user, this call is appropriate in contexts where those +// credentials can be safely stored, usually in a server-based application. +// +// If you are creating a mobile-based or browser-based app that can authenticate +// users using a web identity provider like Login with Amazon, Facebook, Google, +// or an OpenID Connect-compatible identity provider, we recommend that you +// use Amazon Cognito (http://aws.amazon.com/cognito/) or AssumeRoleWithWebIdentity. +// For more information, see Federation Through a Web-based Identity Provider +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// +// The GetFederationToken action must be called by using the long-term AWS +// security credentials of an IAM user. You can also call GetFederationToken +// using the security credentials of an AWS account (root), but this is not +// recommended. Instead, we recommend that you create an IAM user for the purpose +// of the proxy application and then attach a policy to the IAM user that limits +// federated users to only the actions and resources they need access to. For +// more information, see IAM Best Practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) +// in the Using IAM. +// +// The temporary security credentials that are obtained by using the long-term +// credentials of an IAM user are valid for the specified duration, between +// 900 seconds (15 minutes) and 129600 seconds (36 hours). Temporary credentials +// that are obtained by using AWS account (root) credentials have a maximum +// duration of 3600 seconds (1 hour) +// +// Permissions +// +// The permissions for the temporary security credentials returned by GetFederationToken +// are determined by a combination of the following: +// +// The policy or policies that are attached to the IAM user whose credentials +// are used to call GetFederationToken. The policy that is passed as a parameter +// in the call. The passed policy is attached to the temporary security credentials +// that result from the GetFederationToken API call--that is, to the federated +// user. When the federated user makes an AWS request, AWS evaluates the policy +// attached to the federated user in combination with the policy or policies +// attached to the IAM user whose credentials were used to call GetFederationToken. +// AWS allows the federated user's request only when both the federated user +// and the IAM user are explicitly allowed to perform the requested action. +// The passed policy cannot grant more permissions than those that are defined +// in the IAM user policy. +// +// A typical use case is that the permissions of the IAM user whose credentials +// are used to call GetFederationToken are designed to allow access to all the +// actions and resources that any federated user will need. Then, for individual +// users, you pass a policy to the operation that scopes down the permissions +// to a level that's appropriate to that individual user, using a policy that +// allows only a subset of permissions that are granted to the IAM user. +// +// If you do not pass a policy, the resulting temporary security credentials +// have no effective permissions. The only exception is when the temporary security +// credentials are used to access a resource that has a resource-based policy +// that specifically allows the federated user to access the resource. +// +// For more information about how permissions work, see Permissions for GetFederationToken +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). +// For information about using GetFederationToken to create temporary security +// credentials, see GetFederationToken—Federation Through a Custom Identity +// Broker (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getfederationtoken). +func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) { + req, out := c.GetFederationTokenRequest(input) + err := req.Send() + return out, err +} + +const opGetSessionToken = "GetSessionToken" + +// GetSessionTokenRequest generates a request for the GetSessionToken operation. +func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) { + op := &request.Operation{ + Name: opGetSessionToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetSessionTokenInput{} + } + + req = c.newRequest(op, input, output) + output = &GetSessionTokenOutput{} + req.Data = output + return +} + +// Returns a set of temporary credentials for an AWS account or IAM user. The +// credentials consist of an access key ID, a secret access key, and a security +// token. Typically, you use GetSessionToken if you want to use MFA to protect +// programmatic calls to specific AWS APIs like Amazon EC2 StopInstances. MFA-enabled +// IAM users would need to call GetSessionToken and submit an MFA code that +// is associated with their MFA device. Using the temporary security credentials +// that are returned from the call, IAM users can then make programmatic calls +// to APIs that require MFA authentication. If you do not supply a correct MFA +// code, then the API returns an access denied error. +// +// The GetSessionToken action must be called by using the long-term AWS security +// credentials of the AWS account or an IAM user. Credentials that are created +// by IAM users are valid for the duration that you specify, between 900 seconds +// (15 minutes) and 129600 seconds (36 hours); credentials that are created +// by using account credentials have a maximum duration of 3600 seconds (1 hour). +// +// We recommend that you do not call GetSessionToken with root account credentials. +// Instead, follow our best practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users) +// by creating one or more IAM users, giving them the necessary permissions, +// and using IAM users for everyday interaction with AWS. +// +// The permissions associated with the temporary security credentials returned +// by GetSessionToken are based on the permissions associated with account or +// IAM user whose credentials are used to call the action. If GetSessionToken +// is called using root account credentials, the temporary credentials have +// root account permissions. Similarly, if GetSessionToken is called using the +// credentials of an IAM user, the temporary credentials have the same permissions +// as the IAM user. +// +// For more information about using GetSessionToken to create temporary credentials, +// go to Temporary Credentials for Users in Untrusted Environments (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getsessiontoken) +// in the Using IAM. +func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) { + req, out := c.GetSessionTokenRequest(input) + err := req.Send() + return out, err +} + +type AssumeRoleInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + DurationSeconds *int64 `min:"900" type:"integer"` + + // A unique identifier that is used by third parties when assuming roles in + // their customers' accounts. For each role that the third party can assume, + // they should instruct their customers to ensure the role's trust policy checks + // for the external ID that the third party generated. Each time the third party + // assumes the role, they should pass the customer's external ID. The external + // ID is useful in order to help third parties bind a role to the customer who + // created it. For more information about the external ID, see How to Use an + // External ID When Granting Access to Your AWS Resources to a Third Party (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) + // in the Using IAM. + ExternalId *string `min:"2" type:"string"` + + // An IAM policy in JSON format. + // + // This parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both (the intersection of) the access policy of the role that + // is being assumed, and the policy that you pass. This gives you a way to further + // restrict the permissions for the resulting temporary security credentials. + // You cannot use the passed policy to grant permissions that are in excess + // of those allowed by the access policy of the role that is being assumed. + // For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, + // and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the role to assume. + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. + // + // Use the role session name to uniquely identify a session when the same role + // is assumed by different principals or for different reasons. In cross-account + // scenarios, the role session name is visible to, and can be logged by the + // account that owns the role. The role session name is also used in the ARN + // of the assumed role principal. This means that subsequent cross-account API + // requests using the temporary security credentials will expose the role session + // name to the external account in their CloudTrail logs. + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // The identification number of the MFA device that is associated with the user + // who is making the AssumeRole call. Specify this value if the trust policy + // of the role being assumed includes a condition that requires MFA authentication. + // The value is either the serial number for a hardware device (such as GAHT12345678) + // or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user). + SerialNumber *string `min:"9" type:"string"` + + // The value provided by the MFA device, if the trust policy of the role being + // assumed requires MFA (that is, if the policy includes a condition that tests + // for MFA). If the role being assumed requires MFA and if the TokenCode value + // is missing or expired, the AssumeRole call returns an "access denied" error. + TokenCode *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s AssumeRoleInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRole request, including temporary +// AWS credentials that can be used to make AWS requests. +type AssumeRoleOutput struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. + // We strongly recommend that you make no assumptions about the maximum size. + // As of this writing, the typical size is less than 4096 bytes, but that can + // vary. Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` +} + +// String returns the string representation +func (s AssumeRoleOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleOutput) GoString() string { + return s.String() +} + +type AssumeRoleWithSAMLInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. An expiration can also be specified in the SAML authentication + // response's SessionNotOnOrAfter value. The actual expiration time is whichever + // value is shorter. + // + // The maximum duration for a session is 1 hour, and the minimum duration is + // 15 minutes, even if values outside this range are specified. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the SAML provider in IAM that describes + // the IdP. + PrincipalArn *string `min:"20" type:"string" required:"true"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + RoleArn *string `min:"20" type:"string" required:"true"` + + // The base-64 encoded SAML authentication response provided by the IdP. + // + // For more information, see Configuring a Relying Party and Adding Claims + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/create-role-saml-IdP-tasks.html) + // in the Using IAM guide. + SAMLAssertion *string `min:"4" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRoleWithSAML request, including +// temporary AWS credentials that can be used to make AWS requests. +type AssumeRoleWithSAMLOutput struct { + _ struct{} `type:"structure"` + + // The identifiers for the temporary security credentials that the operation + // returns. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The value of the Recipient attribute of the SubjectConfirmationData element + // of the SAML assertion. + Audience *string `type:"string"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. + // We strongly recommend that you make no assumptions about the maximum size. + // As of this writing, the typical size is less than 4096 bytes, but that can + // vary. Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // The value of the Issuer element of the SAML assertion. + Issuer *string `type:"string"` + + // A hash value based on the concatenation of the Issuer response value, the + // AWS account ID, and the friendly name (the last part of the ARN) of the SAML + // provider in IAM. The combination of NameQualifier and Subject can be used + // to uniquely identify a federated user. + // + // The following pseudocode shows how the hash value is calculated: + // + // BASE64 ( SHA1 ( "https://example.com/saml" + "123456789012" + "/MySAMLIdP" + // ) ) + NameQualifier *string `type:"string"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The value of the NameID element in the Subject element of the SAML assertion. + Subject *string `type:"string"` + + // The format of the name ID, as defined by the Format attribute in the NameID + // element of the SAML assertion. Typical examples of the format are transient + // or persistent. + // + // If the format includes the prefix urn:oasis:names:tc:SAML:2.0:nameid-format, + // that prefix is removed. For example, urn:oasis:names:tc:SAML:2.0:nameid-format:transient + // is returned as transient. If the format includes any other prefix, the format + // is returned with no modifications. + SubjectType *string `type:"string"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLOutput) GoString() string { + return s.String() +} + +type AssumeRoleWithWebIdentityInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // see Permissions for AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the Using IAM. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. + Policy *string `min:"1" type:"string"` + + // The fully qualified host component of the domain name of the identity provider. + // + // Specify this value only for OAuth 2.0 access tokens. Currently www.amazon.com + // and graph.facebook.com are the only supported identity providers for OAuth + // 2.0 access tokens. Do not include URL schemes and port numbers. + // + // Do not specify this value for OpenID Connect ID tokens. + ProviderId *string `min:"4" type:"string"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. Typically, you pass the name + // or identifier that is associated with the user who is using your application. + // That way, the temporary security credentials that your application will use + // are associated with that user. This session name is included as part of the + // ARN and assumed role ID in the AssumedRoleUser response element. + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // The OAuth 2.0 access token or OpenID Connect ID token that is provided by + // the identity provider. Your application must get this token by authenticating + // the user who is using your application with a web identity provider before + // the application makes an AssumeRoleWithWebIdentity call. + WebIdentityToken *string `min:"4" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityInput) GoString() string { + return s.String() +} + +// Contains the response to a successful AssumeRoleWithWebIdentity request, +// including temporary AWS credentials that can be used to make AWS requests. +type AssumeRoleWithWebIdentityOutput struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The intended audience (also known as client ID) of the web identity token. + // This is traditionally the client identifier issued to the application that + // requested the web identity token. + Audience *string `type:"string"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security token. + // + // Note: The size of the security token that STS APIs return is not fixed. + // We strongly recommend that you make no assumptions about the maximum size. + // As of this writing, the typical size is less than 4096 bytes, but that can + // vary. Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The issuing authority of the web identity token presented. For OpenID Connect + // ID Tokens this contains the value of the iss field. For OAuth 2.0 access + // tokens, this contains the value of the ProviderId parameter that was passed + // in the AssumeRoleWithWebIdentity request. + Provider *string `type:"string"` + + // The unique user identifier that is returned by the identity provider. This + // identifier is associated with the WebIdentityToken that was submitted with + // the AssumeRoleWithWebIdentity call. The identifier is typically unique to + // the user and the application that acquired the WebIdentityToken (pairwise + // identifier). For OpenID Connect ID tokens, this field contains the value + // returned by the identity provider as the token's sub (Subject) claim. + SubjectFromWebIdentityToken *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityOutput) GoString() string { + return s.String() +} + +// The identifiers for the temporary security credentials that the operation +// returns. +type AssumedRoleUser struct { + _ struct{} `type:"structure"` + + // The ARN of the temporary security credentials that are returned from the + // AssumeRole action. For more information about ARNs and how to use them in + // policies, see IAM Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + Arn *string `min:"20" type:"string" required:"true"` + + // A unique identifier that contains the role ID and the role session name of + // the role that is being assumed. The role ID is generated by AWS when the + // role is created. + AssumedRoleId *string `min:"2" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumedRoleUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumedRoleUser) GoString() string { + return s.String() +} + +// AWS credentials for API authentication. +type Credentials struct { + _ struct{} `type:"structure"` + + // The access key ID that identifies the temporary security credentials. + AccessKeyId *string `min:"16" type:"string" required:"true"` + + // The date on which the current credentials expire. + Expiration *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // The secret access key that can be used to sign requests. + SecretAccessKey *string `type:"string" required:"true"` + + // The token that users must pass to the service API to use the temporary credentials. + SessionToken *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s Credentials) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Credentials) GoString() string { + return s.String() +} + +type DecodeAuthorizationMessageInput struct { + _ struct{} `type:"structure"` + + // The encoded message that was returned with the response. + EncodedMessage *string `min:"1" type:"string" required:"true"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageInput) GoString() string { + return s.String() +} + +// A document that contains additional information about the authorization status +// of a request from an encoded message that is returned in response to an AWS +// request. +type DecodeAuthorizationMessageOutput struct { + _ struct{} `type:"structure"` + + // An XML document that contains the decoded message. For more information, + // see DecodeAuthorizationMessage. + DecodedMessage *string `type:"string"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageOutput) GoString() string { + return s.String() +} + +// Identifiers for the federated user that is associated with the credentials. +type FederatedUser struct { + _ struct{} `type:"structure"` + + // The ARN that specifies the federated user that is associated with the credentials. + // For more information about ARNs and how to use them in policies, see IAM + // Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + Arn *string `min:"20" type:"string" required:"true"` + + // The string that identifies the federated user associated with the credentials, + // similar to the unique ID of an IAM user. + FederatedUserId *string `min:"2" type:"string" required:"true"` +} + +// String returns the string representation +func (s FederatedUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s FederatedUser) GoString() string { + return s.String() +} + +type GetFederationTokenInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, that the session should last. Acceptable durations + // for federation sessions range from 900 seconds (15 minutes) to 129600 seconds + // (36 hours), with 43200 seconds (12 hours) as the default. Sessions obtained + // using AWS account (root) credentials are restricted to a maximum of 3600 + // seconds (one hour). If the specified duration is longer than one hour, the + // session obtained by using AWS account (root) credentials defaults to one + // hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The name of the federated user. The name is used as an identifier for the + // temporary security credentials (such as Bob). For example, you can reference + // the federated user name in a resource-based policy, such as in an Amazon + // S3 bucket policy. + Name *string `min:"2" type:"string" required:"true"` + + // An IAM policy in JSON format that is passed with the GetFederationToken call + // and evaluated along with the policy or policies that are attached to the + // IAM user whose credentials are used to call GetFederationToken. The passed + // policy is used to scope down the permissions that are available to the IAM + // user, by allowing only a subset of the permissions that are granted to the + // IAM user. The passed policy cannot grant more permissions than those granted + // to the IAM user. The final permissions for the federated user are the most + // restrictive set based on the intersection of the passed policy and the IAM + // user policy. + // + // If you do not pass a policy, the resulting temporary security credentials + // have no effective permissions. The only exception is when the temporary security + // credentials are used to access a resource that has a resource-based policy + // that specifically allows the federated user to access the resource. + // + // The policy plain text must be 2048 bytes or shorter. However, an internal + // conversion compresses it into a packed binary format with a separate limit. + // The PackedPolicySize response element indicates by percentage how close to + // the upper size limit the policy is, with 100% equaling the maximum allowed + // size. For more information about how permissions work, see Permissions for + // GetFederationToken (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). + Policy *string `min:"1" type:"string"` +} + +// String returns the string representation +func (s GetFederationTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenInput) GoString() string { + return s.String() +} + +// Contains the response to a successful GetFederationToken request, including +// temporary AWS credentials that can be used to make AWS requests. +type GetFederationTokenOutput struct { + _ struct{} `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. + // We strongly recommend that you make no assumptions about the maximum size. + // As of this writing, the typical size is less than 4096 bytes, but that can + // vary. Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // Identifiers for the federated user associated with the credentials (such + // as arn:aws:sts::123456789012:federated-user/Bob or 123456789012:Bob). You + // can use the federated user's ARN in your resource-based policies, such as + // an Amazon S3 bucket policy. + FederatedUser *FederatedUser `type:"structure"` + + // A percentage value indicating the size of the policy in packed form. The + // service rejects policies for which the packed size is greater than 100 percent + // of the allowed value. + PackedPolicySize *int64 `type:"integer"` +} + +// String returns the string representation +func (s GetFederationTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenOutput) GoString() string { + return s.String() +} + +type GetSessionTokenInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, that the credentials should remain valid. Acceptable + // durations for IAM user sessions range from 900 seconds (15 minutes) to 129600 + // seconds (36 hours), with 43200 seconds (12 hours) as the default. Sessions + // for AWS account owners are restricted to a maximum of 3600 seconds (one hour). + // If the duration is longer than one hour, the session for AWS account owners + // defaults to one hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The identification number of the MFA device that is associated with the IAM + // user who is making the GetSessionToken call. Specify this value if the IAM + // user has a policy that requires MFA authentication. The value is either the + // serial number for a hardware device (such as GAHT12345678) or an Amazon Resource + // Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user). + // You can find the device for an IAM user by going to the AWS Management Console + // and viewing the user's security credentials. + SerialNumber *string `min:"9" type:"string"` + + // The value provided by the MFA device, if MFA is required. If any policy requires + // the IAM user to submit an MFA code, specify this value. If MFA authentication + // is required, and the user does not provide a code when requesting a set of + // temporary security credentials, the user will receive an "access denied" + // response when requesting resources that require MFA authentication. + TokenCode *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s GetSessionTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenInput) GoString() string { + return s.String() +} + +// Contains the response to a successful GetSessionToken request, including +// temporary AWS credentials that can be used to make AWS requests. +type GetSessionTokenOutput struct { + _ struct{} `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. + // We strongly recommend that you make no assumptions about the maximum size. + // As of this writing, the typical size is less than 4096 bytes, but that can + // vary. Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` +} + +// String returns the string representation +func (s GetSessionTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenOutput) GoString() string { + return s.String() +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go new file mode 100644 index 000000000..4010cc7fa --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go @@ -0,0 +1,12 @@ +package sts + +import "github.com/aws/aws-sdk-go/aws/request" + +func init() { + initRequest = func(r *request.Request) { + switch r.Operation.Name { + case opAssumeRoleWithSAML, opAssumeRoleWithWebIdentity: + r.Handlers.Sign.Clear() // these operations are unsigned + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/service.go b/vendor/github.com/aws/aws-sdk-go/service/sts/service.go new file mode 100644 index 000000000..d1944ed20 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/service.go @@ -0,0 +1,130 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package sts + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/signer/v4" +) + +// The AWS Security Token Service (STS) is a web service that enables you to +// request temporary, limited-privilege credentials for AWS Identity and Access +// Management (IAM) users or for users that you authenticate (federated users). +// This guide provides descriptions of the STS API. For more detailed information +// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html). +// +// As an alternative to using the API, you can use one of the AWS SDKs, which +// consist of libraries and sample code for various programming languages and +// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient +// way to create programmatic access to STS. For example, the SDKs take care +// of cryptographically signing requests, managing errors, and retrying requests +// automatically. For information about the AWS SDKs, including how to download +// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/). +// For information about setting up signatures and authorization through the +// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html" +// target="_blank) in the AWS General Reference. For general information about +// the Query API, go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html" +// target="_blank) in Using IAM. For information about using security tokens +// with other AWS products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) +// in the Using IAM. +// +// If you're new to AWS and need additional technical information about a specific +// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/ +// (http://aws.amazon.com/documentation/" target="_blank). +// +// Endpoints +// +// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com +// that maps to the US East (N. Virginia) region. Additional regions are available, +// but must first be activated in the AWS Management Console before you can +// use a different region's endpoint. For more information about activating +// a region for STS see Activating STS in a New Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the Using IAM. +// +// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region) +// in the AWS General Reference. +// +// Recording API requests +// +// STS supports AWS CloudTrail, which is a service that records AWS calls for +// your AWS account and delivers log files to an Amazon S3 bucket. By using +// information collected by CloudTrail, you can determine what requests were +// successfully made to STS, who made the request, when it was made, and so +// on. To learn more about CloudTrail, including how to turn it on and find +// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html). +//The service client's operations are safe to be used concurrently. +// It is not safe to mutate any of the client's properties though. +type STS struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// A ServiceName is the name of the service the client will make API calls to. +const ServiceName = "sts" + +// New creates a new instance of the STS client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a STS client from just a session. +// svc := sts.New(mySession) +// +// // Create a STS client with additional configuration +// svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS { + c := p.ClientConfig(ServiceName, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *STS { + svc := &STS{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2011-06-15", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBack(v4.Sign) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a STS operation and runs any +// custom request initialization. +func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go b/vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go new file mode 100644 index 000000000..09dae0c9d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +// Package stsiface provides an interface for the AWS Security Token Service. +package stsiface + +import ( + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/sts" +) + +// STSAPI is the interface type for sts.STS. +type STSAPI interface { + AssumeRoleRequest(*sts.AssumeRoleInput) (*request.Request, *sts.AssumeRoleOutput) + + AssumeRole(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) + + AssumeRoleWithSAMLRequest(*sts.AssumeRoleWithSAMLInput) (*request.Request, *sts.AssumeRoleWithSAMLOutput) + + AssumeRoleWithSAML(*sts.AssumeRoleWithSAMLInput) (*sts.AssumeRoleWithSAMLOutput, error) + + AssumeRoleWithWebIdentityRequest(*sts.AssumeRoleWithWebIdentityInput) (*request.Request, *sts.AssumeRoleWithWebIdentityOutput) + + AssumeRoleWithWebIdentity(*sts.AssumeRoleWithWebIdentityInput) (*sts.AssumeRoleWithWebIdentityOutput, error) + + DecodeAuthorizationMessageRequest(*sts.DecodeAuthorizationMessageInput) (*request.Request, *sts.DecodeAuthorizationMessageOutput) + + DecodeAuthorizationMessage(*sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error) + + GetFederationTokenRequest(*sts.GetFederationTokenInput) (*request.Request, *sts.GetFederationTokenOutput) + + GetFederationToken(*sts.GetFederationTokenInput) (*sts.GetFederationTokenOutput, error) + + GetSessionTokenRequest(*sts.GetSessionTokenInput) (*request.Request, *sts.GetSessionTokenOutput) + + GetSessionToken(*sts.GetSessionTokenInput) (*sts.GetSessionTokenOutput, error) +} + +var _ STSAPI = (*sts.STS)(nil) diff --git a/vendor/github.com/bgentry/speakeasy/.gitignore b/vendor/github.com/bgentry/speakeasy/.gitignore new file mode 100644 index 000000000..9e1311461 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/.gitignore @@ -0,0 +1,2 @@ +example/example +example/example.exe diff --git a/vendor/github.com/bgentry/speakeasy/LICENSE_WINDOWS b/vendor/github.com/bgentry/speakeasy/LICENSE_WINDOWS new file mode 100644 index 000000000..ff177f612 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/LICENSE_WINDOWS @@ -0,0 +1,201 @@ + 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. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [2013] [the CloudFoundry Authors] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/bgentry/speakeasy/Readme.md b/vendor/github.com/bgentry/speakeasy/Readme.md new file mode 100644 index 000000000..fceda7518 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/Readme.md @@ -0,0 +1,30 @@ +# Speakeasy + +This package provides cross-platform Go (#golang) helpers for taking user input +from the terminal while not echoing the input back (similar to `getpasswd`). The +package uses syscalls to avoid any dependence on cgo, and is therefore +compatible with cross-compiling. + +[![GoDoc](https://godoc.org/github.com/bgentry/speakeasy?status.png)][godoc] + +## Unicode + +Multi-byte unicode characters work successfully on Mac OS X. On Windows, +however, this may be problematic (as is UTF in general on Windows). Other +platforms have not been tested. + +## License + +The code herein was not written by me, but was compiled from two separate open +source packages. Unix portions were imported from [gopass][gopass], while +Windows portions were imported from the [CloudFoundry Go CLI][cf-cli]'s +[Windows terminal helpers][cf-ui-windows]. + +The [license for the windows portion](./LICENSE_WINDOWS) has been copied exactly +from the source (though I attempted to fill in the correct owner in the +boilerplate copyright notice). + +[cf-cli]: https://github.com/cloudfoundry/cli "CloudFoundry Go CLI" +[cf-ui-windows]: https://github.com/cloudfoundry/cli/blob/master/src/cf/terminal/ui_windows.go "CloudFoundry Go CLI Windows input helpers" +[godoc]: https://godoc.org/github.com/bgentry/speakeasy "speakeasy on Godoc.org" +[gopass]: https://code.google.com/p/gopass "gopass" diff --git a/vendor/github.com/bgentry/speakeasy/example/main.go b/vendor/github.com/bgentry/speakeasy/example/main.go new file mode 100644 index 000000000..d71153a16 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/example/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + "os" + + "github.com/bgentry/speakeasy" +) + +func main() { + password, err := speakeasy.Ask("Please enter a password: ") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Printf("Password result: %q\n", password) + fmt.Printf("Password len: %d\n", len(password)) +} diff --git a/vendor/github.com/bgentry/speakeasy/speakeasy.go b/vendor/github.com/bgentry/speakeasy/speakeasy.go new file mode 100644 index 000000000..d16233a1a --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/speakeasy.go @@ -0,0 +1,47 @@ +package speakeasy + +import ( + "fmt" + "io" + "os" + "strings" +) + +// Ask the user to enter a password with input hidden. prompt is a string to +// display before the user's input. Returns the provided password, or an error +// if the command failed. +func Ask(prompt string) (password string, err error) { + return FAsk(os.Stdout, prompt) +} + +// Same as the Ask function, except it is possible to specify the file to write +// the prompt to. +func FAsk(file *os.File, prompt string) (password string, err error) { + if prompt != "" { + fmt.Fprint(file, prompt) // Display the prompt. + } + password, err = getPassword() + + // Carriage return after the user input. + fmt.Fprintln(file, "") + return +} + +func readline() (value string, err error) { + var valb []byte + var n int + b := make([]byte, 1) + for { + // read one byte at a time so we don't accidentally read extra bytes + n, err = os.Stdin.Read(b) + if err != nil && err != io.EOF { + return "", err + } + if n == 0 || b[0] == '\n' { + break + } + valb = append(valb, b[0]) + } + + return strings.TrimSuffix(string(valb), "\r"), nil +} diff --git a/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go b/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go new file mode 100644 index 000000000..dca74bd99 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go @@ -0,0 +1,93 @@ +// based on https://code.google.com/p/gopass +// Author: johnsiilver@gmail.com (John Doak) +// +// Original code is based on code by RogerV in the golang-nuts thread: +// https://groups.google.com/group/golang-nuts/browse_thread/thread/40cc41e9d9fc9247 + +// +build darwin freebsd linux netbsd openbsd solaris + +package speakeasy + +import ( + "fmt" + "os" + "os/signal" + "strings" + "syscall" +) + +const sttyArg0 = "/bin/stty" + +var ( + sttyArgvEOff = []string{"stty", "-echo"} + sttyArgvEOn = []string{"stty", "echo"} +) + +// getPassword gets input hidden from the terminal from a user. This is +// accomplished by turning off terminal echo, reading input from the user and +// finally turning on terminal echo. +func getPassword() (password string, err error) { + sig := make(chan os.Signal, 10) + brk := make(chan bool) + + // File descriptors for stdin, stdout, and stderr. + fd := []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()} + + // Setup notifications of termination signals to channel sig, create a process to + // watch for these signals so we can turn back on echo if need be. + signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT, + syscall.SIGTERM) + go catchSignal(fd, sig, brk) + + // Turn off the terminal echo. + pid, err := echoOff(fd) + if err != nil { + return "", err + } + + // Turn on the terminal echo and stop listening for signals. + defer signal.Stop(sig) + defer close(brk) + defer echoOn(fd) + + syscall.Wait4(pid, nil, 0, nil) + + line, err := readline() + if err == nil { + password = strings.TrimSpace(line) + } else { + err = fmt.Errorf("failed during password entry: %s", err) + } + + return password, err +} + +// echoOff turns off the terminal echo. +func echoOff(fd []uintptr) (int, error) { + pid, err := syscall.ForkExec(sttyArg0, sttyArgvEOff, &syscall.ProcAttr{Dir: "", Files: fd}) + if err != nil { + return 0, fmt.Errorf("failed turning off console echo for password entry:\n\t%s", err) + } + return pid, nil +} + +// echoOn turns back on the terminal echo. +func echoOn(fd []uintptr) { + // Turn on the terminal echo. + pid, e := syscall.ForkExec(sttyArg0, sttyArgvEOn, &syscall.ProcAttr{Dir: "", Files: fd}) + if e == nil { + syscall.Wait4(pid, nil, 0, nil) + } +} + +// catchSignal tries to catch SIGKILL, SIGQUIT and SIGINT so that we can turn +// terminal echo back on before the program ends. Otherwise the user is left +// with echo off on their terminal. +func catchSignal(fd []uintptr, sig chan os.Signal, brk chan bool) { + select { + case <-sig: + echoOn(fd) + os.Exit(-1) + case <-brk: + } +} diff --git a/vendor/github.com/bgentry/speakeasy/speakeasy_windows.go b/vendor/github.com/bgentry/speakeasy/speakeasy_windows.go new file mode 100644 index 000000000..fc4177c44 --- /dev/null +++ b/vendor/github.com/bgentry/speakeasy/speakeasy_windows.go @@ -0,0 +1,43 @@ +// +build windows + +package speakeasy + +import ( + "os" + "syscall" +) + +// SetConsoleMode function can be used to change value of ENABLE_ECHO_INPUT: +// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx +const ENABLE_ECHO_INPUT = 0x0004 + +func getPassword() (password string, err error) { + hStdin := syscall.Handle(os.Stdin.Fd()) + var oldMode uint32 + + err = syscall.GetConsoleMode(hStdin, &oldMode) + if err != nil { + return + } + + var newMode uint32 = (oldMode &^ ENABLE_ECHO_INPUT) + + err = setConsoleMode(hStdin, newMode) + defer setConsoleMode(hStdin, oldMode) + if err != nil { + return + } + + return readline() +} + +func setConsoleMode(console syscall.Handle, mode uint32) (err error) { + dll := syscall.MustLoadDLL("kernel32") + proc := dll.MustFindProc("SetConsoleMode") + r, _, err := proc.Call(uintptr(console), uintptr(mode)) + + if r == 0 { + return err + } + return nil +} diff --git a/vendor/github.com/digitalocean/godo/.travis.yml b/vendor/github.com/digitalocean/godo/.travis.yml new file mode 100644 index 000000000..245a2f517 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.3 + - 1.4 + - tip diff --git a/vendor/github.com/digitalocean/godo/CONTRIBUTING.md b/vendor/github.com/digitalocean/godo/CONTRIBUTING.md new file mode 100644 index 000000000..f27200a7a --- /dev/null +++ b/vendor/github.com/digitalocean/godo/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing + +If you submit a pull request, please keep the following guidelines in mind: + +1. Code should be `go fmt` compliant. +2. Types, structs and funcs should be documented. +3. Tests pass. + +## Getting set up + +Assuming your `$GOPATH` is set up according to your desires, run: + +```sh +go get github.com/digitalocean/godo +``` + +## Running tests + +When working on code in this repository, tests can be run via: + +```sh +go test . +``` diff --git a/vendor/github.com/digitalocean/godo/LICENSE.txt b/vendor/github.com/digitalocean/godo/LICENSE.txt new file mode 100644 index 000000000..43c5d2eee --- /dev/null +++ b/vendor/github.com/digitalocean/godo/LICENSE.txt @@ -0,0 +1,55 @@ +Copyright (c) 2014-2016 The godo AUTHORS. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================== +Portions of the client are based on code at: +https://github.com/google/go-github/ + +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/digitalocean/godo/README.md b/vendor/github.com/digitalocean/godo/README.md new file mode 100644 index 000000000..03d0c0768 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/README.md @@ -0,0 +1,136 @@ +[![Build Status](https://travis-ci.org/digitalocean/godo.svg)](https://travis-ci.org/digitalocean/godo) + +# Godo + +Godo is a Go client library for accessing the DigitalOcean V2 API. + +You can view the client API docs here: [http://godoc.org/github.com/digitalocean/godo](http://godoc.org/github.com/digitalocean/godo) + +You can view DigitalOcean API docs here: [https://developers.digitalocean.com/documentation/v2/](https://developers.digitalocean.com/documentation/v2/) + + +## Usage + +```go +import "github.com/digitalocean/godo" +``` + +Create a new DigitalOcean client, then use the exposed services to +access different parts of the DigitalOcean API. + +### Authentication + +Currently, Personal Access Token (PAT) is the only method of +authenticating with the API. You can manage your tokens +at the DigitalOcean Control Panel [Applications Page](https://cloud.digitalocean.com/settings/applications). + +You can then use your token to create a new client: + +```go +import "golang.org/x/oauth2" + +pat := "mytoken" +type TokenSource struct { + AccessToken string +} + +func (t *TokenSource) Token() (*oauth2.Token, error) { + token := &oauth2.Token{ + AccessToken: t.AccessToken, + } + return token, nil +} + +tokenSource := &TokenSource{ + AccessToken: pat, +} +oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource) +client := godo.NewClient(oauthClient) +``` + +## Examples + + +To create a new Droplet: + +```go +dropletName := "super-cool-droplet" + +createRequest := &godo.DropletCreateRequest{ + Name: dropletName, + Region: "nyc3", + Size: "512mb", + Image: godo.DropletCreateImage{ + Slug: "ubuntu-14-04-x64", + }, +} + +newDroplet, _, err := client.Droplets.Create(createRequest) + +if err != nil { + fmt.Printf("Something bad happened: %s\n\n", err) + return err +} +``` + +### Pagination + +If a list of items is paginated by the API, you must request pages individually. For example, to fetch all Droplets: + +```go +func DropletList(client *godo.Client) ([]godo.Droplet, error) { + // create a list to hold our droplets + list := []godo.Droplet{} + + // create options. initially, these will be blank + opt := &godo.ListOptions{} + for { + droplets, resp, err := client.Droplets.List(opt) + if err != nil { + return nil, err + } + + // append the current page's droplets to our list + for _, d := range droplets { + list = append(list, d) + } + + // if we are at the last page, break out the for loop + if resp.Links == nil || resp.Links.IsLastPage() { + break + } + + page, err := resp.Links.CurrentPage() + if err != nil { + return nil, err + } + + // set the page we want for the next request + opt.Page = page + 1 + } + + return list, nil +} +``` + +## Versioning + +Each version of the client is tagged and the version is updated accordingly. + +Since Go does not have a built-in versioning, a package management tool is +recommended - a good one that works with git tags is +[gopkg.in](http://labix.org/gopkg.in). + +To see the list of past versions, run `git tag`. + + +## Documentation + +For a comprehensive list of examples, check out the [API documentation](https://developers.digitalocean.com/documentation/v2/). + +For details on all the functionality in this library, see the [GoDoc](http://godoc.org/github.com/digitalocean/godo) documentation. + + +## Contributing + +We love pull requests! Please see the [contribution guidelines](CONTRIBUTING.md). diff --git a/vendor/github.com/digitalocean/godo/account.go b/vendor/github.com/digitalocean/godo/account.go new file mode 100644 index 000000000..3c2a1c3af --- /dev/null +++ b/vendor/github.com/digitalocean/godo/account.go @@ -0,0 +1,53 @@ +package godo + +// AccountService is an interface for interfacing with the Account +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2/#account +type AccountService interface { + Get() (*Account, *Response, error) +} + +// AccountServiceOp handles communication with the Account related methods of +// the DigitalOcean API. +type AccountServiceOp struct { + client *Client +} + +var _ AccountService = &AccountServiceOp{} + +// Account represents a DigitalOcean Account +type Account struct { + DropletLimit int `json:"droplet_limit,omitempty"` + FloatingIPLimit int `json:"floating_ip_limit,omitempty"` + Email string `json:"email,omitempty"` + UUID string `json:"uuid,omitempty"` + EmailVerified bool `json:"email_verified,omitempty"` + Status string `json:"status,omitempty"` + StatusMessage string `json:"status_message,omitempty"` +} + +type accountRoot struct { + Account *Account `json:"account"` +} + +func (r Account) String() string { + return Stringify(r) +} + +// Get DigitalOcean account info +func (s *AccountServiceOp) Get() (*Account, *Response, error) { + path := "v2/account" + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(accountRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return root.Account, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/action.go b/vendor/github.com/digitalocean/godo/action.go new file mode 100644 index 000000000..e19493b92 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/action.go @@ -0,0 +1,100 @@ +package godo + +import "fmt" + +const ( + actionsBasePath = "v2/actions" + + // ActionInProgress is an in progress action status + ActionInProgress = "in-progress" + + //ActionCompleted is a completed action status + ActionCompleted = "completed" +) + +// ActionsService handles communction with action related methods of the +// DigitalOcean API: https://developers.digitalocean.com/documentation/v2#actions +type ActionsService interface { + List(*ListOptions) ([]Action, *Response, error) + Get(int) (*Action, *Response, error) +} + +// ActionsServiceOp handles communition with the image action related methods of the +// DigitalOcean API. +type ActionsServiceOp struct { + client *Client +} + +var _ ActionsService = &ActionsServiceOp{} + +type actionsRoot struct { + Actions []Action `json:"actions"` + Links *Links `json:"links"` +} + +type actionRoot struct { + Event Action `json:"action"` +} + +// Action represents a DigitalOcean Action +type Action struct { + ID int `json:"id"` + Status string `json:"status"` + Type string `json:"type"` + StartedAt *Timestamp `json:"started_at"` + CompletedAt *Timestamp `json:"completed_at"` + ResourceID int `json:"resource_id"` + ResourceType string `json:"resource_type"` + Region *Region `json:"region,omitempty"` + RegionSlug string `json:"region_slug,omitempty"` +} + +// List all actions +func (s *ActionsServiceOp) List(opt *ListOptions) ([]Action, *Response, error) { + path := actionsBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Actions, resp, err +} + +// Get an action by ID. +func (s *ActionsServiceOp) Get(id int) (*Action, *Response, error) { + if id < 1 { + return nil, nil, NewArgError("id", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", actionsBasePath, id) + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} + +func (a Action) String() string { + return Stringify(a) +} diff --git a/vendor/github.com/digitalocean/godo/doc.go b/vendor/github.com/digitalocean/godo/doc.go new file mode 100644 index 000000000..e660f794a --- /dev/null +++ b/vendor/github.com/digitalocean/godo/doc.go @@ -0,0 +1,2 @@ +// Package godo is the DigtalOcean API v2 client for Go +package godo diff --git a/vendor/github.com/digitalocean/godo/domains.go b/vendor/github.com/digitalocean/godo/domains.go new file mode 100644 index 000000000..31de17868 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/domains.go @@ -0,0 +1,323 @@ +package godo + +import "fmt" + +const domainsBasePath = "v2/domains" + +// DomainsService is an interface for managing DNS with the DigitalOcean API. +// See: https://developers.digitalocean.com/documentation/v2#domains and +// https://developers.digitalocean.com/documentation/v2#domain-records +type DomainsService interface { + List(*ListOptions) ([]Domain, *Response, error) + Get(string) (*Domain, *Response, error) + Create(*DomainCreateRequest) (*Domain, *Response, error) + Delete(string) (*Response, error) + + Records(string, *ListOptions) ([]DomainRecord, *Response, error) + Record(string, int) (*DomainRecord, *Response, error) + DeleteRecord(string, int) (*Response, error) + EditRecord(string, int, *DomainRecordEditRequest) (*DomainRecord, *Response, error) + CreateRecord(string, *DomainRecordEditRequest) (*DomainRecord, *Response, error) +} + +// DomainsServiceOp handles communication with the domain related methods of the +// DigitalOcean API. +type DomainsServiceOp struct { + client *Client +} + +var _ DomainsService = &DomainsServiceOp{} + +// Domain represents a DigitalOcean domain +type Domain struct { + Name string `json:"name"` + TTL int `json:"ttl"` + ZoneFile string `json:"zone_file"` +} + +// domainRoot represents a response from the DigitalOcean API +type domainRoot struct { + Domain *Domain `json:"domain"` +} + +type domainsRoot struct { + Domains []Domain `json:"domains"` + Links *Links `json:"links"` +} + +// DomainCreateRequest respresents a request to create a domain. +type DomainCreateRequest struct { + Name string `json:"name"` + IPAddress string `json:"ip_address"` +} + +// DomainRecordRoot is the root of an individual Domain Record response +type domainRecordRoot struct { + DomainRecord *DomainRecord `json:"domain_record"` +} + +// DomainRecordsRoot is the root of a group of Domain Record responses +type domainRecordsRoot struct { + DomainRecords []DomainRecord `json:"domain_records"` + Links *Links `json:"links"` +} + +// DomainRecord represents a DigitalOcean DomainRecord +type DomainRecord struct { + ID int `json:"id,float64,omitempty"` + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Data string `json:"data,omitempty"` + Priority int `json:"priority,omitempty"` + Port int `json:"port,omitempty"` + Weight int `json:"weight,omitempty"` +} + +// DomainRecordEditRequest represents a request to update a domain record. +type DomainRecordEditRequest struct { + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Data string `json:"data,omitempty"` + Priority int `json:"priority,omitempty"` + Port int `json:"port,omitempty"` + Weight int `json:"weight,omitempty"` +} + +func (d Domain) String() string { + return Stringify(d) +} + +// List all domains. +func (s DomainsServiceOp) List(opt *ListOptions) ([]Domain, *Response, error) { + path := domainsBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(domainsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Domains, resp, err +} + +// Get individual domain. It requires a non-empty domain name. +func (s *DomainsServiceOp) Get(name string) (*Domain, *Response, error) { + if len(name) < 1 { + return nil, nil, NewArgError("name", "cannot be an empty string") + } + + path := fmt.Sprintf("%s/%s", domainsBasePath, name) + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(domainRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return root.Domain, resp, err +} + +// Create a new domain +func (s *DomainsServiceOp) Create(createRequest *DomainCreateRequest) (*Domain, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + path := domainsBasePath + + req, err := s.client.NewRequest("POST", path, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(domainRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + return root.Domain, resp, err +} + +// Delete domain +func (s *DomainsServiceOp) Delete(name string) (*Response, error) { + if len(name) < 1 { + return nil, NewArgError("name", "cannot be an empty string") + } + + path := fmt.Sprintf("%s/%s", domainsBasePath, name) + + req, err := s.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + + return resp, err +} + +// Converts a DomainRecord to a string. +func (d DomainRecord) String() string { + return Stringify(d) +} + +// Converts a DomainRecordEditRequest to a string. +func (d DomainRecordEditRequest) String() string { + return Stringify(d) +} + +// Records returns a slice of DomainRecords for a domain +func (s *DomainsServiceOp) Records(domain string, opt *ListOptions) ([]DomainRecord, *Response, error) { + if len(domain) < 1 { + return nil, nil, NewArgError("domain", "cannot be an empty string") + } + + path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(domainRecordsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.DomainRecords, resp, err +} + +// Record returns the record id from a domain +func (s *DomainsServiceOp) Record(domain string, id int) (*DomainRecord, *Response, error) { + if len(domain) < 1 { + return nil, nil, NewArgError("domain", "cannot be an empty string") + } + + if id < 1 { + return nil, nil, NewArgError("id", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id) + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + record := new(domainRecordRoot) + resp, err := s.client.Do(req, record) + if err != nil { + return nil, resp, err + } + + return record.DomainRecord, resp, err +} + +// DeleteRecord deletes a record from a domain identified by id +func (s *DomainsServiceOp) DeleteRecord(domain string, id int) (*Response, error) { + if len(domain) < 1 { + return nil, NewArgError("domain", "cannot be an empty string") + } + + if id < 1 { + return nil, NewArgError("id", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id) + + req, err := s.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + + return resp, err +} + +// EditRecord edits a record using a DomainRecordEditRequest +func (s *DomainsServiceOp) EditRecord( + domain string, + id int, + editRequest *DomainRecordEditRequest, +) (*DomainRecord, *Response, error) { + if len(domain) < 1 { + return nil, nil, NewArgError("domain", "cannot be an empty string") + } + + if id < 1 { + return nil, nil, NewArgError("id", "cannot be less than 1") + } + + if editRequest == nil { + return nil, nil, NewArgError("editRequest", "cannot be nil") + } + + path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id) + + req, err := s.client.NewRequest("PUT", path, editRequest) + if err != nil { + return nil, nil, err + } + + d := new(DomainRecord) + resp, err := s.client.Do(req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, err +} + +// CreateRecord creates a record using a DomainRecordEditRequest +func (s *DomainsServiceOp) CreateRecord( + domain string, + createRequest *DomainRecordEditRequest) (*DomainRecord, *Response, error) { + if len(domain) < 1 { + return nil, nil, NewArgError("domain", "cannot be empty string") + } + + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain) + req, err := s.client.NewRequest("POST", path, createRequest) + + if err != nil { + return nil, nil, err + } + + d := new(domainRecordRoot) + resp, err := s.client.Do(req, d) + if err != nil { + return nil, resp, err + } + + return d.DomainRecord, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/droplet_actions.go b/vendor/github.com/digitalocean/godo/droplet_actions.go new file mode 100644 index 000000000..7012aee7f --- /dev/null +++ b/vendor/github.com/digitalocean/godo/droplet_actions.go @@ -0,0 +1,238 @@ +package godo + +import ( + "fmt" + "net/url" +) + +// ActionRequest reprents DigitalOcean Action Request +type ActionRequest map[string]interface{} + +// DropletActionsService is an interface for interfacing with the droplet actions +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#droplet-actions +type DropletActionsService interface { + Shutdown(int) (*Action, *Response, error) + PowerOff(int) (*Action, *Response, error) + PowerOn(int) (*Action, *Response, error) + PowerCycle(int) (*Action, *Response, error) + Reboot(int) (*Action, *Response, error) + Restore(int, int) (*Action, *Response, error) + Resize(int, string, bool) (*Action, *Response, error) + Rename(int, string) (*Action, *Response, error) + Snapshot(int, string) (*Action, *Response, error) + EnableBackups(int) (*Action, *Response, error) + DisableBackups(int) (*Action, *Response, error) + PasswordReset(int) (*Action, *Response, error) + RebuildByImageID(int, int) (*Action, *Response, error) + RebuildByImageSlug(int, string) (*Action, *Response, error) + ChangeKernel(int, int) (*Action, *Response, error) + EnableIPv6(int) (*Action, *Response, error) + EnablePrivateNetworking(int) (*Action, *Response, error) + Upgrade(int) (*Action, *Response, error) + Get(int, int) (*Action, *Response, error) + GetByURI(string) (*Action, *Response, error) +} + +// DropletActionsServiceOp handles communication with the droplet action related +// methods of the DigitalOcean API. +type DropletActionsServiceOp struct { + client *Client +} + +var _ DropletActionsService = &DropletActionsServiceOp{} + +// Shutdown a Droplet +func (s *DropletActionsServiceOp) Shutdown(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "shutdown"} + return s.doAction(id, request) +} + +// PowerOff a Droplet +func (s *DropletActionsServiceOp) PowerOff(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "power_off"} + return s.doAction(id, request) +} + +// PowerOn a Droplet +func (s *DropletActionsServiceOp) PowerOn(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "power_on"} + return s.doAction(id, request) +} + +// PowerCycle a Droplet +func (s *DropletActionsServiceOp) PowerCycle(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "power_cycle"} + return s.doAction(id, request) +} + +// Reboot a Droplet +func (s *DropletActionsServiceOp) Reboot(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "reboot"} + return s.doAction(id, request) +} + +// Restore an image to a Droplet +func (s *DropletActionsServiceOp) Restore(id, imageID int) (*Action, *Response, error) { + requestType := "restore" + request := &ActionRequest{ + "type": requestType, + "image": float64(imageID), + } + return s.doAction(id, request) +} + +// Resize a Droplet +func (s *DropletActionsServiceOp) Resize(id int, sizeSlug string, resizeDisk bool) (*Action, *Response, error) { + requestType := "resize" + request := &ActionRequest{ + "type": requestType, + "size": sizeSlug, + "disk": resizeDisk, + } + return s.doAction(id, request) +} + +// Rename a Droplet +func (s *DropletActionsServiceOp) Rename(id int, name string) (*Action, *Response, error) { + requestType := "rename" + request := &ActionRequest{ + "type": requestType, + "name": name, + } + return s.doAction(id, request) +} + +// Snapshot a Droplet. +func (s *DropletActionsServiceOp) Snapshot(id int, name string) (*Action, *Response, error) { + requestType := "snapshot" + request := &ActionRequest{ + "type": requestType, + "name": name, + } + return s.doAction(id, request) +} + +// EnableBackups enables backups for a droplet. +func (s *DropletActionsServiceOp) EnableBackups(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "enable_backups"} + return s.doAction(id, request) +} + +// DisableBackups disables backups for a droplet. +func (s *DropletActionsServiceOp) DisableBackups(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "disable_backups"} + return s.doAction(id, request) +} + +// PasswordReset resets the password for a droplet. +func (s *DropletActionsServiceOp) PasswordReset(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "password_reset"} + return s.doAction(id, request) +} + +// RebuildByImageID rebuilds a droplet droplet from an image with a given id. +func (s *DropletActionsServiceOp) RebuildByImageID(id, imageID int) (*Action, *Response, error) { + request := &ActionRequest{"type": "rebuild", "image": imageID} + return s.doAction(id, request) +} + +// RebuildByImageSlug rebuilds a droplet from an image with a given slug. +func (s *DropletActionsServiceOp) RebuildByImageSlug(id int, slug string) (*Action, *Response, error) { + request := &ActionRequest{"type": "rebuild", "image": slug} + return s.doAction(id, request) +} + +// ChangeKernel changes the kernel for a droplet. +func (s *DropletActionsServiceOp) ChangeKernel(id, kernelID int) (*Action, *Response, error) { + request := &ActionRequest{"type": "change_kernel", "kernel": kernelID} + return s.doAction(id, request) +} + +// EnableIPv6 enables IPv6 for a droplet. +func (s *DropletActionsServiceOp) EnableIPv6(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "enable_ipv6"} + return s.doAction(id, request) +} + +// EnablePrivateNetworking enables private networking for a droplet. +func (s *DropletActionsServiceOp) EnablePrivateNetworking(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "enable_private_networking"} + return s.doAction(id, request) +} + +// Upgrade a droplet. +func (s *DropletActionsServiceOp) Upgrade(id int) (*Action, *Response, error) { + request := &ActionRequest{"type": "upgrade"} + return s.doAction(id, request) +} + +func (s *DropletActionsServiceOp) doAction(id int, request *ActionRequest) (*Action, *Response, error) { + if id < 1 { + return nil, nil, NewArgError("id", "cannot be less than 1") + } + + if request == nil { + return nil, nil, NewArgError("request", "request can't be nil") + } + + path := dropletActionPath(id) + + req, err := s.client.NewRequest("POST", path, request) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} + +// Get an action for a particular droplet by id. +func (s *DropletActionsServiceOp) Get(dropletID, actionID int) (*Action, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + if actionID < 1 { + return nil, nil, NewArgError("actionID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", dropletActionPath(dropletID), actionID) + return s.get(path) +} + +// GetByURI gets an action for a particular droplet by id. +func (s *DropletActionsServiceOp) GetByURI(rawurl string) (*Action, *Response, error) { + u, err := url.Parse(rawurl) + if err != nil { + return nil, nil, err + } + + return s.get(u.Path) + +} + +func (s *DropletActionsServiceOp) get(path string) (*Action, *Response, error) { + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err + +} + +func dropletActionPath(dropletID int) string { + return fmt.Sprintf("v2/droplets/%d/actions", dropletID) +} diff --git a/vendor/github.com/digitalocean/godo/droplets.go b/vendor/github.com/digitalocean/godo/droplets.go new file mode 100644 index 000000000..5ba7c27d4 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/droplets.go @@ -0,0 +1,495 @@ +package godo + +import ( + "encoding/json" + "errors" + "fmt" +) + +const dropletBasePath = "v2/droplets" + +var errNoNetworks = errors.New("no networks have been defined") + +// DropletsService is an interface for interfacing with the droplet +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#droplets +type DropletsService interface { + List(*ListOptions) ([]Droplet, *Response, error) + Get(int) (*Droplet, *Response, error) + Create(*DropletCreateRequest) (*Droplet, *Response, error) + CreateMultiple(*DropletMultiCreateRequest) ([]Droplet, *Response, error) + Delete(int) (*Response, error) + Kernels(int, *ListOptions) ([]Kernel, *Response, error) + Snapshots(int, *ListOptions) ([]Image, *Response, error) + Backups(int, *ListOptions) ([]Image, *Response, error) + Actions(int, *ListOptions) ([]Action, *Response, error) + Neighbors(int) ([]Droplet, *Response, error) +} + +// DropletsServiceOp handles communication with the droplet related methods of the +// DigitalOcean API. +type DropletsServiceOp struct { + client *Client +} + +var _ DropletsService = &DropletsServiceOp{} + +// Droplet represents a DigitalOcean Droplet +type Droplet struct { + ID int `json:"id,float64,omitempty"` + Name string `json:"name,omitempty"` + Memory int `json:"memory,omitempty"` + Vcpus int `json:"vcpus,omitempty"` + Disk int `json:"disk,omitempty"` + Region *Region `json:"region,omitempty"` + Image *Image `json:"image,omitempty"` + Size *Size `json:"size,omitempty"` + SizeSlug string `json:"size_slug,omitempty"` + BackupIDs []int `json:"backup_ids,omitempty"` + SnapshotIDs []int `json:"snapshot_ids,omitempty"` + Locked bool `json:"locked,bool,omitempty"` + Status string `json:"status,omitempty"` + Networks *Networks `json:"networks,omitempty"` + ActionIDs []int `json:"action_ids,omitempty"` + Created string `json:"created_at,omitempty"` + Kernel *Kernel `json:"kernel, omitempty"` +} + +// PublicIPv4 returns the public IPv4 address for the Droplet. +func (d *Droplet) PublicIPv4() (string, error) { + if d.Networks == nil { + return "", errNoNetworks + } + + for _, v4 := range d.Networks.V4 { + if v4.Type == "public" { + return v4.IPAddress, nil + } + } + + return "", nil +} + +// PrivateIPv4 returns the private IPv4 address for the Droplet. +func (d *Droplet) PrivateIPv4() (string, error) { + if d.Networks == nil { + return "", errNoNetworks + } + + for _, v4 := range d.Networks.V4 { + if v4.Type == "private" { + return v4.IPAddress, nil + } + } + + return "", nil +} + +// PublicIPv6 returns the private IPv6 address for the Droplet. +func (d *Droplet) PublicIPv6() (string, error) { + if d.Networks == nil { + return "", errNoNetworks + } + + for _, v4 := range d.Networks.V6 { + if v4.Type == "public" { + return v4.IPAddress, nil + } + } + + return "", nil +} + +// Kernel object +type Kernel struct { + ID int `json:"id,float64,omitempty"` + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// Convert Droplet to a string +func (d Droplet) String() string { + return Stringify(d) +} + +// DropletRoot represents a Droplet root +type dropletRoot struct { + Droplet *Droplet `json:"droplet"` + Links *Links `json:"links,omitempty"` +} + +type dropletsRoot struct { + Droplets []Droplet `json:"droplets"` + Links *Links `json:"links"` +} + +type kernelsRoot struct { + Kernels []Kernel `json:"kernels,omitempty"` + Links *Links `json:"links"` +} + +type snapshotsRoot struct { + Snapshots []Image `json:"snapshots,omitempty"` + Links *Links `json:"links"` +} + +type backupsRoot struct { + Backups []Image `json:"backups,omitempty"` + Links *Links `json:"links"` +} + +// DropletCreateImage identifies an image for the create request. It prefers slug over ID. +type DropletCreateImage struct { + ID int + Slug string +} + +// MarshalJSON returns either the slug or id of the image. It returns the id +// if the slug is empty. +func (d DropletCreateImage) MarshalJSON() ([]byte, error) { + if d.Slug != "" { + return json.Marshal(d.Slug) + } + + return json.Marshal(d.ID) +} + +// DropletCreateSSHKey identifies a SSH Key for the create request. It prefers fingerprint over ID. +type DropletCreateSSHKey struct { + ID int + Fingerprint string +} + +// MarshalJSON returns either the fingerprint or id of the ssh key. It returns +// the id if the fingerprint is empty. +func (d DropletCreateSSHKey) MarshalJSON() ([]byte, error) { + if d.Fingerprint != "" { + return json.Marshal(d.Fingerprint) + } + + return json.Marshal(d.ID) +} + +// DropletCreateRequest represents a request to create a droplet. +type DropletCreateRequest struct { + Name string `json:"name"` + Region string `json:"region"` + Size string `json:"size"` + Image DropletCreateImage `json:"image"` + SSHKeys []DropletCreateSSHKey `json:"ssh_keys"` + Backups bool `json:"backups"` + IPv6 bool `json:"ipv6"` + PrivateNetworking bool `json:"private_networking"` + UserData string `json:"user_data,omitempty"` +} + +// DropletMultiCreateRequest is a request to create multiple droplets. +type DropletMultiCreateRequest struct { + Names []string `json:"names"` + Region string `json:"region"` + Size string `json:"size"` + Image DropletCreateImage `json:"image"` + SSHKeys []DropletCreateSSHKey `json:"ssh_keys"` + Backups bool `json:"backups"` + IPv6 bool `json:"ipv6"` + PrivateNetworking bool `json:"private_networking"` + UserData string `json:"user_data,omitempty"` +} + +func (d DropletCreateRequest) String() string { + return Stringify(d) +} + +func (d DropletMultiCreateRequest) String() string { + return Stringify(d) +} + +// Networks represents the droplet's networks +type Networks struct { + V4 []NetworkV4 `json:"v4,omitempty"` + V6 []NetworkV6 `json:"v6,omitempty"` +} + +// NetworkV4 represents a DigitalOcean IPv4 Network +type NetworkV4 struct { + IPAddress string `json:"ip_address,omitempty"` + Netmask string `json:"netmask,omitempty"` + Gateway string `json:"gateway,omitempty"` + Type string `json:"type,omitempty"` +} + +func (n NetworkV4) String() string { + return Stringify(n) +} + +// NetworkV6 represents a DigitalOcean IPv6 network. +type NetworkV6 struct { + IPAddress string `json:"ip_address,omitempty"` + Netmask int `json:"netmask,omitempty"` + Gateway string `json:"gateway,omitempty"` + Type string `json:"type,omitempty"` +} + +func (n NetworkV6) String() string { + return Stringify(n) +} + +// List all droplets +func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error) { + path := dropletBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(dropletsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Droplets, resp, err +} + +// Get individual droplet +func (s *DropletsServiceOp) Get(dropletID int) (*Droplet, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID) + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(dropletRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return root.Droplet, resp, err +} + +// Create droplet +func (s *DropletsServiceOp) Create(createRequest *DropletCreateRequest) (*Droplet, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + path := dropletBasePath + + req, err := s.client.NewRequest("POST", path, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(dropletRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Droplet, resp, err +} + +// CreateMultiple creates multiple droplets. +func (s *DropletsServiceOp) CreateMultiple(createRequest *DropletMultiCreateRequest) ([]Droplet, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + path := dropletBasePath + + req, err := s.client.NewRequest("POST", path, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(dropletsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Droplets, resp, err +} + +// Delete droplet +func (s *DropletsServiceOp) Delete(dropletID int) (*Response, error) { + if dropletID < 1 { + return nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID) + + req, err := s.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + + return resp, err +} + +// Kernels lists kernels available for a droplet. +func (s *DropletsServiceOp) Kernels(dropletID int, opt *ListOptions) ([]Kernel, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d/kernels", dropletBasePath, dropletID) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(kernelsRoot) + resp, err := s.client.Do(req, root) + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Kernels, resp, err +} + +// Actions lists the actions for a droplet. +func (s *DropletsServiceOp) Actions(dropletID int, opt *ListOptions) ([]Action, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d/actions", dropletBasePath, dropletID) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Actions, resp, err +} + +// Backups lists the backups for a droplet. +func (s *DropletsServiceOp) Backups(dropletID int, opt *ListOptions) ([]Image, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d/backups", dropletBasePath, dropletID) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(backupsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Backups, resp, err +} + +// Snapshots lists the snapshots available for a droplet. +func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d/snapshots", dropletBasePath, dropletID) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(snapshotsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Snapshots, resp, err +} + +// Neighbors lists the neighbors for a droplet. +func (s *DropletsServiceOp) Neighbors(dropletID int) ([]Droplet, *Response, error) { + if dropletID < 1 { + return nil, nil, NewArgError("dropletID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d/neighbors", dropletBasePath, dropletID) + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(dropletsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return root.Droplets, resp, err +} + +func (s *DropletsServiceOp) dropletActionStatus(uri string) (string, error) { + action, _, err := s.client.DropletActions.GetByURI(uri) + + if err != nil { + return "", err + } + + return action.Status, nil +} diff --git a/vendor/github.com/digitalocean/godo/errors.go b/vendor/github.com/digitalocean/godo/errors.go new file mode 100644 index 000000000..a65ebd76b --- /dev/null +++ b/vendor/github.com/digitalocean/godo/errors.go @@ -0,0 +1,24 @@ +package godo + +import "fmt" + +// ArgError is an error that represents an error with an input to godo. It +// identifies the argument and the cause (if possible). +type ArgError struct { + arg string + reason string +} + +var _ error = &ArgError{} + +// NewArgError creates an InputError. +func NewArgError(arg, reason string) *ArgError { + return &ArgError{ + arg: arg, + reason: reason, + } +} + +func (e *ArgError) Error() string { + return fmt.Sprintf("%s is invalid because %s", e.arg, e.reason) +} diff --git a/vendor/github.com/digitalocean/godo/floating_ips.go b/vendor/github.com/digitalocean/godo/floating_ips.go new file mode 100644 index 000000000..bad04b96c --- /dev/null +++ b/vendor/github.com/digitalocean/godo/floating_ips.go @@ -0,0 +1,131 @@ +package godo + +import "fmt" + +const floatingBasePath = "v2/floating_ips" + +// FloatingIPsService is an interface for interfacing with the floating IPs +// endpoints of the Digital Ocean API. +// See: https://developers.digitalocean.com/documentation/v2#floating-ips +type FloatingIPsService interface { + List(*ListOptions) ([]FloatingIP, *Response, error) + Get(string) (*FloatingIP, *Response, error) + Create(*FloatingIPCreateRequest) (*FloatingIP, *Response, error) + Delete(string) (*Response, error) +} + +// FloatingIPsServiceOp handles communication with the floating IPs related methods of the +// DigitalOcean API. +type FloatingIPsServiceOp struct { + client *Client +} + +var _ FloatingIPsService = &FloatingIPsServiceOp{} + +// FloatingIP represents a Digital Ocean floating IP. +type FloatingIP struct { + Region *Region `json:"region"` + Droplet *Droplet `json:"droplet"` + IP string `json:"ip"` +} + +func (f FloatingIP) String() string { + return Stringify(f) +} + +type floatingIPsRoot struct { + FloatingIPs []FloatingIP `json:"floating_ips"` + Links *Links `json:"links"` +} + +type floatingIPRoot struct { + FloatingIP *FloatingIP `json:"floating_ip"` + Links *Links `json:"links,omitempty"` +} + +// FloatingIPCreateRequest represents a request to create a floating IP. +// If DropletID is not empty, the floating IP will be assigned to the +// droplet. +type FloatingIPCreateRequest struct { + Region string `json:"region"` + DropletID int `json:"droplet_id,omitempty"` +} + +// List all floating IPs. +func (f *FloatingIPsServiceOp) List(opt *ListOptions) ([]FloatingIP, *Response, error) { + path := floatingBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := f.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(floatingIPsRoot) + resp, err := f.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.FloatingIPs, resp, err +} + +// Get an individual floating IP. +func (f *FloatingIPsServiceOp) Get(ip string) (*FloatingIP, *Response, error) { + path := fmt.Sprintf("%s/%s", floatingBasePath, ip) + + req, err := f.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(floatingIPRoot) + resp, err := f.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return root.FloatingIP, resp, err +} + +// Create a floating IP. If the DropletID field of the request is not empty, +// the floating IP will also be assigned to the droplet. +func (f *FloatingIPsServiceOp) Create(createRequest *FloatingIPCreateRequest) (*FloatingIP, *Response, error) { + path := floatingBasePath + + req, err := f.client.NewRequest("POST", path, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(floatingIPRoot) + resp, err := f.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.FloatingIP, resp, err +} + +// Delete a floating IP. +func (f *FloatingIPsServiceOp) Delete(ip string) (*Response, error) { + path := fmt.Sprintf("%s/%s", floatingBasePath, ip) + + req, err := f.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := f.client.Do(req, nil) + + return resp, err +} diff --git a/vendor/github.com/digitalocean/godo/floating_ips_actions.go b/vendor/github.com/digitalocean/godo/floating_ips_actions.go new file mode 100644 index 000000000..f435384eb --- /dev/null +++ b/vendor/github.com/digitalocean/godo/floating_ips_actions.go @@ -0,0 +1,105 @@ +package godo + +import "fmt" + +// FloatingIPActionsService is an interface for interfacing with the +// floating IPs actions endpoints of the Digital Ocean API. +// See: https://developers.digitalocean.com/documentation/v2#floating-ips-action +type FloatingIPActionsService interface { + Assign(ip string, dropletID int) (*Action, *Response, error) + Unassign(ip string) (*Action, *Response, error) + Get(ip string, actionID int) (*Action, *Response, error) + List(ip string, opt *ListOptions) ([]Action, *Response, error) +} + +// FloatingIPActionsServiceOp handles communication with the floating IPs +// action related methods of the DigitalOcean API. +type FloatingIPActionsServiceOp struct { + client *Client +} + +// Assign a floating IP to a droplet. +func (s *FloatingIPActionsServiceOp) Assign(ip string, dropletID int) (*Action, *Response, error) { + request := &ActionRequest{ + "type": "assign", + "droplet_id": dropletID, + } + return s.doAction(ip, request) +} + +// Unassign a floating IP from the droplet it is currently assigned to. +func (s *FloatingIPActionsServiceOp) Unassign(ip string) (*Action, *Response, error) { + request := &ActionRequest{"type": "unassign"} + return s.doAction(ip, request) +} + +// Get an action for a particular floating IP by id. +func (s *FloatingIPActionsServiceOp) Get(ip string, actionID int) (*Action, *Response, error) { + path := fmt.Sprintf("%s/%d", floatingIPActionPath(ip), actionID) + return s.get(path) +} + +// List the actions for a particular floating IP. +func (s *FloatingIPActionsServiceOp) List(ip string, opt *ListOptions) ([]Action, *Response, error) { + path := floatingIPActionPath(ip) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + return s.list(path) +} + +func (s *FloatingIPActionsServiceOp) doAction(ip string, request *ActionRequest) (*Action, *Response, error) { + path := floatingIPActionPath(ip) + + req, err := s.client.NewRequest("POST", path, request) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} + +func (s *FloatingIPActionsServiceOp) get(path string) (*Action, *Response, error) { + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} + +func (s *FloatingIPActionsServiceOp) list(path string) ([]Action, *Response, error) { + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Actions, resp, err +} + +func floatingIPActionPath(ip string) string { + return fmt.Sprintf("%s/%s/actions", floatingBasePath, ip) +} diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go new file mode 100644 index 000000000..47d61391f --- /dev/null +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -0,0 +1,341 @@ +package godo + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "strconv" + "time" + + "github.com/google/go-querystring/query" + headerLink "github.com/tent/http-link-go" +) + +const ( + libraryVersion = "0.1.0" + defaultBaseURL = "https://api.digitalocean.com/" + userAgent = "godo/" + libraryVersion + mediaType = "application/json" + + headerRateLimit = "RateLimit-Limit" + headerRateRemaining = "RateLimit-Remaining" + headerRateReset = "RateLimit-Reset" +) + +// Client manages communication with DigitalOcean V2 API. +type Client struct { + // HTTP client used to communicate with the DO API. + client *http.Client + + // Base URL for API requests. + BaseURL *url.URL + + // User agent for client + UserAgent string + + // Rate contains the current rate limit for the client as determined by the most recent + // API call. + Rate Rate + + // Services used for communicating with the API + Account AccountService + Actions ActionsService + Domains DomainsService + Droplets DropletsService + DropletActions DropletActionsService + Images ImagesService + ImageActions ImageActionsService + Keys KeysService + Regions RegionsService + Sizes SizesService + FloatingIPs FloatingIPsService + FloatingIPActions FloatingIPActionsService + + // Optional function called after every successful request made to the DO APIs + onRequestCompleted RequestCompletionCallback +} + +// RequestCompletionCallback defines the type of the request callback function +type RequestCompletionCallback func(*http.Request, *http.Response) + +// ListOptions specifies the optional parameters to various List methods that +// support pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` +} + +// Response is a DigitalOcean response. This wraps the standard http.Response returned from DigitalOcean. +type Response struct { + *http.Response + + // Links that were returned with the response. These are parsed from + // request body and not the header. + Links *Links + + // Monitoring URI + Monitor string + + Rate +} + +// An ErrorResponse reports the error caused by an API request +type ErrorResponse struct { + // HTTP response that caused this error + Response *http.Response + + // Error message + Message string +} + +// Rate contains the rate limit for the current client. +type Rate struct { + // The number of request per hour the client is currently limited to. + Limit int `json:"limit"` + + // The number of remaining requests the client can make this hour. + Remaining int `json:"remaining"` + + // The time at which the current rate limit will reset. + Reset Timestamp `json:"reset"` +} + +func addOptions(s string, opt interface{}) (string, error) { + v := reflect.ValueOf(opt) + + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + origURL, err := url.Parse(s) + if err != nil { + return s, err + } + + origValues := origURL.Query() + + newValues, err := query.Values(opt) + if err != nil { + return s, err + } + + for k, v := range newValues { + origValues[k] = v + } + + origURL.RawQuery = origValues.Encode() + return origURL.String(), nil +} + +// NewClient returns a new DigitalOcean API client. +func NewClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = http.DefaultClient + } + + baseURL, _ := url.Parse(defaultBaseURL) + + c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent} + c.Account = &AccountServiceOp{client: c} + c.Actions = &ActionsServiceOp{client: c} + c.Domains = &DomainsServiceOp{client: c} + c.Droplets = &DropletsServiceOp{client: c} + c.DropletActions = &DropletActionsServiceOp{client: c} + c.Images = &ImagesServiceOp{client: c} + c.ImageActions = &ImageActionsServiceOp{client: c} + c.Keys = &KeysServiceOp{client: c} + c.Regions = &RegionsServiceOp{client: c} + c.Sizes = &SizesServiceOp{client: c} + c.FloatingIPs = &FloatingIPsServiceOp{client: c} + c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c} + + return c +} + +// NewRequest creates an API request. A relative URL can be provided in urlStr, which will be resolved to the +// BaseURL of the Client. Relative URLS should always be specified without a preceding slash. If specified, the +// value pointed to by body is JSON encoded and included in as the request body. +func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { + rel, err := url.Parse(urlStr) + if err != nil { + return nil, err + } + + u := c.BaseURL.ResolveReference(rel) + + buf := new(bytes.Buffer) + if body != nil { + err := json.NewEncoder(buf).Encode(body) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, u.String(), buf) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", mediaType) + req.Header.Add("Accept", mediaType) + req.Header.Add("User-Agent", userAgent) + return req, nil +} + +// OnRequestCompleted sets the DO API request completion callback +func (c *Client) OnRequestCompleted(rc RequestCompletionCallback) { + c.onRequestCompleted = rc +} + +// newResponse creates a new Response for the provided http.Response +func newResponse(r *http.Response) *Response { + response := Response{Response: r} + response.populateRate() + + return &response +} + +func (r *Response) links() (map[string]headerLink.Link, error) { + if linkText, ok := r.Response.Header["Link"]; ok { + links, err := headerLink.Parse(linkText[0]) + + if err != nil { + return nil, err + } + + linkMap := map[string]headerLink.Link{} + for _, link := range links { + linkMap[link.Rel] = link + } + + return linkMap, nil + } + + return map[string]headerLink.Link{}, nil +} + +// populateRate parses the rate related headers and populates the response Rate. +func (r *Response) populateRate() { + if limit := r.Header.Get(headerRateLimit); limit != "" { + r.Rate.Limit, _ = strconv.Atoi(limit) + } + if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + r.Rate.Remaining, _ = strconv.Atoi(remaining) + } + if reset := r.Header.Get(headerRateReset); reset != "" { + if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { + r.Rate.Reset = Timestamp{time.Unix(v, 0)} + } + } +} + +// Do sends an API request and returns the API response. The API response is JSON decoded and stored in the value +// pointed to by v, or returned as an error if an API error has occurred. If v implements the io.Writer interface, +// the raw response will be written to v, without attempting to decode it. +func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) { + resp, err := c.client.Do(req) + if err != nil { + return nil, err + } + if c.onRequestCompleted != nil { + c.onRequestCompleted(req, resp) + } + + defer func() { + if rerr := resp.Body.Close(); err == nil { + err = rerr + } + }() + + response := newResponse(resp) + c.Rate = response.Rate + + err = CheckResponse(resp) + if err != nil { + return response, err + } + + if v != nil { + if w, ok := v.(io.Writer); ok { + _, err := io.Copy(w, resp.Body) + if err != nil { + return nil, err + } + } else { + err := json.NewDecoder(resp.Body).Decode(v) + if err != nil { + return nil, err + } + } + } + + return response, err +} +func (r *ErrorResponse) Error() string { + return fmt.Sprintf("%v %v: %d %v", + r.Response.Request.Method, r.Response.Request.URL, r.Response.StatusCode, r.Message) +} + +// CheckResponse checks the API response for errors, and returns them if present. A response is considered an +// error if it has a status code outside the 200 range. API error responses are expected to have either no response +// body, or a JSON response body that maps to ErrorResponse. Any other response body will be silently ignored. +func CheckResponse(r *http.Response) error { + if c := r.StatusCode; c >= 200 && c <= 299 { + return nil + } + + errorResponse := &ErrorResponse{Response: r} + data, err := ioutil.ReadAll(r.Body) + if err == nil && len(data) > 0 { + err := json.Unmarshal(data, errorResponse) + if err != nil { + return err + } + } + + return errorResponse +} + +func (r Rate) String() string { + return Stringify(r) +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + p := new(string) + *p = v + return p +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int { + p := new(int) + *p = v + return p +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + p := new(bool) + *p = v + return p +} + +// StreamToString converts a reader to a string +func StreamToString(stream io.Reader) string { + buf := new(bytes.Buffer) + _, _ = buf.ReadFrom(stream) + return buf.String() +} diff --git a/vendor/github.com/digitalocean/godo/image_actions.go b/vendor/github.com/digitalocean/godo/image_actions.go new file mode 100644 index 000000000..2d0538567 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/image_actions.go @@ -0,0 +1,71 @@ +package godo + +import "fmt" + +// ImageActionsService is an interface for interfacing with the image actions +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#image-actions +type ImageActionsService interface { + Get(int, int) (*Action, *Response, error) + Transfer(int, *ActionRequest) (*Action, *Response, error) +} + +// ImageActionsServiceOp handles communition with the image action related methods of the +// DigitalOcean API. +type ImageActionsServiceOp struct { + client *Client +} + +var _ ImageActionsService = &ImageActionsServiceOp{} + +// Transfer an image +func (i *ImageActionsServiceOp) Transfer(imageID int, transferRequest *ActionRequest) (*Action, *Response, error) { + if imageID < 1 { + return nil, nil, NewArgError("imageID", "cannot be less than 1") + } + + if transferRequest == nil { + return nil, nil, NewArgError("transferRequest", "cannot be nil") + } + + path := fmt.Sprintf("v2/images/%d/actions", imageID) + + req, err := i.client.NewRequest("POST", path, transferRequest) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := i.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} + +// Get an action for a particular image by id. +func (i *ImageActionsServiceOp) Get(imageID, actionID int) (*Action, *Response, error) { + if imageID < 1 { + return nil, nil, NewArgError("imageID", "cannot be less than 1") + } + + if actionID < 1 { + return nil, nil, NewArgError("actionID", "cannot be less than 1") + } + + path := fmt.Sprintf("v2/images/%d/actions/%d", imageID, actionID) + + req, err := i.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := i.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Event, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/images.go b/vendor/github.com/digitalocean/godo/images.go new file mode 100644 index 000000000..96894f886 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/images.go @@ -0,0 +1,194 @@ +package godo + +import "fmt" + +const imageBasePath = "v2/images" + +// ImagesService is an interface for interfacing with the images +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#images +type ImagesService interface { + List(*ListOptions) ([]Image, *Response, error) + ListDistribution(opt *ListOptions) ([]Image, *Response, error) + ListApplication(opt *ListOptions) ([]Image, *Response, error) + ListUser(opt *ListOptions) ([]Image, *Response, error) + GetByID(int) (*Image, *Response, error) + GetBySlug(string) (*Image, *Response, error) + Update(int, *ImageUpdateRequest) (*Image, *Response, error) + Delete(int) (*Response, error) +} + +// ImagesServiceOp handles communication with the image related methods of the +// DigitalOcean API. +type ImagesServiceOp struct { + client *Client +} + +var _ ImagesService = &ImagesServiceOp{} + +// Image represents a DigitalOcean Image +type Image struct { + ID int `json:"id,float64,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Distribution string `json:"distribution,omitempty"` + Slug string `json:"slug,omitempty"` + Public bool `json:"public,omitempty"` + Regions []string `json:"regions,omitempty"` + MinDiskSize int `json:"min_disk_size,omitempty"` + Created string `json:"created_at,omitempty"` +} + +// ImageUpdateRequest represents a request to update an image. +type ImageUpdateRequest struct { + Name string `json:"name"` +} + +type imageRoot struct { + Image Image +} + +type imagesRoot struct { + Images []Image + Links *Links `json:"links"` +} + +type listImageOptions struct { + Private bool `url:"private,omitempty"` + Type string `url:"type,omitempty"` +} + +func (i Image) String() string { + return Stringify(i) +} + +// List lists all the images available. +func (s *ImagesServiceOp) List(opt *ListOptions) ([]Image, *Response, error) { + return s.list(opt, nil) +} + +// ListDistribution lists all the distribution images. +func (s *ImagesServiceOp) ListDistribution(opt *ListOptions) ([]Image, *Response, error) { + listOpt := listImageOptions{Type: "distribution"} + return s.list(opt, &listOpt) +} + +// ListApplication lists all the application images. +func (s *ImagesServiceOp) ListApplication(opt *ListOptions) ([]Image, *Response, error) { + listOpt := listImageOptions{Type: "application"} + return s.list(opt, &listOpt) +} + +// ListUser lists all the user images. +func (s *ImagesServiceOp) ListUser(opt *ListOptions) ([]Image, *Response, error) { + listOpt := listImageOptions{Private: true} + return s.list(opt, &listOpt) +} + +// GetByID retrieves an image by id. +func (s *ImagesServiceOp) GetByID(imageID int) (*Image, *Response, error) { + if imageID < 1 { + return nil, nil, NewArgError("imageID", "cannot be less than 1") + } + + return s.get(interface{}(imageID)) +} + +// GetBySlug retrieves an image by slug. +func (s *ImagesServiceOp) GetBySlug(slug string) (*Image, *Response, error) { + if len(slug) < 1 { + return nil, nil, NewArgError("slug", "cannot be blank") + } + + return s.get(interface{}(slug)) +} + +// Update an image name. +func (s *ImagesServiceOp) Update(imageID int, updateRequest *ImageUpdateRequest) (*Image, *Response, error) { + if imageID < 1 { + return nil, nil, NewArgError("imageID", "cannot be less than 1") + } + + if updateRequest == nil { + return nil, nil, NewArgError("updateRequest", "cannot be nil") + } + + path := fmt.Sprintf("%s/%d", imageBasePath, imageID) + req, err := s.client.NewRequest("PUT", path, updateRequest) + if err != nil { + return nil, nil, err + } + + root := new(imageRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Image, resp, err +} + +// Delete an image. +func (s *ImagesServiceOp) Delete(imageID int) (*Response, error) { + if imageID < 1 { + return nil, NewArgError("imageID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", imageBasePath, imageID) + + req, err := s.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + + return resp, err +} + +// Helper method for getting an individual image +func (s *ImagesServiceOp) get(ID interface{}) (*Image, *Response, error) { + path := fmt.Sprintf("%s/%v", imageBasePath, ID) + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(imageRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.Image, resp, err +} + +// Helper method for listing images +func (s *ImagesServiceOp) list(opt *ListOptions, listOpt *listImageOptions) ([]Image, *Response, error) { + path := imageBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + path, err = addOptions(path, listOpt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(imagesRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Images, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/keys.go b/vendor/github.com/digitalocean/godo/keys.go new file mode 100644 index 000000000..8dc50f8a0 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/keys.go @@ -0,0 +1,222 @@ +package godo + +import "fmt" + +const keysBasePath = "v2/account/keys" + +// KeysService is an interface for interfacing with the keys +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#keys +type KeysService interface { + List(*ListOptions) ([]Key, *Response, error) + GetByID(int) (*Key, *Response, error) + GetByFingerprint(string) (*Key, *Response, error) + Create(*KeyCreateRequest) (*Key, *Response, error) + UpdateByID(int, *KeyUpdateRequest) (*Key, *Response, error) + UpdateByFingerprint(string, *KeyUpdateRequest) (*Key, *Response, error) + DeleteByID(int) (*Response, error) + DeleteByFingerprint(string) (*Response, error) +} + +// KeysServiceOp handles communication with key related method of the +// DigitalOcean API. +type KeysServiceOp struct { + client *Client +} + +var _ KeysService = &KeysServiceOp{} + +// Key represents a DigitalOcean Key. +type Key struct { + ID int `json:"id,float64,omitempty"` + Name string `json:"name,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + PublicKey string `json:"public_key,omitempty"` +} + +// KeyUpdateRequest represents a request to update a DigitalOcean key. +type KeyUpdateRequest struct { + Name string `json:"name"` +} + +type keysRoot struct { + SSHKeys []Key `json:"ssh_keys"` + Links *Links `json:"links"` +} + +type keyRoot struct { + SSHKey Key `json:"ssh_key"` +} + +func (s Key) String() string { + return Stringify(s) +} + +// KeyCreateRequest represents a request to create a new key. +type KeyCreateRequest struct { + Name string `json:"name"` + PublicKey string `json:"public_key"` +} + +// List all keys +func (s *KeysServiceOp) List(opt *ListOptions) ([]Key, *Response, error) { + path := keysBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(keysRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.SSHKeys, resp, err +} + +// Performs a get given a path +func (s *KeysServiceOp) get(path string) (*Key, *Response, error) { + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(keyRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.SSHKey, resp, err +} + +// GetByID gets a Key by id +func (s *KeysServiceOp) GetByID(keyID int) (*Key, *Response, error) { + if keyID < 1 { + return nil, nil, NewArgError("keyID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", keysBasePath, keyID) + return s.get(path) +} + +// GetByFingerprint gets a Key by by fingerprint +func (s *KeysServiceOp) GetByFingerprint(fingerprint string) (*Key, *Response, error) { + if len(fingerprint) < 1 { + return nil, nil, NewArgError("fingerprint", "cannot not be empty") + } + + path := fmt.Sprintf("%s/%s", keysBasePath, fingerprint) + return s.get(path) +} + +// Create a key using a KeyCreateRequest +func (s *KeysServiceOp) Create(createRequest *KeyCreateRequest) (*Key, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + req, err := s.client.NewRequest("POST", keysBasePath, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(keyRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.SSHKey, resp, err +} + +// UpdateByID updates a key name by ID. +func (s *KeysServiceOp) UpdateByID(keyID int, updateRequest *KeyUpdateRequest) (*Key, *Response, error) { + if keyID < 1 { + return nil, nil, NewArgError("keyID", "cannot be less than 1") + } + + if updateRequest == nil { + return nil, nil, NewArgError("updateRequest", "cannot be nil") + } + + path := fmt.Sprintf("%s/%d", keysBasePath, keyID) + req, err := s.client.NewRequest("PUT", path, updateRequest) + if err != nil { + return nil, nil, err + } + + root := new(keyRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.SSHKey, resp, err +} + +// UpdateByFingerprint updates a key name by fingerprint. +func (s *KeysServiceOp) UpdateByFingerprint(fingerprint string, updateRequest *KeyUpdateRequest) (*Key, *Response, error) { + if len(fingerprint) < 1 { + return nil, nil, NewArgError("fingerprint", "cannot be empty") + } + + if updateRequest == nil { + return nil, nil, NewArgError("updateRequest", "cannot be nil") + } + + path := fmt.Sprintf("%s/%s", keysBasePath, fingerprint) + req, err := s.client.NewRequest("PUT", path, updateRequest) + if err != nil { + return nil, nil, err + } + + root := new(keyRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + + return &root.SSHKey, resp, err +} + +// Delete key using a path +func (s *KeysServiceOp) delete(path string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + + return resp, err +} + +// DeleteByID deletes a key by its id +func (s *KeysServiceOp) DeleteByID(keyID int) (*Response, error) { + if keyID < 1 { + return nil, NewArgError("keyID", "cannot be less than 1") + } + + path := fmt.Sprintf("%s/%d", keysBasePath, keyID) + return s.delete(path) +} + +// DeleteByFingerprint deletes a key by its fingerprint +func (s *KeysServiceOp) DeleteByFingerprint(fingerprint string) (*Response, error) { + if len(fingerprint) < 1 { + return nil, NewArgError("fingerprint", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", keysBasePath, fingerprint) + return s.delete(path) +} diff --git a/vendor/github.com/digitalocean/godo/links.go b/vendor/github.com/digitalocean/godo/links.go new file mode 100644 index 000000000..463510523 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/links.go @@ -0,0 +1,86 @@ +package godo + +import ( + "net/url" + "strconv" +) + +// Links manages links that are returned along with a List +type Links struct { + Pages *Pages `json:"pages,omitempty"` + Actions []LinkAction `json:"actions,omitempty"` +} + +// Pages are pages specified in Links +type Pages struct { + First string `json:"first,omitempty"` + Prev string `json:"prev,omitempty"` + Last string `json:"last,omitempty"` + Next string `json:"next,omitempty"` +} + +// LinkAction is a pointer to an action +type LinkAction struct { + ID int `json:"id,omitempty"` + Rel string `json:"rel,omitempty"` + HREF string `json:"href,omitempty"` +} + +// CurrentPage is current page of the list +func (l *Links) CurrentPage() (int, error) { + return l.Pages.current() +} + +func (p *Pages) current() (int, error) { + switch { + case p == nil: + return 1, nil + case p.Prev == "" && p.Next != "": + return 1, nil + case p.Prev != "": + prevPage, err := pageForURL(p.Prev) + if err != nil { + return 0, err + } + + return prevPage + 1, nil + } + + return 0, nil +} + +// IsLastPage returns true if the current page is the last +func (l *Links) IsLastPage() bool { + if l.Pages == nil { + return true + } + return l.Pages.isLast() +} + +func (p *Pages) isLast() bool { + if p.Last == "" { + return true + } + + return false +} + +func pageForURL(urlText string) (int, error) { + u, err := url.ParseRequestURI(urlText) + if err != nil { + return 0, err + } + + pageStr := u.Query().Get("page") + page, err := strconv.Atoi(pageStr) + if err != nil { + return 0, err + } + + return page, nil +} + +// Get a link action by id. +func (la *LinkAction) Get(client *Client) (*Action, *Response, error) { + return client.Actions.Get(la.ID) +} diff --git a/vendor/github.com/digitalocean/godo/regions.go b/vendor/github.com/digitalocean/godo/regions.go new file mode 100644 index 000000000..e44e8bcd6 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/regions.go @@ -0,0 +1,63 @@ +package godo + +// RegionsService is an interface for interfacing with the regions +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#regions +type RegionsService interface { + List(*ListOptions) ([]Region, *Response, error) +} + +// RegionsServiceOp handles communication with the region related methods of the +// DigitalOcean API. +type RegionsServiceOp struct { + client *Client +} + +var _ RegionsService = &RegionsServiceOp{} + +// Region represents a DigitalOcean Region +type Region struct { + Slug string `json:"slug,omitempty"` + Name string `json:"name,omitempty"` + Sizes []string `json:"sizes,omitempty"` + Available bool `json:"available,omitempty"` + Features []string `json:"features,omitempty"` +} + +type regionsRoot struct { + Regions []Region + Links *Links `json:"links"` +} + +type regionRoot struct { + Region Region +} + +func (r Region) String() string { + return Stringify(r) +} + +// List all regions +func (s *RegionsServiceOp) List(opt *ListOptions) ([]Region, *Response, error) { + path := "v2/regions" + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(regionsRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Regions, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/sizes.go b/vendor/github.com/digitalocean/godo/sizes.go new file mode 100644 index 000000000..7f454e7eb --- /dev/null +++ b/vendor/github.com/digitalocean/godo/sizes.go @@ -0,0 +1,63 @@ +package godo + +// SizesService is an interface for interfacing with the size +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2#sizes +type SizesService interface { + List(*ListOptions) ([]Size, *Response, error) +} + +// SizesServiceOp handles communication with the size related methods of the +// DigitalOcean API. +type SizesServiceOp struct { + client *Client +} + +var _ SizesService = &SizesServiceOp{} + +// Size represents a DigitalOcean Size +type Size struct { + Slug string `json:"slug,omitempty"` + Memory int `json:"memory,omitempty"` + Vcpus int `json:"vcpus,omitempty"` + Disk int `json:"disk,omitempty"` + PriceMonthly float64 `json:"price_monthly,omitempty"` + PriceHourly float64 `json:"price_hourly,omitempty"` + Regions []string `json:"regions,omitempty"` + Available bool `json:"available,omitempty"` + Transfer float64 `json:"transfer,omitempty"` +} + +func (s Size) String() string { + return Stringify(s) +} + +type sizesRoot struct { + Sizes []Size + Links *Links `json:"links"` +} + +// List all images +func (s *SizesServiceOp) List(opt *ListOptions) ([]Size, *Response, error) { + path := "v2/sizes" + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", path, nil) + if err != nil { + return nil, nil, err + } + + root := new(sizesRoot) + resp, err := s.client.Do(req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + + return root.Sizes, resp, err +} diff --git a/vendor/github.com/digitalocean/godo/strings.go b/vendor/github.com/digitalocean/godo/strings.go new file mode 100644 index 000000000..bbdbc9241 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/strings.go @@ -0,0 +1,83 @@ +package godo + +import ( + "bytes" + "fmt" + "reflect" +) + +var timestampType = reflect.TypeOf(Timestamp{}) + +// Stringify attempts to create a string representation of DigitalOcean types +func Stringify(message interface{}) string { + var buf bytes.Buffer + v := reflect.ValueOf(message) + stringifyValue(&buf, v) + return buf.String() +} + +// stringifyValue was graciously cargoculted from the goprotubuf library +func stringifyValue(w *bytes.Buffer, val reflect.Value) { + if val.Kind() == reflect.Ptr && val.IsNil() { + _, _ = w.Write([]byte("")) + return + } + + v := reflect.Indirect(val) + + switch v.Kind() { + case reflect.String: + fmt.Fprintf(w, `"%s"`, v) + case reflect.Slice: + _, _ = w.Write([]byte{'['}) + for i := 0; i < v.Len(); i++ { + if i > 0 { + _, _ = w.Write([]byte{' '}) + } + + stringifyValue(w, v.Index(i)) + } + + _, _ = w.Write([]byte{']'}) + return + case reflect.Struct: + if v.Type().Name() != "" { + _, _ = w.Write([]byte(v.Type().String())) + } + + // special handling of Timestamp values + if v.Type() == timestampType { + fmt.Fprintf(w, "{%s}", v.Interface()) + return + } + + _, _ = w.Write([]byte{'{'}) + + var sep bool + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + if fv.Kind() == reflect.Ptr && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + continue + } + + if sep { + _, _ = w.Write([]byte(", ")) + } else { + sep = true + } + + _, _ = w.Write([]byte(v.Type().Field(i).Name)) + _, _ = w.Write([]byte{':'}) + stringifyValue(w, fv) + } + + _, _ = w.Write([]byte{'}'}) + default: + if v.CanInterface() { + fmt.Fprint(w, v.Interface()) + } + } +} diff --git a/vendor/github.com/digitalocean/godo/timestamp.go b/vendor/github.com/digitalocean/godo/timestamp.go new file mode 100644 index 000000000..37a28e5f2 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/timestamp.go @@ -0,0 +1,35 @@ +package godo + +import ( + "strconv" + "time" +) + +// Timestamp represents a time that can be unmarshalled from a JSON string +// formatted as either an RFC3339 or Unix timestamp. All +// exported methods of time.Time can be called on Timestamp. +type Timestamp struct { + time.Time +} + +func (t Timestamp) String() string { + return t.Time.String() +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// Time is expected in RFC3339 or Unix format. +func (t *Timestamp) UnmarshalJSON(data []byte) error { + str := string(data) + i, err := strconv.ParseInt(str, 10, 64) + if err == nil { + t.Time = time.Unix(i, 0) + } else { + t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) + } + return err +} + +// Equal reports whether t and u are equal based on time.Equal +func (t Timestamp) Equal(u Timestamp) bool { + return t.Time.Equal(u.Time) +} diff --git a/vendor/github.com/digitalocean/godo/util/droplet.go b/vendor/github.com/digitalocean/godo/util/droplet.go new file mode 100644 index 000000000..4a016bc68 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/util/droplet.go @@ -0,0 +1,47 @@ +package util + +import ( + "fmt" + "time" + + "github.com/digitalocean/godo" +) + +const ( + // activeFailure is the amount of times we can fail before deciding + // the check for active is a total failure. This can help account + // for servers randomly not answering. + activeFailure = 3 +) + +// WaitForActive waits for a droplet to become active +func WaitForActive(client *godo.Client, monitorURI string) error { + if len(monitorURI) == 0 { + return fmt.Errorf("create had no monitor uri") + } + + completed := false + failCount := 0 + for !completed { + action, _, err := client.DropletActions.GetByURI(monitorURI) + + if err != nil { + if failCount <= activeFailure { + failCount++ + continue + } + return err + } + + switch action.Status { + case godo.ActionInProgress: + time.Sleep(5 * time.Second) + case godo.ActionCompleted: + completed = true + default: + return fmt.Errorf("unknown status: [%s]", action.Status) + } + } + + return nil +} diff --git a/vendor/github.com/dylanmei/iso8601/LICENSE b/vendor/github.com/dylanmei/iso8601/LICENSE new file mode 100644 index 000000000..dcabcdc70 --- /dev/null +++ b/vendor/github.com/dylanmei/iso8601/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Dylan Meissner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/dylanmei/iso8601/README.md b/vendor/github.com/dylanmei/iso8601/README.md new file mode 100644 index 000000000..c93b3cf77 --- /dev/null +++ b/vendor/github.com/dylanmei/iso8601/README.md @@ -0,0 +1,9 @@ + +iso 8601 parser and formatter +============================= + +An [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) Go utility. + +- *Time* is not yet implemented +- *Duration* is mostly implemented + diff --git a/vendor/github.com/dylanmei/iso8601/duration.go b/vendor/github.com/dylanmei/iso8601/duration.go new file mode 100644 index 000000000..d5cab17dc --- /dev/null +++ b/vendor/github.com/dylanmei/iso8601/duration.go @@ -0,0 +1,96 @@ +package iso8601 + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "time" +) + +var ( + // ErrBadFormat is returned when parsing fails + ErrBadFormat = errors.New("bad format string") + + // ErrNoMonth is raised when a month is in the format string + ErrNoMonth = errors.New("no months allowed") + + full = regexp.MustCompile(`P((?P\d+)Y)?((?P\d+)M)?((?P\d+)D)?(T((?P\d+)H)?((?P\d+)M)?((?P\d+)S)?)?`) + week = regexp.MustCompile(`P((?P\d+)W)`) +) + +// adapted from https://github.com/BrianHicks/finch/duration +func ParseDuration(value string) (time.Duration, error) { + var match []string + var regex *regexp.Regexp + + if week.MatchString(value) { + match = week.FindStringSubmatch(value) + regex = week + } else if full.MatchString(value) { + match = full.FindStringSubmatch(value) + regex = full + } else { + return time.Duration(0), ErrBadFormat + } + + d := time.Duration(0) + day := time.Hour * 24 + week := day * 7 + year := day * 365 + + for i, name := range regex.SubexpNames() { + part := match[i] + if i == 0 || name == "" || part == "" { + continue + } + + value, err := strconv.Atoi(part) + if err != nil { + return time.Duration(0), err + } + switch name { + case "year": + d += year * time.Duration(value) + case "month": + return time.Duration(0), ErrNoMonth + case "week": + d += week * time.Duration(value) + case "day": + d += day * time.Duration(value) + case "hour": + d += time.Hour * time.Duration(value) + case "minute": + d += time.Minute * time.Duration(value) + case "second": + d += time.Second * time.Duration(value) + } + } + + return d, nil +} + +func FormatDuration(duration time.Duration) string { + // we're not doing negative durations + if duration.Seconds() <= 0 { + return "PT0S" + } + + hours := int(duration.Hours()) + minutes := int(duration.Minutes()) - (hours * 60) + seconds := int(duration.Seconds()) - (hours*3600 + minutes*60) + + // we're not doing Y,M,W + s := "PT" + if hours > 0 { + s = fmt.Sprintf("%s%dH", s, hours) + } + if minutes > 0 { + s = fmt.Sprintf("%s%dM", s, minutes) + } + if seconds > 0 { + s = fmt.Sprintf("%s%dS", s, seconds) + } + + return s +} diff --git a/vendor/github.com/dylanmei/winrmtest/LICENSE b/vendor/github.com/dylanmei/winrmtest/LICENSE new file mode 100644 index 000000000..aac5c68e7 --- /dev/null +++ b/vendor/github.com/dylanmei/winrmtest/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014-2015 Dylan Meissner + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/dylanmei/winrmtest/README.md b/vendor/github.com/dylanmei/winrmtest/README.md new file mode 100644 index 000000000..19c19609d --- /dev/null +++ b/vendor/github.com/dylanmei/winrmtest/README.md @@ -0,0 +1,48 @@ + +# winrmtest + +An in-progress testing package to compliment the [masterzen/winrm](https://github.com/masterzen/winrm) Go-based winrm library. + +My primary use-case for this is for [dylanmei/packer-communicator-winrm](https://github.com/dylanmei/packer-communicator-winrm), a [Packer](http://packer.io) communicator plugin for interacting with machines using Windows Remote Management. + +## Example Use + +A fictitious "Windows tools" package. + +``` + +package wintools + +import ( + "io" + "testing" + "github.com/dylanmei/winrmtest" +) + +func Test_empty_temp_directory(t *testing.T) { + r := winrmtest.NewRemote() + defer r.Close() + + r.CommandFunc(wimrmtest.MatchText("dir C:\Temp"), func(out, err io.Writer) int { + out.Write([]byte(` Volume in drive C is Windows 2012 R2 + Volume Serial Number is XXXX-XXXX + + Directory of C:\ + +File Not Found`)) + return 0 + }) + + lister := NewDirectoryLister(r.Host, r.Port) + list, _ := lister.TempDirectory() + + if count := len(list.Dirs()); count != 0 { + t.Errorf("Expected 0 directories but found %d.\n", count) + } + + if count := len(list.Files()); count != 0 { + t.Errorf("Expected 0 files but found %d.\n", count) + } +} +``` + diff --git a/vendor/github.com/dylanmei/winrmtest/remote.go b/vendor/github.com/dylanmei/winrmtest/remote.go new file mode 100644 index 000000000..ecc083f79 --- /dev/null +++ b/vendor/github.com/dylanmei/winrmtest/remote.go @@ -0,0 +1,79 @@ +package winrmtest + +import ( + "io" + "net/http" + "net/http/httptest" + "net/url" + "regexp" + "strconv" + "strings" +) + +// Remote respresents a WinRM server +type Remote struct { + Host string + Port int + server *httptest.Server + service *wsman +} + +// NewRemote returns a new initialized Remote +func NewRemote() *Remote { + mux := http.NewServeMux() + srv := httptest.NewServer(mux) + + host, port, _ := splitAddr(srv.URL) + remote := Remote{ + Host: host, + Port: port, + server: srv, + service: &wsman{}, + } + + mux.Handle("/wsman", remote.service) + return &remote +} + +// Close closes the WinRM server +func (r *Remote) Close() { + r.server.Close() +} + +// MatcherFunc respresents a function used to match WinRM commands +type MatcherFunc func(candidate string) bool + +// MatchText return a new MatcherFunc based on text matching +func MatchText(text string) MatcherFunc { + return func(candidate string) bool { + return text == candidate + } +} + +// MatchPattern return a new MatcherFunc based on pattern matching +func MatchPattern(pattern string) MatcherFunc { + r := regexp.MustCompile(pattern) + return func(candidate string) bool { + return r.MatchString(candidate) + } +} + +// CommandFunc respresents a function used to mock WinRM commands +type CommandFunc func(out, err io.Writer) (exitCode int) + +// CommandFunc adds a WinRM command mock function to the WinRM server +func (r *Remote) CommandFunc(m MatcherFunc, f CommandFunc) { + r.service.HandleCommand(m, f) +} + +func splitAddr(addr string) (host string, port int, err error) { + u, err := url.Parse(addr) + if err != nil { + return + } + + split := strings.Split(u.Host, ":") + host = split[0] + port, err = strconv.Atoi(split[1]) + return +} diff --git a/vendor/github.com/dylanmei/winrmtest/wsman.go b/vendor/github.com/dylanmei/winrmtest/wsman.go new file mode 100644 index 000000000..c6d1c247b --- /dev/null +++ b/vendor/github.com/dylanmei/winrmtest/wsman.go @@ -0,0 +1,170 @@ +package winrmtest + +import ( + "bytes" + "encoding/base64" + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/masterzen/winrm/soap" + "github.com/masterzen/xmlpath" + "github.com/satori/go.uuid" +) + +type wsman struct { + commands []*command + identitySeed int +} + +type command struct { + id string + matcher MatcherFunc + handler CommandFunc +} + +func (w *wsman) HandleCommand(m MatcherFunc, f CommandFunc) string { + id := uuid.NewV4().String() + w.commands = append(w.commands, &command{ + id: id, + matcher: m, + handler: f, + }) + + return id +} + +func (w *wsman) CommandByText(cmd string) *command { + for _, c := range w.commands { + if c.matcher(cmd) { + return c + } + } + return nil +} + +func (w *wsman) CommandByID(id string) *command { + for _, c := range w.commands { + if c.id == id { + return c + } + } + return nil +} + +func (w *wsman) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + rw.Header().Add("Content-Type", "application/soap+xml") + + defer r.Body.Close() + env, err := xmlpath.Parse(r.Body) + + if err != nil { + return + } + + action := readAction(env) + switch { + case strings.HasSuffix(action, "transfer/Create"): + // create a new shell + + rw.Write([]byte(` + + 123 + `)) + + case strings.HasSuffix(action, "shell/Command"): + // execute on behalf of the client + text := readCommand(env) + cmd := w.CommandByText(text) + + if cmd == nil { + fmt.Printf("I don't know this command: Command=%s\n", text) + rw.WriteHeader(http.StatusInternalServerError) + return + } + + rw.Write([]byte(fmt.Sprintf(` + + %s + `, cmd.id))) + + case strings.HasSuffix(action, "shell/Receive"): + // client ready to receive the results + + id := readCommandIDFromDesiredStream(env) + cmd := w.CommandByID(id) + + if cmd == nil { + fmt.Printf("I don't know this command: CommandId=%s\n", id) + rw.WriteHeader(http.StatusInternalServerError) + return + } + + stdout := new(bytes.Buffer) + stderr := new(bytes.Buffer) + result := cmd.handler(stdout, stderr) + content := base64.StdEncoding.EncodeToString(stdout.Bytes()) + + rw.Write([]byte(fmt.Sprintf(` + + + %s + + + + %d + + + `, id, content, id, id, result))) + + case strings.HasSuffix(action, "shell/Signal"): + // end of the shell command + rw.WriteHeader(http.StatusOK) + case strings.HasSuffix(action, "transfer/Delete"): + // end of the session + rw.WriteHeader(http.StatusOK) + default: + fmt.Printf("I don't know this action: %s\n", action) + rw.WriteHeader(http.StatusInternalServerError) + } +} + +func readAction(env *xmlpath.Node) string { + xpath, err := xmlpath.CompileWithNamespace( + "//a:Action", soap.GetAllNamespaces()) + + if err != nil { + return "" + } + + action, _ := xpath.String(env) + return action +} + +func readCommand(env *xmlpath.Node) string { + xpath, err := xmlpath.CompileWithNamespace( + "//rsp:Command", soap.GetAllNamespaces()) + + if err != nil { + return "" + } + + command, _ := xpath.String(env) + if unquoted, err := strconv.Unquote(command); err == nil { + return unquoted + } + return command +} + +func readCommandIDFromDesiredStream(env *xmlpath.Node) string { + xpath, err := xmlpath.CompileWithNamespace( + "//rsp:DesiredStream/@CommandId", soap.GetAllNamespaces()) + + if err != nil { + return "" + } + + id, _ := xpath.String(env) + return id +} diff --git a/vendor/github.com/go-ini/ini/.gitignore b/vendor/github.com/go-ini/ini/.gitignore new file mode 100644 index 000000000..7adca9439 --- /dev/null +++ b/vendor/github.com/go-ini/ini/.gitignore @@ -0,0 +1,4 @@ +testdata/conf_out.ini +ini.sublime-project +ini.sublime-workspace +testdata/conf_reflect.ini diff --git a/vendor/github.com/go-ini/ini/LICENSE b/vendor/github.com/go-ini/ini/LICENSE new file mode 100644 index 000000000..37ec93a14 --- /dev/null +++ b/vendor/github.com/go-ini/ini/LICENSE @@ -0,0 +1,191 @@ +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: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +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 +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. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/go-ini/ini/README.md b/vendor/github.com/go-ini/ini/README.md new file mode 100644 index 000000000..c52f63a47 --- /dev/null +++ b/vendor/github.com/go-ini/ini/README.md @@ -0,0 +1,590 @@ +ini [![Build Status](https://drone.io/github.com/go-ini/ini/status.png)](https://drone.io/github.com/go-ini/ini/latest) [![](http://gocover.io/_badge/github.com/go-ini/ini)](http://gocover.io/github.com/go-ini/ini) +=== + +![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200) + +Package ini provides INI file read and write functionality in Go. + +[简体中文](README_ZH.md) + +## Feature + +- Load multiple data sources(`[]byte` or file) with overwrites. +- Read with recursion values. +- Read with parent-child sections. +- Read with auto-increment key names. +- Read with multiple-line values. +- Read with tons of helper methods. +- Read and convert values to Go types. +- Read and **WRITE** comments of sections and keys. +- Manipulate sections, keys and comments with ease. +- Keep sections and keys in order as you parse and save. + +## Installation + +To use a tagged revision: + + go get gopkg.in/ini.v1 + +To use with latest changes: + + go get github.com/go-ini/ini + +### Testing + +If you want to test on your machine, please apply `-t` flag: + + go get -t gopkg.in/ini.v1 + +## Getting Started + +### Loading from data sources + +A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many as** data sources you want. Passing other types will simply return an error. + +```go +cfg, err := ini.Load([]byte("raw data"), "filename") +``` + +Or start with an empty object: + +```go +cfg := ini.Empty() +``` + +When you cannot decide how many data sources to load at the beginning, you still able to **Append()** them later. + +```go +err := cfg.Append("other file", []byte("other raw data")) +``` + +### Working with sections + +To get a section, you would need to: + +```go +section, err := cfg.GetSection("section name") +``` + +For a shortcut for default section, just give an empty string as name: + +```go +section, err := cfg.GetSection("") +``` + +When you're pretty sure the section exists, following code could make your life easier: + +```go +section := cfg.Section("") +``` + +What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you. + +To create a new section: + +```go +err := cfg.NewSection("new section") +``` + +To get a list of sections or section names: + +```go +sections := cfg.Sections() +names := cfg.SectionStrings() +``` + +### Working with keys + +To get a key under a section: + +```go +key, err := cfg.Section("").GetKey("key name") +``` + +Same rule applies to key operations: + +```go +key := cfg.Section("").Key("key name") +``` + +To check if a key exists: + +```go +yes := cfg.Section("").HasKey("key name") +``` + +To create a new key: + +```go +err := cfg.Section("").NewKey("name", "value") +``` + +To get a list of keys or key names: + +```go +keys := cfg.Section("").Keys() +names := cfg.Section("").KeyStrings() +``` + +To get a clone hash of keys and corresponding values: + +```go +hash := cfg.GetSection("").KeysHash() +``` + +### Working with values + +To get a string value: + +```go +val := cfg.Section("").Key("key name").String() +``` + +To validate key value on the fly: + +```go +val := cfg.Section("").Key("key name").Validate(func(in string) string { + if len(in) == 0 { + return "default" + } + return in +}) +``` + +If you do not want any auto-transformation (such as recursive read) for the values, you can get raw value directly (this way you get much better performance): + +```go +val := cfg.Section("").Key("key name").Value() +``` + +To check if raw value exists: + +```go +yes := cfg.Section("").HasValue("test value") +``` + +To get value with types: + +```go +// For boolean values: +// true when value is: 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On +// false when value is: 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off +v, err = cfg.Section("").Key("BOOL").Bool() +v, err = cfg.Section("").Key("FLOAT64").Float64() +v, err = cfg.Section("").Key("INT").Int() +v, err = cfg.Section("").Key("INT64").Int64() +v, err = cfg.Section("").Key("UINT").Uint() +v, err = cfg.Section("").Key("UINT64").Uint64() +v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339) +v, err = cfg.Section("").Key("TIME").Time() // RFC3339 + +v = cfg.Section("").Key("BOOL").MustBool() +v = cfg.Section("").Key("FLOAT64").MustFloat64() +v = cfg.Section("").Key("INT").MustInt() +v = cfg.Section("").Key("INT64").MustInt64() +v = cfg.Section("").Key("UINT").MustUint() +v = cfg.Section("").Key("UINT64").MustUint64() +v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339) +v = cfg.Section("").Key("TIME").MustTime() // RFC3339 + +// Methods start with Must also accept one argument for default value +// when key not found or fail to parse value to given type. +// Except method MustString, which you have to pass a default value. + +v = cfg.Section("").Key("String").MustString("default") +v = cfg.Section("").Key("BOOL").MustBool(true) +v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25) +v = cfg.Section("").Key("INT").MustInt(10) +v = cfg.Section("").Key("INT64").MustInt64(99) +v = cfg.Section("").Key("UINT").MustUint(3) +v = cfg.Section("").Key("UINT64").MustUint64(6) +v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now()) +v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339 +``` + +What if my value is three-line long? + +```ini +[advance] +ADDRESS = """404 road, +NotFound, State, 5000 +Earth""" +``` + +Not a problem! + +```go +cfg.Section("advance").Key("ADDRESS").String() + +/* --- start --- +404 road, +NotFound, State, 5000 +Earth +------ end --- */ +``` + +That's cool, how about continuation lines? + +```ini +[advance] +two_lines = how about \ + continuation lines? +lots_of_lines = 1 \ + 2 \ + 3 \ + 4 +``` + +Piece of cake! + +```go +cfg.Section("advance").Key("two_lines").String() // how about continuation lines? +cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4 +``` + +Note that single quotes around values will be stripped: + +```ini +foo = "some value" // foo: some value +bar = 'some value' // bar: some value +``` + +That's all? Hmm, no. + +#### Helper methods of working with values + +To get value with given candidates: + +```go +v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"}) +v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75}) +v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30}) +v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30}) +v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9}) +v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9}) +v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3}) +v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339 +``` + +Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates. + +To validate value in a given range: + +```go +vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2) +vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20) +vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20) +vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9) +vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9) +vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime) +vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339 +``` + +To auto-split value into slice: + +```go +vals = cfg.Section("").Key("STRINGS").Strings(",") +vals = cfg.Section("").Key("FLOAT64S").Float64s(",") +vals = cfg.Section("").Key("INTS").Ints(",") +vals = cfg.Section("").Key("INT64S").Int64s(",") +vals = cfg.Section("").Key("UINTS").Uints(",") +vals = cfg.Section("").Key("UINT64S").Uint64s(",") +vals = cfg.Section("").Key("TIMES").Times(",") +``` + +### Save your configuration + +Finally, it's time to save your configuration to somewhere. + +A typical way to save configuration is writing it to a file: + +```go +// ... +err = cfg.SaveTo("my.ini") +err = cfg.SaveToIndent("my.ini", "\t") +``` + +Another way to save is writing to a `io.Writer` interface: + +```go +// ... +cfg.WriteTo(writer) +cfg.WriteToIndent(writer, "\t") +``` + +## Advanced Usage + +### Recursive Values + +For all value of keys, there is a special syntax `%()s`, where `` is the key name in same section or default section, and `%()s` will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions. + +```ini +NAME = ini + +[author] +NAME = Unknwon +GITHUB = https://github.com/%(NAME)s + +[package] +FULL_NAME = github.com/go-ini/%(NAME)s +``` + +```go +cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon +cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini +``` + +### Parent-child Sections + +You can use `.` in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section. + +```ini +NAME = ini +VERSION = v1 +IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s + +[package] +CLONE_URL = https://%(IMPORT_PATH)s + +[package.sub] +``` + +```go +cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1 +``` + +### Auto-increment Key Names + +If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter. + +```ini +[features] +-: Support read/write comments of keys and sections +-: Support auto-increment of key names +-: Support load multiple files to overwrite key values +``` + +```go +cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"} +``` + +### Map To Struct + +Want more objective way to play with INI? Cool. + +```ini +Name = Unknwon +age = 21 +Male = true +Born = 1993-01-01T20:17:05Z + +[Note] +Content = Hi is a good man! +Cities = HangZhou, Boston +``` + +```go +type Note struct { + Content string + Cities []string +} + +type Person struct { + Name string + Age int `ini:"age"` + Male bool + Born time.Time + Note + Created time.Time `ini:"-"` +} + +func main() { + cfg, err := ini.Load("path/to/ini") + // ... + p := new(Person) + err = cfg.MapTo(p) + // ... + + // Things can be simpler. + err = ini.MapTo(p, "path/to/ini") + // ... + + // Just map a section? Fine. + n := new(Note) + err = cfg.Section("Note").MapTo(n) + // ... +} +``` + +Can I have default value for field? Absolutely. + +Assign it before you map to struct. It will keep the value as it is if the key is not presented or got wrong type. + +```go +// ... +p := &Person{ + Name: "Joe", +} +// ... +``` + +It's really cool, but what's the point if you can't give me my file back from struct? + +### Reflect From Struct + +Why not? + +```go +type Embeded struct { + Dates []time.Time `delim:"|"` + Places []string + None []int +} + +type Author struct { + Name string `ini:"NAME"` + Male bool + Age int + GPA float64 + NeverMind string `ini:"-"` + *Embeded +} + +func main() { + a := &Author{"Unknwon", true, 21, 2.8, "", + &Embeded{ + []time.Time{time.Now(), time.Now()}, + []string{"HangZhou", "Boston"}, + []int{}, + }} + cfg := ini.Empty() + err = ini.ReflectFrom(cfg, a) + // ... +} +``` + +So, what do I get? + +```ini +NAME = Unknwon +Male = true +Age = 21 +GPA = 2.8 + +[Embeded] +Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 +Places = HangZhou,Boston +None = +``` + +#### Name Mapper + +To save your time and make your code cleaner, this library supports [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) between struct field and actual section and key name. + +There are 2 built-in name mappers: + +- `AllCapsUnderscore`: it converts to format `ALL_CAPS_UNDERSCORE` then match section or key. +- `TitleUnderscore`: it converts to format `title_underscore` then match section or key. + +To use them: + +```go +type Info struct { + PackageName string +} + +func main() { + err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini")) + // ... + + cfg, err := ini.Load([]byte("PACKAGE_NAME=ini")) + // ... + info := new(Info) + cfg.NameMapper = ini.AllCapsUnderscore + err = cfg.MapTo(info) + // ... +} +``` + +Same rules of name mapper apply to `ini.ReflectFromWithMapper` function. + +#### Other Notes On Map/Reflect + +Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature: + +```go +type Child struct { + Age string +} + +type Parent struct { + Name string + Child +} + +type Config struct { + City string + Parent +} +``` + +Example configuration: + +```ini +City = Boston + +[Parent] +Name = Unknwon + +[Child] +Age = 21 +``` + +What if, yes, I'm paranoid, I want embedded struct to be in the same section. Well, all roads lead to Rome. + +```go +type Child struct { + Age string +} + +type Parent struct { + Name string + Child `ini:"Parent"` +} + +type Config struct { + City string + Parent +} +``` + +Example configuration: + +```ini +City = Boston + +[Parent] +Name = Unknwon +Age = 21 +``` + +## Getting Help + +- [API Documentation](https://gowalker.org/gopkg.in/ini.v1) +- [File An Issue](https://github.com/go-ini/ini/issues/new) + +## FAQs + +### What does `BlockMode` field do? + +By default, library lets you read and write values so we need a locker to make sure your data is safe. But in cases that you are very sure about only reading data through the library, you can set `cfg.BlockMode = false` to speed up read operations about **50-70%** faster. + +### Why another INI library? + +Many people are using my another INI library [goconfig](https://github.com/Unknwon/goconfig), so the reason for this one is I would like to make more Go style code. Also when you set `cfg.BlockMode = false`, this one is about **10-30%** faster. + +To make those changes I have to confirm API broken, so it's safer to keep it in another place and start using `gopkg.in` to version my package at this time.(PS: shorter import path) + +## License + +This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. diff --git a/vendor/github.com/go-ini/ini/README_ZH.md b/vendor/github.com/go-ini/ini/README_ZH.md new file mode 100644 index 000000000..ce6d8eb45 --- /dev/null +++ b/vendor/github.com/go-ini/ini/README_ZH.md @@ -0,0 +1,577 @@ +本包æ供了 Go 语言中读写 INI 文件的功能。 + +## 功能特性 + +- 支æŒè¦†ç›–加载多个数æ®æºï¼ˆ`[]byte` 或文件) +- 支æŒé€’归读å–键值 +- 支æŒè¯»å–父å­åˆ†åŒº +- 支æŒè¯»å–自增键å +- 支æŒè¯»å–多行的键值 +- 支æŒå¤§é‡è¾…助方法 +- 支æŒåœ¨è¯»å–时直接转æ¢ä¸º Go 语言类型 +- 支æŒè¯»å–å’Œ **写入** 分区和键的注释 +- è½»æ¾æ“作分区ã€é”®å€¼å’Œæ³¨é‡Š +- 在ä¿å­˜æ–‡ä»¶æ—¶åˆ†åŒºå’Œé”®å€¼ä¼šä¿æŒåŽŸæœ‰çš„é¡ºåº + +## 下载安装 + +使用一个特定版本: + + go get gopkg.in/ini.v1 + +使用最新版: + + go get github.com/go-ini/ini + +### 测试安装 + +如果您想è¦åœ¨è‡ªå·±çš„机器上è¿è¡Œæµ‹è¯•ï¼Œè¯·ä½¿ç”¨ `-t` 标记: + + go get -t gopkg.in/ini.v1 + +## 开始使用 + +### 从数æ®æºåŠ è½½ + +一个 **æ•°æ®æº** å¯ä»¥æ˜¯ `[]byte` 类型的原始数æ®ï¼Œæˆ– `string` 类型的文件路径。您å¯ä»¥åŠ è½½ **ä»»æ„多个** æ•°æ®æºã€‚如果您传递其它类型的数æ®æºï¼Œåˆ™ä¼šç›´æŽ¥è¿”回错误。 + +```go +cfg, err := ini.Load([]byte("raw data"), "filename") +``` + +或者从一个空白的文件开始: + +```go +cfg := ini.Empty() +``` + +当您在一开始无法决定需è¦åŠ è½½å“ªäº›æ•°æ®æºæ—¶ï¼Œä»å¯ä»¥ä½¿ç”¨ **Append()** 在需è¦çš„时候加载它们。 + +```go +err := cfg.Append("other file", []byte("other raw data")) +``` + +### æ“作分区(Section) + +获å–指定分区: + +```go +section, err := cfg.GetSection("section name") +``` + +如果您想è¦èŽ·å–默认分区,则å¯ä»¥ç”¨ç©ºå­—符串代替分区å: + +```go +section, err := cfg.GetSection("") +``` + +当您éžå¸¸ç¡®å®šæŸä¸ªåˆ†åŒºæ˜¯å­˜åœ¨çš„,å¯ä»¥ä½¿ç”¨ä»¥ä¸‹ç®€ä¾¿æ–¹æ³•ï¼š + +```go +section := cfg.Section("") +``` + +如果ä¸å°å¿ƒåˆ¤æ–­é”™äº†ï¼Œè¦èŽ·å–的分区其实是ä¸å­˜åœ¨çš„,那会å‘生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。 + +创建一个分区: + +```go +err := cfg.NewSection("new section") +``` + +获å–所有分区对象或å称: + +```go +sections := cfg.Sections() +names := cfg.SectionStrings() +``` + +### æ“作键(Key) + +获å–æŸä¸ªåˆ†åŒºä¸‹çš„键: + +```go +key, err := cfg.Section("").GetKey("key name") +``` + +和分区一样,您也å¯ä»¥ç›´æŽ¥èŽ·å–键而忽略错误处ç†ï¼š + +```go +key := cfg.Section("").Key("key name") +``` + +判断æŸä¸ªé”®æ˜¯å¦å­˜åœ¨ï¼š + +```go +yes := cfg.Section("").HasKey("key name") +``` + +创建一个新的键: + +```go +err := cfg.Section("").NewKey("name", "value") +``` + +获å–分区下的所有键或键å: + +```go +keys := cfg.Section("").Keys() +names := cfg.Section("").KeyStrings() +``` + +获å–分区下的所有键值对的克隆: + +```go +hash := cfg.GetSection("").KeysHash() +``` + +### æ“作键值(Value) + +获å–一个类型为字符串(string)的值: + +```go +val := cfg.Section("").Key("key name").String() +``` + +获å–值的åŒæ—¶é€šè¿‡è‡ªå®šä¹‰å‡½æ•°è¿›è¡Œå¤„ç†éªŒè¯ï¼š + +```go +val := cfg.Section("").Key("key name").Validate(func(in string) string { + if len(in) == 0 { + return "default" + } + return in +}) +``` + +如果您ä¸éœ€è¦ä»»ä½•å¯¹å€¼çš„自动转å˜åŠŸèƒ½ï¼ˆä¾‹å¦‚递归读å–),å¯ä»¥ç›´æŽ¥èŽ·å–原值(这ç§æ–¹å¼æ€§èƒ½æœ€ä½³ï¼‰ï¼š + +```go +val := cfg.Section("").Key("key name").Value() +``` + +判断æŸä¸ªåŽŸå€¼æ˜¯å¦å­˜åœ¨ï¼š + +```go +yes := cfg.Section("").HasValue("test value") +``` + +获å–其它类型的值: + +```go +// 布尔值的规则: +// true 当值为:1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On +// false 当值为:0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off +v, err = cfg.Section("").Key("BOOL").Bool() +v, err = cfg.Section("").Key("FLOAT64").Float64() +v, err = cfg.Section("").Key("INT").Int() +v, err = cfg.Section("").Key("INT64").Int64() +v, err = cfg.Section("").Key("UINT").Uint() +v, err = cfg.Section("").Key("UINT64").Uint64() +v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339) +v, err = cfg.Section("").Key("TIME").Time() // RFC3339 + +v = cfg.Section("").Key("BOOL").MustBool() +v = cfg.Section("").Key("FLOAT64").MustFloat64() +v = cfg.Section("").Key("INT").MustInt() +v = cfg.Section("").Key("INT64").MustInt64() +v = cfg.Section("").Key("UINT").MustUint() +v = cfg.Section("").Key("UINT64").MustUint64() +v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339) +v = cfg.Section("").Key("TIME").MustTime() // RFC3339 + +// ç”± Must 开头的方法åå…许接收一个相åŒç±»åž‹çš„å‚æ•°æ¥ä½œä¸ºé»˜è®¤å€¼ï¼Œ +// 当键ä¸å­˜åœ¨æˆ–者转æ¢å¤±è´¥æ—¶ï¼Œåˆ™ä¼šç›´æŽ¥è¿”回该默认值。 +// 但是,MustString 方法必须传递一个默认值。 + +v = cfg.Seciont("").Key("String").MustString("default") +v = cfg.Section("").Key("BOOL").MustBool(true) +v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25) +v = cfg.Section("").Key("INT").MustInt(10) +v = cfg.Section("").Key("INT64").MustInt64(99) +v = cfg.Section("").Key("UINT").MustUint(3) +v = cfg.Section("").Key("UINT64").MustUint64(6) +v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now()) +v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339 +``` + +如果我的值有好多行怎么办? + +```ini +[advance] +ADDRESS = """404 road, +NotFound, State, 5000 +Earth""" +``` + +å—¯å“¼ï¼Ÿå° caseï¼ + +```go +cfg.Section("advance").Key("ADDRESS").String() + +/* --- start --- +404 road, +NotFound, State, 5000 +Earth +------ end --- */ +``` + +赞爆了ï¼é‚£è¦æ˜¯æˆ‘属于一行的内容写ä¸ä¸‹æƒ³è¦å†™åˆ°ç¬¬äºŒè¡Œæ€Žä¹ˆåŠžï¼Ÿ + +```ini +[advance] +two_lines = how about \ + continuation lines? +lots_of_lines = 1 \ + 2 \ + 3 \ + 4 +``` + +简直是å°èœä¸€ç¢Ÿï¼ + +```go +cfg.Section("advance").Key("two_lines").String() // how about continuation lines? +cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4 +``` + +需è¦æ³¨æ„的是,值两侧的å•å¼•å·ä¼šè¢«è‡ªåŠ¨å‰”除: + +```ini +foo = "some value" // foo: some value +bar = 'some value' // bar: some value +``` + +这就是全部了?哈哈,当然ä¸æ˜¯ã€‚ + +#### æ“作键值的辅助方法 + +获å–键值时设定候选值: + +```go +v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"}) +v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75}) +v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30}) +v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30}) +v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9}) +v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9}) +v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3}) +v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339 +``` + +如果获å–到的值ä¸æ˜¯å€™é€‰å€¼çš„ä»»æ„一个,则会返回默认值,而默认值ä¸éœ€è¦æ˜¯å€™é€‰å€¼ä¸­çš„一员。 + +验è¯èŽ·å–的值是å¦åœ¨æŒ‡å®šèŒƒå›´å†…: + +```go +vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2) +vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20) +vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20) +vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9) +vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9) +vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime) +vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339 +``` + +自动分割键值为切片(slice): + +```go +vals = cfg.Section("").Key("STRINGS").Strings(",") +vals = cfg.Section("").Key("FLOAT64S").Float64s(",") +vals = cfg.Section("").Key("INTS").Ints(",") +vals = cfg.Section("").Key("INT64S").Int64s(",") +vals = cfg.Section("").Key("UINTS").Uints(",") +vals = cfg.Section("").Key("UINT64S").Uint64s(",") +vals = cfg.Section("").Key("TIMES").Times(",") +``` + +### ä¿å­˜é…ç½® + +终于到了这个时刻,是时候ä¿å­˜ä¸€ä¸‹é…置了。 + +比较原始的åšæ³•æ˜¯è¾“出é…置到æŸä¸ªæ–‡ä»¶ï¼š + +```go +// ... +err = cfg.SaveTo("my.ini") +err = cfg.SaveToIndent("my.ini", "\t") +``` + +å¦ä¸€ä¸ªæ¯”较高级的åšæ³•æ˜¯å†™å…¥åˆ°ä»»ä½•å®žçŽ° `io.Writer` 接å£çš„对象中: + +```go +// ... +cfg.WriteTo(writer) +cfg.WriteToIndent(writer, "\t") +``` + +### 高级用法 + +#### 递归读å–键值 + +在获å–所有键值的过程中,特殊语法 `%()s` 会被应用,其中 `` å¯ä»¥æ˜¯ç›¸åŒåˆ†åŒºæˆ–者默认分区下的键å。字符串 `%()s` 会被相应的键值所替代,如果指定的键ä¸å­˜åœ¨ï¼Œåˆ™ä¼šç”¨ç©ºå­—符串替代。您å¯ä»¥æœ€å¤šä½¿ç”¨ 99 层的递归嵌套。 + +```ini +NAME = ini + +[author] +NAME = Unknwon +GITHUB = https://github.com/%(NAME)s + +[package] +FULL_NAME = github.com/go-ini/%(NAME)s +``` + +```go +cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon +cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini +``` + +#### 读å–父å­åˆ†åŒº + +您å¯ä»¥åœ¨åˆ†åŒºå称中使用 `.` æ¥è¡¨ç¤ºä¸¤ä¸ªæˆ–多个分区之间的父å­å…³ç³»ã€‚如果æŸä¸ªé”®åœ¨å­åˆ†åŒºä¸­ä¸å­˜åœ¨ï¼Œåˆ™ä¼šåŽ»å®ƒçš„父分区中å†æ¬¡å¯»æ‰¾ï¼Œç›´åˆ°æ²¡æœ‰çˆ¶åˆ†åŒºä¸ºæ­¢ã€‚ + +```ini +NAME = ini +VERSION = v1 +IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s + +[package] +CLONE_URL = https://%(IMPORT_PATH)s + +[package.sub] +``` + +```go +cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1 +``` + +#### 读å–自增键å + +如果数æ®æºä¸­çš„é”®å为 `-`,则认为该键使用了自增键å的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。 + +```ini +[features] +-: Support read/write comments of keys and sections +-: Support auto-increment of key names +-: Support load multiple files to overwrite key values +``` + +```go +cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"} +``` + +### 映射到结构 + +想è¦ä½¿ç”¨æ›´åŠ é¢å‘对象的方å¼çŽ©è½¬ INI å—?好主æ„。 + +```ini +Name = Unknwon +age = 21 +Male = true +Born = 1993-01-01T20:17:05Z + +[Note] +Content = Hi is a good man! +Cities = HangZhou, Boston +``` + +```go +type Note struct { + Content string + Cities []string +} + +type Person struct { + Name string + Age int `ini:"age"` + Male bool + Born time.Time + Note + Created time.Time `ini:"-"` +} + +func main() { + cfg, err := ini.Load("path/to/ini") + // ... + p := new(Person) + err = cfg.MapTo(p) + // ... + + // 一切竟å¯ä»¥å¦‚此的简å•ã€‚ + err = ini.MapTo(p, "path/to/ini") + // ... + + // 嗯哼?åªéœ€è¦æ˜ å°„一个分区å—? + n := new(Note) + err = cfg.Section("Note").MapTo(n) + // ... +} +``` + +结构的字段怎么设置默认值呢?很简å•ï¼Œåªè¦åœ¨æ˜ å°„之å‰å¯¹æŒ‡å®šå­—段进行赋值就å¯ä»¥äº†ã€‚如果键未找到或者类型错误,该值ä¸ä¼šå‘生改å˜ã€‚ + +```go +// ... +p := &Person{ + Name: "Joe", +} +// ... +``` + +这样玩 INI 真的好酷啊ï¼ç„¶è€Œï¼Œå¦‚æžœä¸èƒ½è¿˜ç»™æˆ‘原æ¥çš„é…置文件,有什么åµç”¨ï¼Ÿ + +### 从结构åå°„ + +å¯æ˜¯ï¼Œæˆ‘有说ä¸èƒ½å—? + +```go +type Embeded struct { + Dates []time.Time `delim:"|"` + Places []string + None []int +} + +type Author struct { + Name string `ini:"NAME"` + Male bool + Age int + GPA float64 + NeverMind string `ini:"-"` + *Embeded +} + +func main() { + a := &Author{"Unknwon", true, 21, 2.8, "", + &Embeded{ + []time.Time{time.Now(), time.Now()}, + []string{"HangZhou", "Boston"}, + []int{}, + }} + cfg := ini.Empty() + err = ini.ReflectFrom(cfg, a) + // ... +} +``` + +瞧瞧,奇迹å‘生了。 + +```ini +NAME = Unknwon +Male = true +Age = 21 +GPA = 2.8 + +[Embeded] +Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 +Places = HangZhou,Boston +None = +``` + +#### å称映射器(Name Mapper) + +为了节çœæ‚¨çš„时间并简化代ç ï¼Œæœ¬åº“支æŒç±»åž‹ä¸º [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) çš„å称映射器,该映射器负责结构字段å与分区å和键å之间的映射。 + +ç›®å‰æœ‰ 2 款内置的映射器: + +- `AllCapsUnderscore`:该映射器将字段å转æ¢è‡³æ ¼å¼ `ALL_CAPS_UNDERSCORE` åŽå†åŽ»åŒ¹é…分区å和键å。 +- `TitleUnderscore`:该映射器将字段å转æ¢è‡³æ ¼å¼ `title_underscore` åŽå†åŽ»åŒ¹é…分区å和键å。 + +使用方法: + +```go +type Info struct{ + PackageName string +} + +func main() { + err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini")) + // ... + + cfg, err := ini.Load([]byte("PACKAGE_NAME=ini")) + // ... + info := new(Info) + cfg.NameMapper = ini.AllCapsUnderscore + err = cfg.MapTo(info) + // ... +} +``` + +使用函数 `ini.ReflectFromWithMapper` 时也å¯åº”用相åŒçš„规则。 + +#### 映射/å射的其它说明 + +任何嵌入的结构都会被默认认作一个ä¸åŒçš„分区,并且ä¸ä¼šè‡ªåŠ¨äº§ç”Ÿæ‰€è°“的父å­åˆ†åŒºå…³è”: + +```go +type Child struct { + Age string +} + +type Parent struct { + Name string + Child +} + +type Config struct { + City string + Parent +} +``` + +示例é…置文件: + +```ini +City = Boston + +[Parent] +Name = Unknwon + +[Child] +Age = 21 +``` + +很好,但是,我就是è¦åµŒå…¥ç»“构也在åŒä¸€ä¸ªåˆ†åŒºã€‚好å§ï¼Œä½ çˆ¹æ˜¯æŽåˆšï¼ + +```go +type Child struct { + Age string +} + +type Parent struct { + Name string + Child `ini:"Parent"` +} + +type Config struct { + City string + Parent +} +``` + +示例é…置文件: + +```ini +City = Boston + +[Parent] +Name = Unknwon +Age = 21 +``` + +## 获å–帮助 + +- [API 文档](https://gowalker.org/gopkg.in/ini.v1) +- [创建工å•](https://github.com/go-ini/ini/issues/new) + +## 常è§é—®é¢˜ + +### 字段 `BlockMode` 是什么? + +默认情况下,本库会在您进行读写æ“作时采用é”机制æ¥ç¡®ä¿æ•°æ®æ—¶é—´ã€‚但在æŸäº›æƒ…况下,您éžå¸¸ç¡®å®šåªè¿›è¡Œè¯»æ“作。此时,您å¯ä»¥é€šè¿‡è®¾ç½® `cfg.BlockMode = false` æ¥å°†è¯»æ“作æå‡å¤§çº¦ **50-70%** 的性能。 + +### 为什么è¦å†™å¦ä¸€ä¸ª INI 解æžåº“? + +许多人都在使用我的 [goconfig](https://github.com/Unknwon/goconfig) æ¥å®Œæˆå¯¹ INI 文件的æ“作,但我希望使用更加 Go 风格的代ç ã€‚并且当您设置 `cfg.BlockMode = false` 时,会有大约 **10-30%** 的性能æå‡ã€‚ + +为了åšå‡ºè¿™äº›æ”¹å˜ï¼Œæˆ‘必须对 API 进行破å,所以新开一个仓库是最安全的åšæ³•ã€‚除此之外,本库直接使用 `gopkg.in` æ¥è¿›è¡Œç‰ˆæœ¬åŒ–å‘布。(其实真相是导入路径更短了) diff --git a/vendor/github.com/go-ini/ini/ini.go b/vendor/github.com/go-ini/ini/ini.go new file mode 100644 index 000000000..1a27f0680 --- /dev/null +++ b/vendor/github.com/go-ini/ini/ini.go @@ -0,0 +1,1027 @@ +// Copyright 2014 Unknwon +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// Package ini provides INI file read and write functionality in Go. +package ini + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "regexp" + "runtime" + "strconv" + "strings" + "sync" + "time" +) + +const ( + DEFAULT_SECTION = "DEFAULT" + // Maximum allowed depth when recursively substituing variable names. + _DEPTH_VALUES = 99 + + _VERSION = "1.8.6" +) + +func Version() string { + return _VERSION +} + +var ( + LineBreak = "\n" + + // Variable regexp pattern: %(variable)s + varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`) + + // Write spaces around "=" to look better. + PrettyFormat = true +) + +func init() { + if runtime.GOOS == "windows" { + LineBreak = "\r\n" + } +} + +func inSlice(str string, s []string) bool { + for _, v := range s { + if str == v { + return true + } + } + return false +} + +// dataSource is a interface that returns file content. +type dataSource interface { + ReadCloser() (io.ReadCloser, error) +} + +type sourceFile struct { + name string +} + +func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) { + return os.Open(s.name) +} + +type bytesReadCloser struct { + reader io.Reader +} + +func (rc *bytesReadCloser) Read(p []byte) (n int, err error) { + return rc.reader.Read(p) +} + +func (rc *bytesReadCloser) Close() error { + return nil +} + +type sourceData struct { + data []byte +} + +func (s *sourceData) ReadCloser() (io.ReadCloser, error) { + return &bytesReadCloser{bytes.NewReader(s.data)}, nil +} + +// ____ __. +// | |/ _|____ ___.__. +// | <_/ __ < | | +// | | \ ___/\___ | +// |____|__ \___ > ____| +// \/ \/\/ + +// Key represents a key under a section. +type Key struct { + s *Section + Comment string + name string + value string + isAutoIncr bool +} + +// Name returns name of key. +func (k *Key) Name() string { + return k.name +} + +// Value returns raw value of key for performance purpose. +func (k *Key) Value() string { + return k.value +} + +// String returns string representation of value. +func (k *Key) String() string { + val := k.value + if strings.Index(val, "%") == -1 { + return val + } + + for i := 0; i < _DEPTH_VALUES; i++ { + vr := varPattern.FindString(val) + if len(vr) == 0 { + break + } + + // Take off leading '%(' and trailing ')s'. + noption := strings.TrimLeft(vr, "%(") + noption = strings.TrimRight(noption, ")s") + + // Search in the same section. + nk, err := k.s.GetKey(noption) + if err != nil { + // Search again in default section. + nk, _ = k.s.f.Section("").GetKey(noption) + } + + // Substitute by new value and take off leading '%(' and trailing ')s'. + val = strings.Replace(val, vr, nk.value, -1) + } + return val +} + +// Validate accepts a validate function which can +// return modifed result as key value. +func (k *Key) Validate(fn func(string) string) string { + return fn(k.String()) +} + +// parseBool returns the boolean value represented by the string. +// +// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On, +// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off. +// Any other value returns an error. +func parseBool(str string) (value bool, err error) { + switch str { + case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On": + return true, nil + case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off": + return false, nil + } + return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) +} + +// Bool returns bool type value. +func (k *Key) Bool() (bool, error) { + return parseBool(k.String()) +} + +// Float64 returns float64 type value. +func (k *Key) Float64() (float64, error) { + return strconv.ParseFloat(k.String(), 64) +} + +// Int returns int type value. +func (k *Key) Int() (int, error) { + return strconv.Atoi(k.String()) +} + +// Int64 returns int64 type value. +func (k *Key) Int64() (int64, error) { + return strconv.ParseInt(k.String(), 10, 64) +} + +// Uint returns uint type valued. +func (k *Key) Uint() (uint, error) { + u, e := strconv.ParseUint(k.String(), 10, 64) + return uint(u), e +} + +// Uint64 returns uint64 type value. +func (k *Key) Uint64() (uint64, error) { + return strconv.ParseUint(k.String(), 10, 64) +} + +// Duration returns time.Duration type value. +func (k *Key) Duration() (time.Duration, error) { + return time.ParseDuration(k.String()) +} + +// TimeFormat parses with given format and returns time.Time type value. +func (k *Key) TimeFormat(format string) (time.Time, error) { + return time.Parse(format, k.String()) +} + +// Time parses with RFC3339 format and returns time.Time type value. +func (k *Key) Time() (time.Time, error) { + return k.TimeFormat(time.RFC3339) +} + +// MustString returns default value if key value is empty. +func (k *Key) MustString(defaultVal string) string { + val := k.String() + if len(val) == 0 { + return defaultVal + } + return val +} + +// MustBool always returns value without error, +// it returns false if error occurs. +func (k *Key) MustBool(defaultVal ...bool) bool { + val, err := k.Bool() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustFloat64 always returns value without error, +// it returns 0.0 if error occurs. +func (k *Key) MustFloat64(defaultVal ...float64) float64 { + val, err := k.Float64() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustInt always returns value without error, +// it returns 0 if error occurs. +func (k *Key) MustInt(defaultVal ...int) int { + val, err := k.Int() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustInt64 always returns value without error, +// it returns 0 if error occurs. +func (k *Key) MustInt64(defaultVal ...int64) int64 { + val, err := k.Int64() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustUint always returns value without error, +// it returns 0 if error occurs. +func (k *Key) MustUint(defaultVal ...uint) uint { + val, err := k.Uint() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustUint64 always returns value without error, +// it returns 0 if error occurs. +func (k *Key) MustUint64(defaultVal ...uint64) uint64 { + val, err := k.Uint64() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustDuration always returns value without error, +// it returns zero value if error occurs. +func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration { + val, err := k.Duration() + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustTimeFormat always parses with given format and returns value without error, +// it returns zero value if error occurs. +func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { + val, err := k.TimeFormat(format) + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustTime always parses with RFC3339 format and returns value without error, +// it returns zero value if error occurs. +func (k *Key) MustTime(defaultVal ...time.Time) time.Time { + return k.MustTimeFormat(time.RFC3339, defaultVal...) +} + +// In always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) In(defaultVal string, candidates []string) string { + val := k.String() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InFloat64 always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { + val := k.MustFloat64() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InInt always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InInt(defaultVal int, candidates []int) int { + val := k.MustInt() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InInt64 always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { + val := k.MustInt64() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InUint always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InUint(defaultVal uint, candidates []uint) uint { + val := k.MustUint() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InUint64 always returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 { + val := k.MustUint64() + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InTimeFormat always parses with given format and returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { + val := k.MustTimeFormat(format) + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InTime always parses with RFC3339 format and returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { + return k.InTimeFormat(time.RFC3339, defaultVal, candidates) +} + +// RangeFloat64 checks if value is in given range inclusively, +// and returns default value if it's not. +func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { + val := k.MustFloat64() + if val < min || val > max { + return defaultVal + } + return val +} + +// RangeInt checks if value is in given range inclusively, +// and returns default value if it's not. +func (k *Key) RangeInt(defaultVal, min, max int) int { + val := k.MustInt() + if val < min || val > max { + return defaultVal + } + return val +} + +// RangeInt64 checks if value is in given range inclusively, +// and returns default value if it's not. +func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { + val := k.MustInt64() + if val < min || val > max { + return defaultVal + } + return val +} + +// RangeTimeFormat checks if value with given format is in given range inclusively, +// and returns default value if it's not. +func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { + val := k.MustTimeFormat(format) + if val.Unix() < min.Unix() || val.Unix() > max.Unix() { + return defaultVal + } + return val +} + +// RangeTime checks if value with RFC3339 format is in given range inclusively, +// and returns default value if it's not. +func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { + return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) +} + +// Strings returns list of string divided by given delimiter. +func (k *Key) Strings(delim string) []string { + str := k.String() + if len(str) == 0 { + return []string{} + } + + vals := strings.Split(str, delim) + for i := range vals { + vals[i] = strings.TrimSpace(vals[i]) + } + return vals +} + +// Float64s returns list of float64 divided by given delimiter. +func (k *Key) Float64s(delim string) []float64 { + strs := k.Strings(delim) + vals := make([]float64, len(strs)) + for i := range strs { + vals[i], _ = strconv.ParseFloat(strs[i], 64) + } + return vals +} + +// Ints returns list of int divided by given delimiter. +func (k *Key) Ints(delim string) []int { + strs := k.Strings(delim) + vals := make([]int, len(strs)) + for i := range strs { + vals[i], _ = strconv.Atoi(strs[i]) + } + return vals +} + +// Int64s returns list of int64 divided by given delimiter. +func (k *Key) Int64s(delim string) []int64 { + strs := k.Strings(delim) + vals := make([]int64, len(strs)) + for i := range strs { + vals[i], _ = strconv.ParseInt(strs[i], 10, 64) + } + return vals +} + +// Uints returns list of uint divided by given delimiter. +func (k *Key) Uints(delim string) []uint { + strs := k.Strings(delim) + vals := make([]uint, len(strs)) + for i := range strs { + u, _ := strconv.ParseUint(strs[i], 10, 0) + vals[i] = uint(u) + } + return vals +} + +// Uint64s returns list of uint64 divided by given delimiter. +func (k *Key) Uint64s(delim string) []uint64 { + strs := k.Strings(delim) + vals := make([]uint64, len(strs)) + for i := range strs { + vals[i], _ = strconv.ParseUint(strs[i], 10, 64) + } + return vals +} + +// TimesFormat parses with given format and returns list of time.Time divided by given delimiter. +func (k *Key) TimesFormat(format, delim string) []time.Time { + strs := k.Strings(delim) + vals := make([]time.Time, len(strs)) + for i := range strs { + vals[i], _ = time.Parse(format, strs[i]) + } + return vals +} + +// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter. +func (k *Key) Times(delim string) []time.Time { + return k.TimesFormat(time.RFC3339, delim) +} + +// SetValue changes key value. +func (k *Key) SetValue(v string) { + if k.s.f.BlockMode { + k.s.f.lock.Lock() + defer k.s.f.lock.Unlock() + } + + k.value = v + k.s.keysHash[k.name] = v +} + +// _________ __ .__ +// / _____/ ____ _____/ |_|__| ____ ____ +// \_____ \_/ __ \_/ ___\ __\ |/ _ \ / \ +// / \ ___/\ \___| | | ( <_> ) | \ +// /_______ /\___ >\___ >__| |__|\____/|___| / +// \/ \/ \/ \/ + +// Section represents a config section. +type Section struct { + f *File + Comment string + name string + keys map[string]*Key + keyList []string + keysHash map[string]string +} + +func newSection(f *File, name string) *Section { + return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)} +} + +// Name returns name of Section. +func (s *Section) Name() string { + return s.name +} + +// NewKey creates a new key to given section. +func (s *Section) NewKey(name, val string) (*Key, error) { + if len(name) == 0 { + return nil, errors.New("error creating new key: empty key name") + } + + if s.f.BlockMode { + s.f.lock.Lock() + defer s.f.lock.Unlock() + } + + if inSlice(name, s.keyList) { + s.keys[name].value = val + return s.keys[name], nil + } + + s.keyList = append(s.keyList, name) + s.keys[name] = &Key{s, "", name, val, false} + s.keysHash[name] = val + return s.keys[name], nil +} + +// GetKey returns key in section by given name. +func (s *Section) GetKey(name string) (*Key, error) { + // FIXME: change to section level lock? + if s.f.BlockMode { + s.f.lock.RLock() + } + key := s.keys[name] + if s.f.BlockMode { + s.f.lock.RUnlock() + } + + if key == nil { + // Check if it is a child-section. + sname := s.name + for { + if i := strings.LastIndex(sname, "."); i > -1 { + sname = sname[:i] + sec, err := s.f.GetSection(sname) + if err != nil { + continue + } + return sec.GetKey(name) + } else { + break + } + } + return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name) + } + return key, nil +} + +// HasKey returns true if section contains a key with given name. +func (s *Section) HasKey(name string) bool { + key, _ := s.GetKey(name) + return key != nil +} + +// Haskey is a backwards-compatible name for HasKey. +func (s *Section) Haskey(name string) bool { + return s.HasKey(name) +} + +// HasValue returns true if section contains given raw value. +func (s *Section) HasValue(value string) bool { + if s.f.BlockMode { + s.f.lock.RLock() + defer s.f.lock.RUnlock() + } + + for _, k := range s.keys { + if value == k.value { + return true + } + } + return false +} + +// Key assumes named Key exists in section and returns a zero-value when not. +func (s *Section) Key(name string) *Key { + key, err := s.GetKey(name) + if err != nil { + // It's OK here because the only possible error is empty key name, + // but if it's empty, this piece of code won't be executed. + key, _ = s.NewKey(name, "") + return key + } + return key +} + +// Keys returns list of keys of section. +func (s *Section) Keys() []*Key { + keys := make([]*Key, len(s.keyList)) + for i := range s.keyList { + keys[i] = s.Key(s.keyList[i]) + } + return keys +} + +// KeyStrings returns list of key names of section. +func (s *Section) KeyStrings() []string { + list := make([]string, len(s.keyList)) + copy(list, s.keyList) + return list +} + +// KeysHash returns keys hash consisting of names and values. +func (s *Section) KeysHash() map[string]string { + if s.f.BlockMode { + s.f.lock.RLock() + defer s.f.lock.RUnlock() + } + + hash := map[string]string{} + for key, value := range s.keysHash { + hash[key] = value + } + return hash +} + +// DeleteKey deletes a key from section. +func (s *Section) DeleteKey(name string) { + if s.f.BlockMode { + s.f.lock.Lock() + defer s.f.lock.Unlock() + } + + for i, k := range s.keyList { + if k == name { + s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) + delete(s.keys, name) + return + } + } +} + +// ___________.__.__ +// \_ _____/|__| | ____ +// | __) | | | _/ __ \ +// | \ | | |_\ ___/ +// \___ / |__|____/\___ > +// \/ \/ + +// File represents a combination of a or more INI file(s) in memory. +type File struct { + // Should make things safe, but sometimes doesn't matter. + BlockMode bool + // Make sure data is safe in multiple goroutines. + lock sync.RWMutex + + // Allow combination of multiple data sources. + dataSources []dataSource + // Actual data is stored here. + sections map[string]*Section + + // To keep data in order. + sectionList []string + + NameMapper +} + +// newFile initializes File object with given data sources. +func newFile(dataSources []dataSource) *File { + return &File{ + BlockMode: true, + dataSources: dataSources, + sections: make(map[string]*Section), + sectionList: make([]string, 0, 10), + } +} + +func parseDataSource(source interface{}) (dataSource, error) { + switch s := source.(type) { + case string: + return sourceFile{s}, nil + case []byte: + return &sourceData{s}, nil + default: + return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s) + } +} + +// Load loads and parses from INI data sources. +// Arguments can be mixed of file name with string type, or raw data in []byte. +func Load(source interface{}, others ...interface{}) (_ *File, err error) { + sources := make([]dataSource, len(others)+1) + sources[0], err = parseDataSource(source) + if err != nil { + return nil, err + } + for i := range others { + sources[i+1], err = parseDataSource(others[i]) + if err != nil { + return nil, err + } + } + f := newFile(sources) + if err = f.Reload(); err != nil { + return nil, err + } + return f, nil +} + +// Empty returns an empty file object. +func Empty() *File { + // Ignore error here, we sure our data is good. + f, _ := Load([]byte("")) + return f +} + +// NewSection creates a new section. +func (f *File) NewSection(name string) (*Section, error) { + if len(name) == 0 { + return nil, errors.New("error creating new section: empty section name") + } + + if f.BlockMode { + f.lock.Lock() + defer f.lock.Unlock() + } + + if inSlice(name, f.sectionList) { + return f.sections[name], nil + } + + f.sectionList = append(f.sectionList, name) + f.sections[name] = newSection(f, name) + return f.sections[name], nil +} + +// NewSections creates a list of sections. +func (f *File) NewSections(names ...string) (err error) { + for _, name := range names { + if _, err = f.NewSection(name); err != nil { + return err + } + } + return nil +} + +// GetSection returns section by given name. +func (f *File) GetSection(name string) (*Section, error) { + if len(name) == 0 { + name = DEFAULT_SECTION + } + + if f.BlockMode { + f.lock.RLock() + defer f.lock.RUnlock() + } + + sec := f.sections[name] + if sec == nil { + return nil, fmt.Errorf("error when getting section: section '%s' not exists", name) + } + return sec, nil +} + +// Section assumes named section exists and returns a zero-value when not. +func (f *File) Section(name string) *Section { + sec, err := f.GetSection(name) + if err != nil { + // Note: It's OK here because the only possible error is empty section name, + // but if it's empty, this piece of code won't be executed. + sec, _ = f.NewSection(name) + return sec + } + return sec +} + +// Section returns list of Section. +func (f *File) Sections() []*Section { + sections := make([]*Section, len(f.sectionList)) + for i := range f.sectionList { + sections[i] = f.Section(f.sectionList[i]) + } + return sections +} + +// SectionStrings returns list of section names. +func (f *File) SectionStrings() []string { + list := make([]string, len(f.sectionList)) + copy(list, f.sectionList) + return list +} + +// DeleteSection deletes a section. +func (f *File) DeleteSection(name string) { + if f.BlockMode { + f.lock.Lock() + defer f.lock.Unlock() + } + + if len(name) == 0 { + name = DEFAULT_SECTION + } + + for i, s := range f.sectionList { + if s == name { + f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) + delete(f.sections, name) + return + } + } +} + +func (f *File) reload(s dataSource) error { + r, err := s.ReadCloser() + if err != nil { + return err + } + defer r.Close() + + return f.parse(r) +} + +// Reload reloads and parses all data sources. +func (f *File) Reload() (err error) { + for _, s := range f.dataSources { + if err = f.reload(s); err != nil { + return err + } + } + return nil +} + +// Append appends one or more data sources and reloads automatically. +func (f *File) Append(source interface{}, others ...interface{}) error { + ds, err := parseDataSource(source) + if err != nil { + return err + } + f.dataSources = append(f.dataSources, ds) + for _, s := range others { + ds, err = parseDataSource(s) + if err != nil { + return err + } + f.dataSources = append(f.dataSources, ds) + } + return f.Reload() +} + +// WriteToIndent writes file content into io.Writer with given value indention. +func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) { + equalSign := "=" + if PrettyFormat { + equalSign = " = " + } + + // Use buffer to make sure target is safe until finish encoding. + buf := bytes.NewBuffer(nil) + for i, sname := range f.sectionList { + sec := f.Section(sname) + if len(sec.Comment) > 0 { + if sec.Comment[0] != '#' && sec.Comment[0] != ';' { + sec.Comment = "; " + sec.Comment + } + if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil { + return 0, err + } + } + + if i > 0 { + if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil { + return 0, err + } + } else { + // Write nothing if default section is empty. + if len(sec.keyList) == 0 { + continue + } + } + + for _, kname := range sec.keyList { + key := sec.Key(kname) + if len(key.Comment) > 0 { + if len(indent) > 0 && sname != DEFAULT_SECTION { + buf.WriteString(indent) + } + if key.Comment[0] != '#' && key.Comment[0] != ';' { + key.Comment = "; " + key.Comment + } + if _, err = buf.WriteString(key.Comment + LineBreak); err != nil { + return 0, err + } + } + + if len(indent) > 0 && sname != DEFAULT_SECTION { + buf.WriteString(indent) + } + + switch { + case key.isAutoIncr: + kname = "-" + case strings.ContainsAny(kname, "\"=:"): + kname = "`" + kname + "`" + case strings.Contains(kname, "`"): + kname = `"""` + kname + `"""` + } + + val := key.value + // In case key value contains "\n", "`", "\"", "#" or ";". + if strings.ContainsAny(val, "\n`") { + val = `"""` + val + `"""` + } else if strings.ContainsAny(val, "#;") { + val = "`" + val + "`" + } + if _, err = buf.WriteString(kname + equalSign + val + LineBreak); err != nil { + return 0, err + } + } + + // Put a line between sections. + if _, err = buf.WriteString(LineBreak); err != nil { + return 0, err + } + } + + return buf.WriteTo(w) +} + +// WriteTo writes file content into io.Writer. +func (f *File) WriteTo(w io.Writer) (int64, error) { + return f.WriteToIndent(w, "") +} + +// SaveToIndent writes content to file system with given value indention. +func (f *File) SaveToIndent(filename, indent string) error { + // Note: Because we are truncating with os.Create, + // so it's safer to save to a temporary file location and rename afte done. + tmpPath := filename + "." + strconv.Itoa(time.Now().Nanosecond()) + ".tmp" + defer os.Remove(tmpPath) + + fw, err := os.Create(tmpPath) + if err != nil { + return err + } + + if _, err = f.WriteToIndent(fw, indent); err != nil { + fw.Close() + return err + } + fw.Close() + + // Remove old file and rename the new one. + os.Remove(filename) + return os.Rename(tmpPath, filename) +} + +// SaveTo writes content to file system. +func (f *File) SaveTo(filename string) error { + return f.SaveToIndent(filename, "") +} diff --git a/vendor/github.com/go-ini/ini/parser.go b/vendor/github.com/go-ini/ini/parser.go new file mode 100644 index 000000000..1c1bf91f0 --- /dev/null +++ b/vendor/github.com/go-ini/ini/parser.go @@ -0,0 +1,312 @@ +// Copyright 2015 Unknwon +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package ini + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + "unicode" +) + +type tokenType int + +const ( + _TOKEN_INVALID tokenType = iota + _TOKEN_COMMENT + _TOKEN_SECTION + _TOKEN_KEY +) + +type parser struct { + buf *bufio.Reader + isEOF bool + count int + comment *bytes.Buffer +} + +func newParser(r io.Reader) *parser { + return &parser{ + buf: bufio.NewReader(r), + count: 1, + comment: &bytes.Buffer{}, + } +} + +// BOM handles header of BOM-UTF8 format. +// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding +func (p *parser) BOM() error { + mask, err := p.buf.Peek(3) + if err != nil && err != io.EOF { + return err + } else if len(mask) < 3 { + return nil + } else if mask[0] == 239 && mask[1] == 187 && mask[2] == 191 { + p.buf.Read(mask) + } + return nil +} + +func (p *parser) readUntil(delim byte) ([]byte, error) { + data, err := p.buf.ReadBytes(delim) + if err != nil { + if err == io.EOF { + p.isEOF = true + } else { + return nil, err + } + } + return data, nil +} + +func cleanComment(in []byte) ([]byte, bool) { + i := bytes.IndexAny(in, "#;") + if i == -1 { + return nil, false + } + return in[i:], true +} + +func readKeyName(in []byte) (string, int, error) { + line := string(in) + + // Check if key name surrounded by quotes. + var keyQuote string + if line[0] == '"' { + if len(line) > 6 && string(line[0:3]) == `"""` { + keyQuote = `"""` + } else { + keyQuote = `"` + } + } else if line[0] == '`' { + keyQuote = "`" + } + + // Get out key name + endIdx := -1 + if len(keyQuote) > 0 { + startIdx := len(keyQuote) + // FIXME: fail case -> """"""name"""=value + pos := strings.Index(line[startIdx:], keyQuote) + if pos == -1 { + return "", -1, fmt.Errorf("missing closing key quote: %s", line) + } + pos += startIdx + + // Find key-value delimiter + i := strings.IndexAny(line[pos+startIdx:], "=:") + if i < 0 { + return "", -1, fmt.Errorf("key-value delimiter not found: %s", line) + } + endIdx = pos + i + return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil + } + + endIdx = strings.IndexAny(line, "=:") + if endIdx < 0 { + return "", -1, fmt.Errorf("key-value delimiter not found: %s", line) + } + return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil +} + +func (p *parser) readMultilines(line, val, valQuote string) (string, error) { + for { + data, err := p.readUntil('\n') + if err != nil { + return "", err + } + next := string(data) + + pos := strings.LastIndex(next, valQuote) + if pos > -1 { + val += next[:pos] + + comment, has := cleanComment([]byte(next[pos:])) + if has { + p.comment.Write(bytes.TrimSpace(comment)) + } + break + } + val += next + if p.isEOF { + return "", fmt.Errorf("missing closing key quote from '%s' to '%s'", line, next) + } + } + return val, nil +} + +func (p *parser) readContinuationLines(val string) (string, error) { + for { + data, err := p.readUntil('\n') + if err != nil { + return "", err + } + next := strings.TrimSpace(string(data)) + + if len(next) == 0 { + break + } + val += next + if val[len(val)-1] != '\\' { + break + } + val = val[:len(val)-1] + } + return val, nil +} + +// hasSurroundedQuote check if and only if the first and last characters +// are quotes \" or \'. +// It returns false if any other parts also contain same kind of quotes. +func hasSurroundedQuote(in string, quote byte) bool { + return len(in) > 2 && in[0] == quote && in[len(in)-1] == quote && + strings.IndexByte(in[1:], quote) == len(in)-2 +} + +func (p *parser) readValue(in []byte) (string, error) { + line := strings.TrimLeftFunc(string(in), unicode.IsSpace) + if len(line) == 0 { + return "", nil + } + + var valQuote string + if len(line) > 3 && string(line[0:3]) == `"""` { + valQuote = `"""` + } else if line[0] == '`' { + valQuote = "`" + } + + if len(valQuote) > 0 { + startIdx := len(valQuote) + pos := strings.LastIndex(line[startIdx:], valQuote) + // Check for multi-line value + if pos == -1 { + return p.readMultilines(line, line[startIdx:], valQuote) + } + + return line[startIdx : pos+startIdx], nil + } + + // Won't be able to reach here if value only contains whitespace. + line = strings.TrimSpace(line) + + // Check continuation lines + if line[len(line)-1] == '\\' { + return p.readContinuationLines(line[:len(line)-1]) + } + + i := strings.IndexAny(line, "#;") + if i > -1 { + p.comment.WriteString(line[i:]) + line = strings.TrimSpace(line[:i]) + } + + // Trim single quotes + if hasSurroundedQuote(line, '\'') || + hasSurroundedQuote(line, '"') { + line = line[1 : len(line)-1] + } + return line, nil +} + +// parse parses data through an io.Reader. +func (f *File) parse(reader io.Reader) (err error) { + p := newParser(reader) + if err = p.BOM(); err != nil { + return fmt.Errorf("BOM: %v", err) + } + + // Ignore error because default section name is never empty string. + section, _ := f.NewSection(DEFAULT_SECTION) + + var line []byte + for !p.isEOF { + line, err = p.readUntil('\n') + if err != nil { + return err + } + + line = bytes.TrimLeftFunc(line, unicode.IsSpace) + if len(line) == 0 { + continue + } + + // Comments + if line[0] == '#' || line[0] == ';' { + // Note: we do not care ending line break, + // it is needed for adding second line, + // so just clean it once at the end when set to value. + p.comment.Write(line) + continue + } + + // Section + if line[0] == '[' { + // Read to the next ']' (TODO: support quoted strings) + closeIdx := bytes.IndexByte(line, ']') + if closeIdx == -1 { + return fmt.Errorf("unclosed section: %s", line) + } + + section, err = f.NewSection(string(line[1:closeIdx])) + if err != nil { + return err + } + + comment, has := cleanComment(line[closeIdx+1:]) + if has { + p.comment.Write(comment) + } + + section.Comment = strings.TrimSpace(p.comment.String()) + + // Reset aotu-counter and comments + p.comment.Reset() + p.count = 1 + continue + } + + kname, offset, err := readKeyName(line) + if err != nil { + return err + } + + // Auto increment. + isAutoIncr := false + if kname == "-" { + isAutoIncr = true + kname = "#" + strconv.Itoa(p.count) + p.count++ + } + + key, err := section.NewKey(kname, "") + if err != nil { + return err + } + key.isAutoIncr = isAutoIncr + + value, err := p.readValue(line[offset:]) + if err != nil { + return err + } + key.SetValue(value) + key.Comment = strings.TrimSpace(p.comment.String()) + p.comment.Reset() + } + return nil +} diff --git a/vendor/github.com/go-ini/ini/struct.go b/vendor/github.com/go-ini/ini/struct.go new file mode 100644 index 000000000..3fb92c396 --- /dev/null +++ b/vendor/github.com/go-ini/ini/struct.go @@ -0,0 +1,351 @@ +// Copyright 2014 Unknwon +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package ini + +import ( + "bytes" + "errors" + "fmt" + "reflect" + "time" + "unicode" +) + +// NameMapper represents a ini tag name mapper. +type NameMapper func(string) string + +// Built-in name getters. +var ( + // AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. + AllCapsUnderscore NameMapper = func(raw string) string { + newstr := make([]rune, 0, len(raw)) + for i, chr := range raw { + if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { + if i > 0 { + newstr = append(newstr, '_') + } + } + newstr = append(newstr, unicode.ToUpper(chr)) + } + return string(newstr) + } + // TitleUnderscore converts to format title_underscore. + TitleUnderscore NameMapper = func(raw string) string { + newstr := make([]rune, 0, len(raw)) + for i, chr := range raw { + if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { + if i > 0 { + newstr = append(newstr, '_') + } + chr -= ('A' - 'a') + } + newstr = append(newstr, chr) + } + return string(newstr) + } +) + +func (s *Section) parseFieldName(raw, actual string) string { + if len(actual) > 0 { + return actual + } + if s.f.NameMapper != nil { + return s.f.NameMapper(raw) + } + return raw +} + +func parseDelim(actual string) string { + if len(actual) > 0 { + return actual + } + return "," +} + +var reflectTime = reflect.TypeOf(time.Now()).Kind() + +// setWithProperType sets proper value to field based on its type, +// but it does not return error for failing parsing, +// because we want to use default value that is already assigned to strcut. +func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error { + switch t.Kind() { + case reflect.String: + if len(key.String()) == 0 { + return nil + } + field.SetString(key.String()) + case reflect.Bool: + boolVal, err := key.Bool() + if err != nil { + return nil + } + field.SetBool(boolVal) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + durationVal, err := key.Duration() + // Skip zero value + if err == nil && int(durationVal) > 0 { + field.Set(reflect.ValueOf(durationVal)) + return nil + } + + intVal, err := key.Int64() + if err != nil || intVal == 0 { + return nil + } + field.SetInt(intVal) + // byte is an alias for uint8, so supporting uint8 breaks support for byte + case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: + durationVal, err := key.Duration() + if err == nil { + field.Set(reflect.ValueOf(durationVal)) + return nil + } + + uintVal, err := key.Uint64() + if err != nil { + return nil + } + field.SetUint(uintVal) + + case reflect.Float64: + floatVal, err := key.Float64() + if err != nil { + return nil + } + field.SetFloat(floatVal) + case reflectTime: + timeVal, err := key.Time() + if err != nil { + return nil + } + field.Set(reflect.ValueOf(timeVal)) + case reflect.Slice: + vals := key.Strings(delim) + numVals := len(vals) + if numVals == 0 { + return nil + } + + sliceOf := field.Type().Elem().Kind() + + var times []time.Time + if sliceOf == reflectTime { + times = key.Times(delim) + } + + slice := reflect.MakeSlice(field.Type(), numVals, numVals) + for i := 0; i < numVals; i++ { + switch sliceOf { + case reflectTime: + slice.Index(i).Set(reflect.ValueOf(times[i])) + default: + slice.Index(i).Set(reflect.ValueOf(vals[i])) + } + } + field.Set(slice) + default: + return fmt.Errorf("unsupported type '%s'", t) + } + return nil +} + +func (s *Section) mapTo(val reflect.Value) error { + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + typ := val.Type() + + for i := 0; i < typ.NumField(); i++ { + field := val.Field(i) + tpField := typ.Field(i) + + tag := tpField.Tag.Get("ini") + if tag == "-" { + continue + } + + fieldName := s.parseFieldName(tpField.Name, tag) + if len(fieldName) == 0 || !field.CanSet() { + continue + } + + isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous + isStruct := tpField.Type.Kind() == reflect.Struct + if isAnonymous { + field.Set(reflect.New(tpField.Type.Elem())) + } + + if isAnonymous || isStruct { + if sec, err := s.f.GetSection(fieldName); err == nil { + if err = sec.mapTo(field); err != nil { + return fmt.Errorf("error mapping field(%s): %v", fieldName, err) + } + continue + } + } + + if key, err := s.GetKey(fieldName); err == nil { + if err = setWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { + return fmt.Errorf("error mapping field(%s): %v", fieldName, err) + } + } + } + return nil +} + +// MapTo maps section to given struct. +func (s *Section) MapTo(v interface{}) error { + typ := reflect.TypeOf(v) + val := reflect.ValueOf(v) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + val = val.Elem() + } else { + return errors.New("cannot map to non-pointer struct") + } + + return s.mapTo(val) +} + +// MapTo maps file to given struct. +func (f *File) MapTo(v interface{}) error { + return f.Section("").MapTo(v) +} + +// MapTo maps data sources to given struct with name mapper. +func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { + cfg, err := Load(source, others...) + if err != nil { + return err + } + cfg.NameMapper = mapper + return cfg.MapTo(v) +} + +// MapTo maps data sources to given struct. +func MapTo(v, source interface{}, others ...interface{}) error { + return MapToWithMapper(v, nil, source, others...) +} + +// reflectWithProperType does the opposite thing with setWithProperType. +func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error { + switch t.Kind() { + case reflect.String: + key.SetValue(field.String()) + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float64, + reflectTime: + key.SetValue(fmt.Sprint(field)) + case reflect.Slice: + vals := field.Slice(0, field.Len()) + if field.Len() == 0 { + return nil + } + + var buf bytes.Buffer + isTime := fmt.Sprint(field.Type()) == "[]time.Time" + for i := 0; i < field.Len(); i++ { + if isTime { + buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339)) + } else { + buf.WriteString(fmt.Sprint(vals.Index(i))) + } + buf.WriteString(delim) + } + key.SetValue(buf.String()[:buf.Len()-1]) + default: + return fmt.Errorf("unsupported type '%s'", t) + } + return nil +} + +func (s *Section) reflectFrom(val reflect.Value) error { + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + typ := val.Type() + + for i := 0; i < typ.NumField(); i++ { + field := val.Field(i) + tpField := typ.Field(i) + + tag := tpField.Tag.Get("ini") + if tag == "-" { + continue + } + + fieldName := s.parseFieldName(tpField.Name, tag) + if len(fieldName) == 0 || !field.CanSet() { + continue + } + + if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) || + (tpField.Type.Kind() == reflect.Struct) { + // Note: The only error here is section doesn't exist. + sec, err := s.f.GetSection(fieldName) + if err != nil { + // Note: fieldName can never be empty here, ignore error. + sec, _ = s.f.NewSection(fieldName) + } + if err = sec.reflectFrom(field); err != nil { + return fmt.Errorf("error reflecting field(%s): %v", fieldName, err) + } + continue + } + + // Note: Same reason as secion. + key, err := s.GetKey(fieldName) + if err != nil { + key, _ = s.NewKey(fieldName, "") + } + if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { + return fmt.Errorf("error reflecting field(%s): %v", fieldName, err) + } + + } + return nil +} + +// ReflectFrom reflects secion from given struct. +func (s *Section) ReflectFrom(v interface{}) error { + typ := reflect.TypeOf(v) + val := reflect.ValueOf(v) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + val = val.Elem() + } else { + return errors.New("cannot reflect from non-pointer struct") + } + + return s.reflectFrom(val) +} + +// ReflectFrom reflects file from given struct. +func (f *File) ReflectFrom(v interface{}) error { + return f.Section("").ReflectFrom(v) +} + +// ReflectFrom reflects data sources from given struct with name mapper. +func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error { + cfg.NameMapper = mapper + return cfg.ReflectFrom(v) +} + +// ReflectFrom reflects data sources from given struct. +func ReflectFrom(cfg *File, v interface{}) error { + return ReflectFromWithMapper(cfg, v, nil) +} diff --git a/vendor/github.com/golang/protobuf/LICENSE b/vendor/github.com/golang/protobuf/LICENSE new file mode 100644 index 000000000..1b1b1921e --- /dev/null +++ b/vendor/github.com/golang/protobuf/LICENSE @@ -0,0 +1,31 @@ +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile new file mode 100644 index 000000000..f1f06564a --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/Makefile @@ -0,0 +1,43 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +install: + go install + +test: install generate-test-pbs + go test + + +generate-test-pbs: + make install + make -C testdata + protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto + make diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go new file mode 100644 index 000000000..e98ddec98 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/clone.go @@ -0,0 +1,223 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Protocol buffer deep copy and merge. +// TODO: RawMessage. + +package proto + +import ( + "log" + "reflect" + "strings" +) + +// Clone returns a deep copy of a protocol buffer. +func Clone(pb Message) Message { + in := reflect.ValueOf(pb) + if in.IsNil() { + return pb + } + + out := reflect.New(in.Type().Elem()) + // out is empty so a merge is a deep copy. + mergeStruct(out.Elem(), in.Elem()) + return out.Interface().(Message) +} + +// Merge merges src into dst. +// Required and optional fields that are set in src will be set to that value in dst. +// Elements of repeated fields will be appended. +// Merge panics if src and dst are not the same type, or if dst is nil. +func Merge(dst, src Message) { + in := reflect.ValueOf(src) + out := reflect.ValueOf(dst) + if out.IsNil() { + panic("proto: nil destination") + } + if in.Type() != out.Type() { + // Explicit test prior to mergeStruct so that mistyped nils will fail + panic("proto: type mismatch") + } + if in.IsNil() { + // Merging nil into non-nil is a quiet no-op + return + } + mergeStruct(out.Elem(), in.Elem()) +} + +func mergeStruct(out, in reflect.Value) { + sprop := GetProperties(in.Type()) + for i := 0; i < in.NumField(); i++ { + f := in.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) + } + + if emIn, ok := in.Addr().Interface().(extendableProto); ok { + emOut := out.Addr().Interface().(extendableProto) + mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) + } + + uf := in.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return + } + uin := uf.Bytes() + if len(uin) > 0 { + out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) + } +} + +// mergeAny performs a merge between two values of the same type. +// viaPtr indicates whether the values were indirected through a pointer (implying proto2). +// prop is set if this is a struct field (it may be nil). +func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { + if in.Type() == protoMessageType { + if !in.IsNil() { + if out.IsNil() { + out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) + } else { + Merge(out.Interface().(Message), in.Interface().(Message)) + } + } + return + } + switch in.Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + if !viaPtr && isProto3Zero(in) { + return + } + out.Set(in) + case reflect.Interface: + // Probably a oneof field; copy non-nil values. + if in.IsNil() { + return + } + // Allocate destination if it is not set, or set to a different type. + // Otherwise we will merge as normal. + if out.IsNil() || out.Elem().Type() != in.Elem().Type() { + out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) + } + mergeAny(out.Elem(), in.Elem(), false, nil) + case reflect.Map: + if in.Len() == 0 { + return + } + if out.IsNil() { + out.Set(reflect.MakeMap(in.Type())) + } + // For maps with value types of *T or []byte we need to deep copy each value. + elemKind := in.Type().Elem().Kind() + for _, key := range in.MapKeys() { + var val reflect.Value + switch elemKind { + case reflect.Ptr: + val = reflect.New(in.Type().Elem().Elem()) + mergeAny(val, in.MapIndex(key), false, nil) + case reflect.Slice: + val = in.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + default: + val = in.MapIndex(key) + } + out.SetMapIndex(key, val) + } + case reflect.Ptr: + if in.IsNil() { + return + } + if out.IsNil() { + out.Set(reflect.New(in.Elem().Type())) + } + mergeAny(out.Elem(), in.Elem(), true, nil) + case reflect.Slice: + if in.IsNil() { + return + } + if in.Type().Elem().Kind() == reflect.Uint8 { + // []byte is a scalar bytes field, not a repeated field. + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value, and should not + // be merged. + if prop != nil && prop.proto3 && in.Len() == 0 { + return + } + + // Make a deep copy. + // Append to []byte{} instead of []byte(nil) so that we never end up + // with a nil result. + out.SetBytes(append([]byte{}, in.Bytes()...)) + return + } + n := in.Len() + if out.IsNil() { + out.Set(reflect.MakeSlice(in.Type(), 0, n)) + } + switch in.Type().Elem().Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + out.Set(reflect.AppendSlice(out, in)) + default: + for i := 0; i < n; i++ { + x := reflect.Indirect(reflect.New(in.Type().Elem())) + mergeAny(x, in.Index(i), false, nil) + out.Set(reflect.Append(out, x)) + } + } + case reflect.Struct: + mergeStruct(out, in) + default: + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to copy %v", in) + } +} + +func mergeExtension(out, in map[int32]Extension) { + for extNum, eIn := range in { + eOut := Extension{desc: eIn.desc} + if eIn.value != nil { + v := reflect.New(reflect.TypeOf(eIn.value)).Elem() + mergeAny(v, reflect.ValueOf(eIn.value), false, nil) + eOut.value = v.Interface() + } + if eIn.enc != nil { + eOut.enc = make([]byte, len(eIn.enc)) + copy(eOut.enc, eIn.enc) + } + + out[extNum] = eOut + } +} diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go new file mode 100644 index 000000000..5810782fd --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/decode.go @@ -0,0 +1,867 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for decoding protocol buffer data to construct in-memory representations. + */ + +import ( + "errors" + "fmt" + "io" + "os" + "reflect" +) + +// errOverflow is returned when an integer is too large to be represented. +var errOverflow = errors.New("proto: integer overflow") + +// ErrInternalBadWireType is returned by generated code when an incorrect +// wire type is encountered. It does not get returned to user code. +var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") + +// The fundamental decoders that interpret bytes on the wire. +// Those that take integer types all return uint64 and are +// therefore of type valueDecoder. + +// DecodeVarint reads a varint-encoded integer from the slice. +// It returns the integer and the number of bytes consumed, or +// zero if there is not enough. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func DecodeVarint(buf []byte) (x uint64, n int) { + // x, n already 0 + for shift := uint(0); shift < 64; shift += 7 { + if n >= len(buf) { + return 0, 0 + } + b := uint64(buf[n]) + n++ + x |= (b & 0x7F) << shift + if (b & 0x80) == 0 { + return x, n + } + } + + // The number is too large to represent in a 64-bit value. + return 0, 0 +} + +// DecodeVarint reads a varint-encoded integer from the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) DecodeVarint() (x uint64, err error) { + // x, err already 0 + + i := p.index + l := len(p.buf) + + for shift := uint(0); shift < 64; shift += 7 { + if i >= l { + err = io.ErrUnexpectedEOF + return + } + b := p.buf[i] + i++ + x |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + p.index = i + return + } + } + + // The number is too large to represent in a 64-bit value. + err = errOverflow + return +} + +// DecodeFixed64 reads a 64-bit integer from the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) DecodeFixed64() (x uint64, err error) { + // x, err already 0 + i := p.index + 8 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-8]) + x |= uint64(p.buf[i-7]) << 8 + x |= uint64(p.buf[i-6]) << 16 + x |= uint64(p.buf[i-5]) << 24 + x |= uint64(p.buf[i-4]) << 32 + x |= uint64(p.buf[i-3]) << 40 + x |= uint64(p.buf[i-2]) << 48 + x |= uint64(p.buf[i-1]) << 56 + return +} + +// DecodeFixed32 reads a 32-bit integer from the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) DecodeFixed32() (x uint64, err error) { + // x, err already 0 + i := p.index + 4 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-4]) + x |= uint64(p.buf[i-3]) << 8 + x |= uint64(p.buf[i-2]) << 16 + x |= uint64(p.buf[i-1]) << 24 + return +} + +// DecodeZigzag64 reads a zigzag-encoded 64-bit integer +// from the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) DecodeZigzag64() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) + return +} + +// DecodeZigzag32 reads a zigzag-encoded 32-bit integer +// from the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) DecodeZigzag32() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) + return +} + +// These are not ValueDecoders: they produce an array of bytes or a string. +// bytes, embedded messages + +// DecodeRawBytes reads a count-delimited byte buffer from the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { + n, err := p.DecodeVarint() + if err != nil { + return nil, err + } + + nb := int(n) + if nb < 0 { + return nil, fmt.Errorf("proto: bad byte length %d", nb) + } + end := p.index + nb + if end < p.index || end > len(p.buf) { + return nil, io.ErrUnexpectedEOF + } + + if !alloc { + // todo: check if can get more uses of alloc=false + buf = p.buf[p.index:end] + p.index += nb + return + } + + buf = make([]byte, nb) + copy(buf, p.buf[p.index:]) + p.index += nb + return +} + +// DecodeStringBytes reads an encoded string from the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) DecodeStringBytes() (s string, err error) { + buf, err := p.DecodeRawBytes(false) + if err != nil { + return + } + return string(buf), nil +} + +// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. +// If the protocol buffer has extensions, and the field matches, add it as an extension. +// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. +func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { + oi := o.index + + err := o.skip(t, tag, wire) + if err != nil { + return err + } + + if !unrecField.IsValid() { + return nil + } + + ptr := structPointer_Bytes(base, unrecField) + + // Add the skipped field to struct field + obuf := o.buf + + o.buf = *ptr + o.EncodeVarint(uint64(tag<<3 | wire)) + *ptr = append(o.buf, obuf[oi:o.index]...) + + o.buf = obuf + + return nil +} + +// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. +func (o *Buffer) skip(t reflect.Type, tag, wire int) error { + + var u uint64 + var err error + + switch wire { + case WireVarint: + _, err = o.DecodeVarint() + case WireFixed64: + _, err = o.DecodeFixed64() + case WireBytes: + _, err = o.DecodeRawBytes(false) + case WireFixed32: + _, err = o.DecodeFixed32() + case WireStartGroup: + for { + u, err = o.DecodeVarint() + if err != nil { + break + } + fwire := int(u & 0x7) + if fwire == WireEndGroup { + break + } + ftag := int(u >> 3) + err = o.skip(t, ftag, fwire) + if err != nil { + break + } + } + default: + err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) + } + return err +} + +// Unmarshaler is the interface representing objects that can +// unmarshal themselves. The method should reset the receiver before +// decoding starts. The argument points to data that may be +// overwritten, so implementations should not keep references to the +// buffer. +type Unmarshaler interface { + Unmarshal([]byte) error +} + +// Unmarshal parses the protocol buffer representation in buf and places the +// decoded result in pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// Unmarshal resets pb before starting to unmarshal, so any +// existing data in pb is always removed. Use UnmarshalMerge +// to preserve and append to existing data. +func Unmarshal(buf []byte, pb Message) error { + pb.Reset() + return UnmarshalMerge(buf, pb) +} + +// UnmarshalMerge parses the protocol buffer representation in buf and +// writes the decoded result to pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// UnmarshalMerge merges into existing data in pb. +// Most code should use Unmarshal instead. +func UnmarshalMerge(buf []byte, pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// DecodeMessage reads a count-delimited message from the Buffer. +func (p *Buffer) DecodeMessage(pb Message) error { + enc, err := p.DecodeRawBytes(false) + if err != nil { + return err + } + return NewBuffer(enc).Unmarshal(pb) +} + +// DecodeGroup reads a tag-delimited group from the Buffer. +func (p *Buffer) DecodeGroup(pb Message) error { + typ, base, err := getbase(pb) + if err != nil { + return err + } + return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) +} + +// Unmarshal parses the protocol buffer representation in the +// Buffer and places the decoded result in pb. If the struct +// underlying pb does not match the data in the buffer, the results can be +// unpredictable. +func (p *Buffer) Unmarshal(pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(Unmarshaler); ok { + err := u.Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + + typ, base, err := getbase(pb) + if err != nil { + return err + } + + err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) + + if collectStats { + stats.Decode++ + } + + return err +} + +// unmarshalType does the work of unmarshaling a structure. +func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { + var state errorState + required, reqFields := prop.reqCount, uint64(0) + + var err error + for err == nil && o.index < len(o.buf) { + oi := o.index + var u uint64 + u, err = o.DecodeVarint() + if err != nil { + break + } + wire := int(u & 0x7) + if wire == WireEndGroup { + if is_group { + return nil // input is satisfied + } + return fmt.Errorf("proto: %s: wiretype end group for non-group", st) + } + tag := int(u >> 3) + if tag <= 0 { + return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) + } + fieldnum, ok := prop.decoderTags.get(tag) + if !ok { + // Maybe it's an extension? + if prop.extendable { + if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) { + if err = o.skip(st, tag, wire); err == nil { + ext := e.ExtensionMap()[int32(tag)] // may be missing + ext.enc = append(ext.enc, o.buf[oi:o.index]...) + e.ExtensionMap()[int32(tag)] = ext + } + continue + } + } + // Maybe it's a oneof? + if prop.oneofUnmarshaler != nil { + m := structPointer_Interface(base, st).(Message) + // First return value indicates whether tag is a oneof field. + ok, err = prop.oneofUnmarshaler(m, tag, wire, o) + if err == ErrInternalBadWireType { + // Map the error to something more descriptive. + // Do the formatting here to save generated code space. + err = fmt.Errorf("bad wiretype for oneof field in %T", m) + } + if ok { + continue + } + } + err = o.skipAndSave(st, tag, wire, base, prop.unrecField) + continue + } + p := prop.Prop[fieldnum] + + if p.dec == nil { + fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) + continue + } + dec := p.dec + if wire != WireStartGroup && wire != p.WireType { + if wire == WireBytes && p.packedDec != nil { + // a packable field + dec = p.packedDec + } else { + err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) + continue + } + } + decErr := dec(o, p, base) + if decErr != nil && !state.shouldContinue(decErr, p) { + err = decErr + } + if err == nil && p.Required { + // Successfully decoded a required field. + if tag <= 64 { + // use bitmap for fields 1-64 to catch field reuse. + var mask uint64 = 1 << uint64(tag-1) + if reqFields&mask == 0 { + // new required field + reqFields |= mask + required-- + } + } else { + // This is imprecise. It can be fooled by a required field + // with a tag > 64 that is encoded twice; that's very rare. + // A fully correct implementation would require allocating + // a data structure, which we would like to avoid. + required-- + } + } + } + if err == nil { + if is_group { + return io.ErrUnexpectedEOF + } + if state.err != nil { + return state.err + } + if required > 0 { + // Not enough information to determine the exact field. If we use extra + // CPU, we could determine the field only if the missing required field + // has a tag <= 64 and we check reqFields. + return &RequiredNotSetError{"{Unknown}"} + } + } + return err +} + +// Individual type decoders +// For each, +// u is the decoded value, +// v is a pointer to the field (pointer) in the struct + +// Sizes of the pools to allocate inside the Buffer. +// The goal is modest amortization and allocation +// on at least 16-byte boundaries. +const ( + boolPoolSize = 16 + uint32PoolSize = 8 + uint64PoolSize = 4 +) + +// Decode a bool. +func (o *Buffer) dec_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + if len(o.bools) == 0 { + o.bools = make([]bool, boolPoolSize) + } + o.bools[0] = u != 0 + *structPointer_Bool(base, p.field) = &o.bools[0] + o.bools = o.bools[1:] + return nil +} + +func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + *structPointer_BoolVal(base, p.field) = u != 0 + return nil +} + +// Decode an int32. +func (o *Buffer) dec_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) + return nil +} + +func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) + return nil +} + +// Decode an int64. +func (o *Buffer) dec_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word64_Set(structPointer_Word64(base, p.field), o, u) + return nil +} + +func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word64Val_Set(structPointer_Word64Val(base, p.field), o, u) + return nil +} + +// Decode a string. +func (o *Buffer) dec_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + *structPointer_String(base, p.field) = &s + return nil +} + +func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + *structPointer_StringVal(base, p.field) = s + return nil +} + +// Decode a slice of bytes ([]byte). +func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { + b, err := o.DecodeRawBytes(true) + if err != nil { + return err + } + *structPointer_Bytes(base, p.field) = b + return nil +} + +// Decode a slice of bools ([]bool). +func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + v := structPointer_BoolSlice(base, p.field) + *v = append(*v, u != 0) + return nil +} + +// Decode a slice of bools ([]bool) in packed format. +func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { + v := structPointer_BoolSlice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded bools + fin := o.index + nb + if fin < o.index { + return errOverflow + } + + y := *v + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + y = append(y, u != 0) + } + + *v = y + return nil +} + +// Decode a slice of int32s ([]int32). +func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + structPointer_Word32Slice(base, p.field).Append(uint32(u)) + return nil +} + +// Decode a slice of int32s ([]int32) in packed format. +func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { + v := structPointer_Word32Slice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded int32s + + fin := o.index + nb + if fin < o.index { + return errOverflow + } + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + v.Append(uint32(u)) + } + return nil +} + +// Decode a slice of int64s ([]int64). +func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + + structPointer_Word64Slice(base, p.field).Append(u) + return nil +} + +// Decode a slice of int64s ([]int64) in packed format. +func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { + v := structPointer_Word64Slice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded int64s + + fin := o.index + nb + if fin < o.index { + return errOverflow + } + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + v.Append(u) + } + return nil +} + +// Decode a slice of strings ([]string). +func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + v := structPointer_StringSlice(base, p.field) + *v = append(*v, s) + return nil +} + +// Decode a slice of slice of bytes ([][]byte). +func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { + b, err := o.DecodeRawBytes(true) + if err != nil { + return err + } + v := structPointer_BytesSlice(base, p.field) + *v = append(*v, b) + return nil +} + +// Decode a map field. +func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { + raw, err := o.DecodeRawBytes(false) + if err != nil { + return err + } + oi := o.index // index at the end of this map entry + o.index -= len(raw) // move buffer back to start of map entry + + mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V + if mptr.Elem().IsNil() { + mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) + } + v := mptr.Elem() // map[K]V + + // Prepare addressable doubly-indirect placeholders for the key and value types. + // See enc_new_map for why. + keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K + keybase := toStructPointer(keyptr.Addr()) // **K + + var valbase structPointer + var valptr reflect.Value + switch p.mtype.Elem().Kind() { + case reflect.Slice: + // []byte + var dummy []byte + valptr = reflect.ValueOf(&dummy) // *[]byte + valbase = toStructPointer(valptr) // *[]byte + case reflect.Ptr: + // message; valptr is **Msg; need to allocate the intermediate pointer + valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V + valptr.Set(reflect.New(valptr.Type().Elem())) + valbase = toStructPointer(valptr) + default: + // everything else + valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V + valbase = toStructPointer(valptr.Addr()) // **V + } + + // Decode. + // This parses a restricted wire format, namely the encoding of a message + // with two fields. See enc_new_map for the format. + for o.index < oi { + // tagcode for key and value properties are always a single byte + // because they have tags 1 and 2. + tagcode := o.buf[o.index] + o.index++ + switch tagcode { + case p.mkeyprop.tagcode[0]: + if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { + return err + } + case p.mvalprop.tagcode[0]: + if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { + return err + } + default: + // TODO: Should we silently skip this instead? + return fmt.Errorf("proto: bad map data tag %d", raw[0]) + } + } + keyelem, valelem := keyptr.Elem(), valptr.Elem() + if !keyelem.IsValid() || !valelem.IsValid() { + // We did not decode the key or the value in the map entry. + // Either way, it's an invalid map entry. + return fmt.Errorf("proto: bad map data: missing key/val") + } + + v.SetMapIndex(keyelem, valelem) + return nil +} + +// Decode a group. +func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { + bas := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(bas) { + // allocate new nested message + bas = toStructPointer(reflect.New(p.stype)) + structPointer_SetStructPointer(base, p.field, bas) + } + return o.unmarshalType(p.stype, p.sprop, true, bas) +} + +// Decode an embedded message. +func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { + raw, e := o.DecodeRawBytes(false) + if e != nil { + return e + } + + bas := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(bas) { + // allocate new nested message + bas = toStructPointer(reflect.New(p.stype)) + structPointer_SetStructPointer(base, p.field, bas) + } + + // If the object can unmarshal itself, let it. + if p.isUnmarshaler { + iv := structPointer_Interface(bas, p.stype) + return iv.(Unmarshaler).Unmarshal(raw) + } + + obuf := o.buf + oi := o.index + o.buf = raw + o.index = 0 + + err = o.unmarshalType(p.stype, p.sprop, false, bas) + o.buf = obuf + o.index = oi + + return err +} + +// Decode a slice of embedded messages. +func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { + return o.dec_slice_struct(p, false, base) +} + +// Decode a slice of embedded groups. +func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { + return o.dec_slice_struct(p, true, base) +} + +// Decode a slice of structs ([]*struct). +func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { + v := reflect.New(p.stype) + bas := toStructPointer(v) + structPointer_StructPointerSlice(base, p.field).Append(bas) + + if is_group { + err := o.unmarshalType(p.stype, p.sprop, is_group, bas) + return err + } + + raw, err := o.DecodeRawBytes(false) + if err != nil { + return err + } + + // If the object can unmarshal itself, let it. + if p.isUnmarshaler { + iv := v.Interface() + return iv.(Unmarshaler).Unmarshal(raw) + } + + obuf := o.buf + oi := o.index + o.buf = raw + o.index = 0 + + err = o.unmarshalType(p.stype, p.sprop, is_group, bas) + + o.buf = obuf + o.index = oi + + return err +} diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go new file mode 100644 index 000000000..231b07401 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/encode.go @@ -0,0 +1,1325 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "errors" + "fmt" + "reflect" + "sort" +) + +// RequiredNotSetError is the error returned if Marshal is called with +// a protocol buffer struct whose required fields have not +// all been initialized. It is also the error returned if Unmarshal is +// called with an encoded protocol buffer that does not include all the +// required fields. +// +// When printed, RequiredNotSetError reports the first unset required field in a +// message. If the field cannot be precisely determined, it is reported as +// "{Unknown}". +type RequiredNotSetError struct { + field string +} + +func (e *RequiredNotSetError) Error() string { + return fmt.Sprintf("proto: required field %q not set", e.field) +} + +var ( + // errRepeatedHasNil is the error returned if Marshal is called with + // a struct with a repeated field containing a nil element. + errRepeatedHasNil = errors.New("proto: repeated field has nil element") + + // ErrNil is the error returned if Marshal is called with nil. + ErrNil = errors.New("proto: Marshal called with nil") +) + +// The fundamental encoders that put bytes on the wire. +// Those that take integer types all accept uint64 and are +// therefore of type valueEncoder. + +const maxVarintBytes = 10 // maximum length of a varint + +// EncodeVarint returns the varint encoding of x. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +// Not used by the package itself, but helpful to clients +// wishing to use the same encoding. +func EncodeVarint(x uint64) []byte { + var buf [maxVarintBytes]byte + var n int + for n = 0; x > 127; n++ { + buf[n] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + buf[n] = uint8(x) + n++ + return buf[0:n] +} + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + p.buf = append(p.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + p.buf = append(p.buf, uint8(x)) + return nil +} + +// SizeVarint returns the varint encoding size of an integer. +func SizeVarint(x uint64) int { + return sizeVarint(x) +} + +func sizeVarint(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) EncodeFixed64(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +func sizeFixed64(x uint64) int { + return 8 +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) EncodeFixed32(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +func sizeFixed32(x uint64) int { + return 4 +} + +// EncodeZigzag64 writes a zigzag-encoded 64-bit integer +// to the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) EncodeZigzag64(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} + +func sizeZigzag64(x uint64) int { + return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} + +// EncodeZigzag32 writes a zigzag-encoded 32-bit integer +// to the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) EncodeZigzag32(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +func sizeZigzag32(x uint64) int { + return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) EncodeRawBytes(b []byte) error { + p.EncodeVarint(uint64(len(b))) + p.buf = append(p.buf, b...) + return nil +} + +func sizeRawBytes(b []byte) int { + return sizeVarint(uint64(len(b))) + + len(b) +} + +// EncodeStringBytes writes an encoded string to the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) EncodeStringBytes(s string) error { + p.EncodeVarint(uint64(len(s))) + p.buf = append(p.buf, s...) + return nil +} + +func sizeStringBytes(s string) int { + return sizeVarint(uint64(len(s))) + + len(s) +} + +// Marshaler is the interface representing objects that can marshal themselves. +type Marshaler interface { + Marshal() ([]byte, error) +} + +// Marshal takes the protocol buffer +// and encodes it into the wire format, returning the data. +func Marshal(pb Message) ([]byte, error) { + // Can the object marshal itself? + if m, ok := pb.(Marshaler); ok { + return m.Marshal() + } + p := NewBuffer(nil) + err := p.Marshal(pb) + var state errorState + if err != nil && !state.shouldContinue(err, nil) { + return nil, err + } + if p.buf == nil && err == nil { + // Return a non-nil slice on success. + return []byte{}, nil + } + return p.buf, err +} + +// EncodeMessage writes the protocol buffer to the Buffer, +// prefixed by a varint-encoded length. +func (p *Buffer) EncodeMessage(pb Message) error { + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return ErrNil + } + if err == nil { + var state errorState + err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) + } + return err +} + +// Marshal takes the protocol buffer +// and encodes it into the wire format, writing the result to the +// Buffer. +func (p *Buffer) Marshal(pb Message) error { + // Can the object marshal itself? + if m, ok := pb.(Marshaler); ok { + data, err := m.Marshal() + if err != nil { + return err + } + p.buf = append(p.buf, data...) + return nil + } + + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return ErrNil + } + if err == nil { + err = p.enc_struct(GetProperties(t.Elem()), base) + } + + if collectStats { + stats.Encode++ + } + + return err +} + +// Size returns the encoded size of a protocol buffer. +func Size(pb Message) (n int) { + // Can the object marshal itself? If so, Size is slow. + // TODO: add Size to Marshaler, or add a Sizer interface. + if m, ok := pb.(Marshaler); ok { + b, _ := m.Marshal() + return len(b) + } + + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return 0 + } + if err == nil { + n = size_struct(GetProperties(t.Elem()), base) + } + + if collectStats { + stats.Size++ + } + + return +} + +// Individual type encoders. + +// Encode a bool. +func (o *Buffer) enc_bool(p *Properties, base structPointer) error { + v := *structPointer_Bool(base, p.field) + if v == nil { + return ErrNil + } + x := 0 + if *v { + x = 1 + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { + v := *structPointer_BoolVal(base, p.field) + if !v { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, 1) + return nil +} + +func size_bool(p *Properties, base structPointer) int { + v := *structPointer_Bool(base, p.field) + if v == nil { + return 0 + } + return len(p.tagcode) + 1 // each bool takes exactly one byte +} + +func size_proto3_bool(p *Properties, base structPointer) int { + v := *structPointer_BoolVal(base, p.field) + if !v && !p.oneof { + return 0 + } + return len(p.tagcode) + 1 // each bool takes exactly one byte +} + +// Encode an int32. +func (o *Buffer) enc_int32(p *Properties, base structPointer) error { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return ErrNil + } + x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { + v := structPointer_Word32Val(base, p.field) + x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func size_int32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return 0 + } + x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +func size_proto3_int32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32Val(base, p.field) + x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +// Encode a uint32. +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return ErrNil + } + x := word32_Get(v) + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { + v := structPointer_Word32Val(base, p.field) + x := word32Val_Get(v) + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func size_uint32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return 0 + } + x := word32_Get(v) + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +func size_proto3_uint32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32Val(base, p.field) + x := word32Val_Get(v) + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +// Encode an int64. +func (o *Buffer) enc_int64(p *Properties, base structPointer) error { + v := structPointer_Word64(base, p.field) + if word64_IsNil(v) { + return ErrNil + } + x := word64_Get(v) + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, x) + return nil +} + +func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { + v := structPointer_Word64Val(base, p.field) + x := word64Val_Get(v) + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, x) + return nil +} + +func size_int64(p *Properties, base structPointer) (n int) { + v := structPointer_Word64(base, p.field) + if word64_IsNil(v) { + return 0 + } + x := word64_Get(v) + n += len(p.tagcode) + n += p.valSize(x) + return +} + +func size_proto3_int64(p *Properties, base structPointer) (n int) { + v := structPointer_Word64Val(base, p.field) + x := word64Val_Get(v) + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(x) + return +} + +// Encode a string. +func (o *Buffer) enc_string(p *Properties, base structPointer) error { + v := *structPointer_String(base, p.field) + if v == nil { + return ErrNil + } + x := *v + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(x) + return nil +} + +func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { + v := *structPointer_StringVal(base, p.field) + if v == "" { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(v) + return nil +} + +func size_string(p *Properties, base structPointer) (n int) { + v := *structPointer_String(base, p.field) + if v == nil { + return 0 + } + x := *v + n += len(p.tagcode) + n += sizeStringBytes(x) + return +} + +func size_proto3_string(p *Properties, base structPointer) (n int) { + v := *structPointer_StringVal(base, p.field) + if v == "" && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeStringBytes(v) + return +} + +// All protocol buffer fields are nillable, but be careful. +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} + +// Encode a message struct. +func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { + var state errorState + structp := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(structp) { + return ErrNil + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, err := m.Marshal() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(data) + return state.err + } + + o.buf = append(o.buf, p.tagcode...) + return o.enc_len_struct(p.sprop, structp, &state) +} + +func size_struct_message(p *Properties, base structPointer) int { + structp := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(structp) { + return 0 + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, _ := m.Marshal() + n0 := len(p.tagcode) + n1 := sizeRawBytes(data) + return n0 + n1 + } + + n0 := len(p.tagcode) + n1 := size_struct(p.sprop, structp) + n2 := sizeVarint(uint64(n1)) // size of encoded length + return n0 + n1 + n2 +} + +// Encode a group struct. +func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { + var state errorState + b := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(b) { + return ErrNil + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) + err := o.enc_struct(p.sprop, b) + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) + return state.err +} + +func size_struct_group(p *Properties, base structPointer) (n int) { + b := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(b) { + return 0 + } + + n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) + n += size_struct(p.sprop, b) + n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) + return +} + +// Encode a slice of bools ([]bool). +func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return ErrNil + } + for _, x := range s { + o.buf = append(o.buf, p.tagcode...) + v := uint64(0) + if x { + v = 1 + } + p.valEnc(o, v) + } + return nil +} + +func size_slice_bool(p *Properties, base structPointer) int { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return 0 + } + return l * (len(p.tagcode) + 1) // each bool takes exactly one byte +} + +// Encode a slice of bools ([]bool) in packed format. +func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(l)) // each bool takes exactly one byte + for _, x := range s { + v := uint64(0) + if x { + v = 1 + } + p.valEnc(o, v) + } + return nil +} + +func size_slice_packed_bool(p *Properties, base structPointer) (n int) { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return 0 + } + n += len(p.tagcode) + n += sizeVarint(uint64(l)) + n += l // each bool takes exactly one byte + return +} + +// Encode a slice of bytes ([]byte). +func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { + s := *structPointer_Bytes(base, p.field) + if s == nil { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(s) + return nil +} + +func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { + s := *structPointer_Bytes(base, p.field) + if len(s) == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(s) + return nil +} + +func size_slice_byte(p *Properties, base structPointer) (n int) { + s := *structPointer_Bytes(base, p.field) + if s == nil && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeRawBytes(s) + return +} + +func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { + s := *structPointer_Bytes(base, p.field) + if len(s) == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeRawBytes(s) + return +} + +// Encode a slice of int32s ([]int32). +func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + p.valEnc(o, uint64(x)) + } + return nil +} + +func size_slice_int32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + n += p.valSize(uint64(x)) + } + return +} + +// Encode a slice of int32s ([]int32) in packed format. +func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + p.valEnc(buf, uint64(x)) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_int32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + bufSize += p.valSize(uint64(x)) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of uint32s ([]uint32). +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + x := s.Index(i) + p.valEnc(o, uint64(x)) + } + return nil +} + +func size_slice_uint32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + x := s.Index(i) + n += p.valSize(uint64(x)) + } + return +} + +// Encode a slice of uint32s ([]uint32) in packed format. +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + p.valEnc(buf, uint64(s.Index(i))) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + bufSize += p.valSize(uint64(s.Index(i))) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of int64s ([]int64). +func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, s.Index(i)) + } + return nil +} + +func size_slice_int64(p *Properties, base structPointer) (n int) { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + n += p.valSize(s.Index(i)) + } + return +} + +// Encode a slice of int64s ([]int64) in packed format. +func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + p.valEnc(buf, s.Index(i)) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_int64(p *Properties, base structPointer) (n int) { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + bufSize += p.valSize(s.Index(i)) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of slice of bytes ([][]byte). +func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { + ss := *structPointer_BytesSlice(base, p.field) + l := len(ss) + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(ss[i]) + } + return nil +} + +func size_slice_slice_byte(p *Properties, base structPointer) (n int) { + ss := *structPointer_BytesSlice(base, p.field) + l := len(ss) + if l == 0 { + return 0 + } + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + n += sizeRawBytes(ss[i]) + } + return +} + +// Encode a slice of strings ([]string). +func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { + ss := *structPointer_StringSlice(base, p.field) + l := len(ss) + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(ss[i]) + } + return nil +} + +func size_slice_string(p *Properties, base structPointer) (n int) { + ss := *structPointer_StringSlice(base, p.field) + l := len(ss) + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + n += sizeStringBytes(ss[i]) + } + return +} + +// Encode a slice of message structs ([]*struct). +func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { + var state errorState + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + for i := 0; i < l; i++ { + structp := s.Index(i) + if structPointer_IsNil(structp) { + return errRepeatedHasNil + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, err := m.Marshal() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(data) + continue + } + + o.buf = append(o.buf, p.tagcode...) + err := o.enc_len_struct(p.sprop, structp, &state) + if err != nil && !state.shouldContinue(err, nil) { + if err == ErrNil { + return errRepeatedHasNil + } + return err + } + } + return state.err +} + +func size_slice_struct_message(p *Properties, base structPointer) (n int) { + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + structp := s.Index(i) + if structPointer_IsNil(structp) { + return // return the size up to this point + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, _ := m.Marshal() + n += len(p.tagcode) + n += sizeRawBytes(data) + continue + } + + n0 := size_struct(p.sprop, structp) + n1 := sizeVarint(uint64(n0)) // size of encoded length + n += n0 + n1 + } + return +} + +// Encode a slice of group structs ([]*struct). +func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { + var state errorState + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + for i := 0; i < l; i++ { + b := s.Index(i) + if structPointer_IsNil(b) { + return errRepeatedHasNil + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) + + err := o.enc_struct(p.sprop, b) + + if err != nil && !state.shouldContinue(err, nil) { + if err == ErrNil { + return errRepeatedHasNil + } + return err + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) + } + return state.err +} + +func size_slice_struct_group(p *Properties, base structPointer) (n int) { + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) + n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) + for i := 0; i < l; i++ { + b := s.Index(i) + if structPointer_IsNil(b) { + return // return size up to this point + } + + n += size_struct(p.sprop, b) + } + return +} + +// Encode an extension map. +func (o *Buffer) enc_map(p *Properties, base structPointer) error { + v := *structPointer_ExtMap(base, p.field) + if err := encodeExtensionMap(v); err != nil { + return err + } + // Fast-path for common cases: zero or one extensions. + if len(v) <= 1 { + for _, e := range v { + o.buf = append(o.buf, e.enc...) + } + return nil + } + + // Sort keys to provide a deterministic encoding. + keys := make([]int, 0, len(v)) + for k := range v { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + o.buf = append(o.buf, v[int32(k)].enc...) + } + return nil +} + +func size_map(p *Properties, base structPointer) int { + v := *structPointer_ExtMap(base, p.field) + return sizeExtensionMap(v) +} + +// Encode a map field. +func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { + var state errorState // XXX: or do we need to plumb this through? + + /* + A map defined as + map map_field = N; + is encoded in the same way as + message MapFieldEntry { + key_type key = 1; + value_type value = 2; + } + repeated MapFieldEntry map_field = N; + */ + + v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V + if v.Len() == 0 { + return nil + } + + keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) + + enc := func() error { + if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { + return err + } + if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { + return err + } + return nil + } + + // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. + for _, key := range v.MapKeys() { + val := v.MapIndex(key) + + // The only illegal map entry values are nil message pointers. + if val.Kind() == reflect.Ptr && val.IsNil() { + return errors.New("proto: map has nil element") + } + + keycopy.Set(key) + valcopy.Set(val) + + o.buf = append(o.buf, p.tagcode...) + if err := o.enc_len_thing(enc, &state); err != nil { + return err + } + } + return nil +} + +func size_new_map(p *Properties, base structPointer) int { + v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V + + keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) + + n := 0 + for _, key := range v.MapKeys() { + val := v.MapIndex(key) + keycopy.Set(key) + valcopy.Set(val) + + // Tag codes for key and val are the responsibility of the sub-sizer. + keysize := p.mkeyprop.size(p.mkeyprop, keybase) + valsize := p.mvalprop.size(p.mvalprop, valbase) + entry := keysize + valsize + // Add on tag code and length of map entry itself. + n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry + } + return n +} + +// mapEncodeScratch returns a new reflect.Value matching the map's value type, +// and a structPointer suitable for passing to an encoder or sizer. +func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { + // Prepare addressable doubly-indirect placeholders for the key and value types. + // This is needed because the element-type encoders expect **T, but the map iteration produces T. + + keycopy = reflect.New(mapType.Key()).Elem() // addressable K + keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K + keyptr.Set(keycopy.Addr()) // + keybase = toStructPointer(keyptr.Addr()) // **K + + // Value types are more varied and require special handling. + switch mapType.Elem().Kind() { + case reflect.Slice: + // []byte + var dummy []byte + valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte + valbase = toStructPointer(valcopy.Addr()) + case reflect.Ptr: + // message; the generated field type is map[K]*Msg (so V is *Msg), + // so we only need one level of indirection. + valcopy = reflect.New(mapType.Elem()).Elem() // addressable V + valbase = toStructPointer(valcopy.Addr()) + default: + // everything else + valcopy = reflect.New(mapType.Elem()).Elem() // addressable V + valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V + valptr.Set(valcopy.Addr()) // + valbase = toStructPointer(valptr.Addr()) // **V + } + return +} + +// Encode a struct. +func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { + var state errorState + // Encode fields in tag order so that decoders may use optimizations + // that depend on the ordering. + // https://developers.google.com/protocol-buffers/docs/encoding#order + for _, i := range prop.order { + p := prop.Prop[i] + if p.enc != nil { + err := p.enc(o, p, base) + if err != nil { + if err == ErrNil { + if p.Required && state.err == nil { + state.err = &RequiredNotSetError{p.Name} + } + } else if err == errRepeatedHasNil { + // Give more context to nil values in repeated fields. + return errors.New("repeated field " + p.OrigName + " has nil element") + } else if !state.shouldContinue(err, p) { + return err + } + } + } + } + + // Do oneof fields. + if prop.oneofMarshaler != nil { + m := structPointer_Interface(base, prop.stype).(Message) + if err := prop.oneofMarshaler(m, o); err != nil { + return err + } + } + + // Add unrecognized fields at the end. + if prop.unrecField.IsValid() { + v := *structPointer_Bytes(base, prop.unrecField) + if len(v) > 0 { + o.buf = append(o.buf, v...) + } + } + + return state.err +} + +func size_struct(prop *StructProperties, base structPointer) (n int) { + for _, i := range prop.order { + p := prop.Prop[i] + if p.size != nil { + n += p.size(p, base) + } + } + + // Add unrecognized fields at the end. + if prop.unrecField.IsValid() { + v := *structPointer_Bytes(base, prop.unrecField) + n += len(v) + } + + // Factor in any oneof fields. + if prop.oneofSizer != nil { + m := structPointer_Interface(base, prop.stype).(Message) + n += prop.oneofSizer(m) + } + + return +} + +var zeroes [20]byte // longer than any conceivable sizeVarint + +// Encode a struct, preceded by its encoded length (as a varint). +func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { + return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) +} + +// Encode something, preceded by its encoded length (as a varint). +func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { + iLen := len(o.buf) + o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length + iMsg := len(o.buf) + err := enc() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + lMsg := len(o.buf) - iMsg + lLen := sizeVarint(uint64(lMsg)) + switch x := lLen - (iMsg - iLen); { + case x > 0: // actual length is x bytes larger than the space we reserved + // Move msg x bytes right. + o.buf = append(o.buf, zeroes[:x]...) + copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) + case x < 0: // actual length is x bytes smaller than the space we reserved + // Move msg x bytes left. + copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) + o.buf = o.buf[:len(o.buf)+x] // x is negative + } + // Encode the length in the reserved space. + o.buf = o.buf[:iLen] + o.EncodeVarint(uint64(lMsg)) + o.buf = o.buf[:len(o.buf)+lMsg] + return state.err +} + +// errorState maintains the first error that occurs and updates that error +// with additional context. +type errorState struct { + err error +} + +// shouldContinue reports whether encoding should continue upon encountering the +// given error. If the error is RequiredNotSetError, shouldContinue returns true +// and, if this is the first appearance of that error, remembers it for future +// reporting. +// +// If prop is not nil, it may update any error with additional context about the +// field with the error. +func (s *errorState) shouldContinue(err error, prop *Properties) bool { + // Ignore unset required fields. + reqNotSet, ok := err.(*RequiredNotSetError) + if !ok { + return false + } + if s.err == nil { + if prop != nil { + err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} + } + s.err = err + } + return true +} diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go new file mode 100644 index 000000000..f5db1def3 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/equal.go @@ -0,0 +1,276 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Protocol buffer comparison. + +package proto + +import ( + "bytes" + "log" + "reflect" + "strings" +) + +/* +Equal returns true iff protocol buffers a and b are equal. +The arguments must both be pointers to protocol buffer structs. + +Equality is defined in this way: + - Two messages are equal iff they are the same type, + corresponding fields are equal, unknown field sets + are equal, and extensions sets are equal. + - Two set scalar fields are equal iff their values are equal. + If the fields are of a floating-point type, remember that + NaN != x for all x, including NaN. If the message is defined + in a proto3 .proto file, fields are not "set"; specifically, + zero length proto3 "bytes" fields are equal (nil == {}). + - Two repeated fields are equal iff their lengths are the same, + and their corresponding elements are equal (a "bytes" field, + although represented by []byte, is not a repeated field) + - Two unset fields are equal. + - Two unknown field sets are equal if their current + encoded state is equal. + - Two extension sets are equal iff they have corresponding + elements that are pairwise equal. + - Every other combination of things are not equal. + +The return value is undefined if a and b are not protocol buffers. +*/ +func Equal(a, b Message) bool { + if a == nil || b == nil { + return a == b + } + v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) + if v1.Type() != v2.Type() { + return false + } + if v1.Kind() == reflect.Ptr { + if v1.IsNil() { + return v2.IsNil() + } + if v2.IsNil() { + return false + } + v1, v2 = v1.Elem(), v2.Elem() + } + if v1.Kind() != reflect.Struct { + return false + } + return equalStruct(v1, v2) +} + +// v1 and v2 are known to have the same type. +func equalStruct(v1, v2 reflect.Value) bool { + sprop := GetProperties(v1.Type()) + for i := 0; i < v1.NumField(); i++ { + f := v1.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + f1, f2 := v1.Field(i), v2.Field(i) + if f.Type.Kind() == reflect.Ptr { + if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { + // both unset + continue + } else if n1 != n2 { + // set/unset mismatch + return false + } + b1, ok := f1.Interface().(raw) + if ok { + b2 := f2.Interface().(raw) + // RawMessage + if !bytes.Equal(b1.Bytes(), b2.Bytes()) { + return false + } + continue + } + f1, f2 = f1.Elem(), f2.Elem() + } + if !equalAny(f1, f2, sprop.Prop[i]) { + return false + } + } + + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_extensions") + if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + return false + } + } + + uf := v1.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return true + } + + u1 := uf.Bytes() + u2 := v2.FieldByName("XXX_unrecognized").Bytes() + if !bytes.Equal(u1, u2) { + return false + } + + return true +} + +// v1 and v2 are known to have the same type. +// prop may be nil. +func equalAny(v1, v2 reflect.Value, prop *Properties) bool { + if v1.Type() == protoMessageType { + m1, _ := v1.Interface().(Message) + m2, _ := v2.Interface().(Message) + return Equal(m1, m2) + } + switch v1.Kind() { + case reflect.Bool: + return v1.Bool() == v2.Bool() + case reflect.Float32, reflect.Float64: + return v1.Float() == v2.Float() + case reflect.Int32, reflect.Int64: + return v1.Int() == v2.Int() + case reflect.Interface: + // Probably a oneof field; compare the inner values. + n1, n2 := v1.IsNil(), v2.IsNil() + if n1 || n2 { + return n1 == n2 + } + e1, e2 := v1.Elem(), v2.Elem() + if e1.Type() != e2.Type() { + return false + } + return equalAny(e1, e2, nil) + case reflect.Map: + if v1.Len() != v2.Len() { + return false + } + for _, key := range v1.MapKeys() { + val2 := v2.MapIndex(key) + if !val2.IsValid() { + // This key was not found in the second map. + return false + } + if !equalAny(v1.MapIndex(key), val2, nil) { + return false + } + } + return true + case reflect.Ptr: + return equalAny(v1.Elem(), v2.Elem(), prop) + case reflect.Slice: + if v1.Type().Elem().Kind() == reflect.Uint8 { + // short circuit: []byte + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value. + if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) + } + + if v1.Len() != v2.Len() { + return false + } + for i := 0; i < v1.Len(); i++ { + if !equalAny(v1.Index(i), v2.Index(i), prop) { + return false + } + } + return true + case reflect.String: + return v1.Interface().(string) == v2.Interface().(string) + case reflect.Struct: + return equalStruct(v1, v2) + case reflect.Uint32, reflect.Uint64: + return v1.Uint() == v2.Uint() + } + + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to compare %v", v1) + return false +} + +// base is the struct type that the extensions are based on. +// em1 and em2 are extension maps. +func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool { + if len(em1) != len(em2) { + return false + } + + for extNum, e1 := range em1 { + e2, ok := em2[extNum] + if !ok { + return false + } + + m1, m2 := e1.value, e2.value + + if m1 != nil && m2 != nil { + // Both are unencoded. + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + continue + } + + // At least one is encoded. To do a semantically correct comparison + // we need to unmarshal them first. + var desc *ExtensionDesc + if m := extensionMaps[base]; m != nil { + desc = m[extNum] + } + if desc == nil { + log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) + continue + } + var err error + if m1 == nil { + m1, err = decodeExtension(e1.enc, desc) + } + if m2 == nil && err == nil { + m2, err = decodeExtension(e2.enc, desc) + } + if err != nil { + // The encoded form is invalid. + log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) + return false + } + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + } + + return true +} diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go new file mode 100644 index 000000000..054f4f1df --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/extensions.go @@ -0,0 +1,399 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Types and routines for supporting protocol buffer extensions. + */ + +import ( + "errors" + "fmt" + "reflect" + "strconv" + "sync" +) + +// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. +var ErrMissingExtension = errors.New("proto: missing extension") + +// ExtensionRange represents a range of message extensions for a protocol buffer. +// Used in code generated by the protocol compiler. +type ExtensionRange struct { + Start, End int32 // both inclusive +} + +// extendableProto is an interface implemented by any protocol buffer that may be extended. +type extendableProto interface { + Message + ExtensionRangeArray() []ExtensionRange + ExtensionMap() map[int32]Extension +} + +var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() + +// ExtensionDesc represents an extension specification. +// Used in generated code from the protocol compiler. +type ExtensionDesc struct { + ExtendedType Message // nil pointer to the type that is being extended + ExtensionType interface{} // nil pointer to the extension type + Field int32 // field number + Name string // fully-qualified name of extension, for text formatting + Tag string // protobuf tag style +} + +func (ed *ExtensionDesc) repeated() bool { + t := reflect.TypeOf(ed.ExtensionType) + return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 +} + +// Extension represents an extension in a message. +type Extension struct { + // When an extension is stored in a message using SetExtension + // only desc and value are set. When the message is marshaled + // enc will be set to the encoded form of the message. + // + // When a message is unmarshaled and contains extensions, each + // extension will have only enc set. When such an extension is + // accessed using GetExtension (or GetExtensions) desc and value + // will be set. + desc *ExtensionDesc + value interface{} + enc []byte +} + +// SetRawExtension is for testing only. +func SetRawExtension(base extendableProto, id int32, b []byte) { + base.ExtensionMap()[id] = Extension{enc: b} +} + +// isExtensionField returns true iff the given field number is in an extension range. +func isExtensionField(pb extendableProto, field int32) bool { + for _, er := range pb.ExtensionRangeArray() { + if er.Start <= field && field <= er.End { + return true + } + } + return false +} + +// checkExtensionTypes checks that the given extension is valid for pb. +func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + // Check the extended type. + if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b { + return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) + } + // Check the range. + if !isExtensionField(pb, extension.Field) { + return errors.New("proto: bad extension number; not in declared ranges") + } + return nil +} + +// extPropKey is sufficient to uniquely identify an extension. +type extPropKey struct { + base reflect.Type + field int32 +} + +var extProp = struct { + sync.RWMutex + m map[extPropKey]*Properties +}{ + m: make(map[extPropKey]*Properties), +} + +func extensionProperties(ed *ExtensionDesc) *Properties { + key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} + + extProp.RLock() + if prop, ok := extProp.m[key]; ok { + extProp.RUnlock() + return prop + } + extProp.RUnlock() + + extProp.Lock() + defer extProp.Unlock() + // Check again. + if prop, ok := extProp.m[key]; ok { + return prop + } + + prop := new(Properties) + prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) + extProp.m[key] = prop + return prop +} + +// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. +func encodeExtensionMap(m map[int32]Extension) error { + for k, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + et := reflect.TypeOf(e.desc.ExtensionType) + props := extensionProperties(e.desc) + + p := NewBuffer(nil) + // If e.value has type T, the encoder expects a *struct{ X T }. + // Pass a *T with a zero field and hope it all works out. + x := reflect.New(et) + x.Elem().Set(reflect.ValueOf(e.value)) + if err := props.enc(p, props, toStructPointer(x)); err != nil { + return err + } + e.enc = p.buf + m[k] = e + } + return nil +} + +func sizeExtensionMap(m map[int32]Extension) (n int) { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + et := reflect.TypeOf(e.desc.ExtensionType) + props := extensionProperties(e.desc) + + // If e.value has type T, the encoder expects a *struct{ X T }. + // Pass a *T with a zero field and hope it all works out. + x := reflect.New(et) + x.Elem().Set(reflect.ValueOf(e.value)) + n += props.size(props, toStructPointer(x)) + } + return +} + +// HasExtension returns whether the given extension is present in pb. +func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { + // TODO: Check types, field numbers, etc.? + _, ok := pb.ExtensionMap()[extension.Field] + return ok +} + +// ClearExtension removes the given extension from pb. +func ClearExtension(pb extendableProto, extension *ExtensionDesc) { + // TODO: Check types, field numbers, etc.? + delete(pb.ExtensionMap(), extension.Field) +} + +// GetExtension parses and returns the given extension of pb. +// If the extension is not present and has no default value it returns ErrMissingExtension. +func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { + if err := checkExtensionTypes(pb, extension); err != nil { + return nil, err + } + + emap := pb.ExtensionMap() + e, ok := emap[extension.Field] + if !ok { + // defaultExtensionValue returns the default value or + // ErrMissingExtension if there is no default. + return defaultExtensionValue(extension) + } + + if e.value != nil { + // Already decoded. Check the descriptor, though. + if e.desc != extension { + // This shouldn't happen. If it does, it means that + // GetExtension was called twice with two different + // descriptors with the same field number. + return nil, errors.New("proto: descriptor conflict") + } + return e.value, nil + } + + v, err := decodeExtension(e.enc, extension) + if err != nil { + return nil, err + } + + // Remember the decoded version and drop the encoded version. + // That way it is safe to mutate what we return. + e.value = v + e.desc = extension + e.enc = nil + emap[extension.Field] = e + return e.value, nil +} + +// defaultExtensionValue returns the default value for extension. +// If no default for an extension is defined ErrMissingExtension is returned. +func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { + t := reflect.TypeOf(extension.ExtensionType) + props := extensionProperties(extension) + + sf, _, err := fieldDefault(t, props) + if err != nil { + return nil, err + } + + if sf == nil || sf.value == nil { + // There is no default value. + return nil, ErrMissingExtension + } + + if t.Kind() != reflect.Ptr { + // We do not need to return a Ptr, we can directly return sf.value. + return sf.value, nil + } + + // We need to return an interface{} that is a pointer to sf.value. + value := reflect.New(t).Elem() + value.Set(reflect.New(value.Type().Elem())) + if sf.kind == reflect.Int32 { + // We may have an int32 or an enum, but the underlying data is int32. + // Since we can't set an int32 into a non int32 reflect.value directly + // set it as a int32. + value.Elem().SetInt(int64(sf.value.(int32))) + } else { + value.Elem().Set(reflect.ValueOf(sf.value)) + } + return value.Interface(), nil +} + +// decodeExtension decodes an extension encoded in b. +func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { + o := NewBuffer(b) + + t := reflect.TypeOf(extension.ExtensionType) + + props := extensionProperties(extension) + + // t is a pointer to a struct, pointer to basic type or a slice. + // Allocate a "field" to store the pointer/slice itself; the + // pointer/slice will be stored here. We pass + // the address of this field to props.dec. + // This passes a zero field and a *t and lets props.dec + // interpret it as a *struct{ x t }. + value := reflect.New(t).Elem() + + for { + // Discard wire type and field number varint. It isn't needed. + if _, err := o.DecodeVarint(); err != nil { + return nil, err + } + + if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { + return nil, err + } + + if o.index >= len(o.buf) { + break + } + } + return value.Interface(), nil +} + +// GetExtensions returns a slice of the extensions present in pb that are also listed in es. +// The returned slice has the same length as es; missing extensions will appear as nil elements. +func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { + epb, ok := pb.(extendableProto) + if !ok { + err = errors.New("proto: not an extendable proto") + return + } + extensions = make([]interface{}, len(es)) + for i, e := range es { + extensions[i], err = GetExtension(epb, e) + if err == ErrMissingExtension { + err = nil + } + if err != nil { + return + } + } + return +} + +// SetExtension sets the specified extension of pb to the specified value. +func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { + if err := checkExtensionTypes(pb, extension); err != nil { + return err + } + typ := reflect.TypeOf(extension.ExtensionType) + if typ != reflect.TypeOf(value) { + return errors.New("proto: bad extension value type") + } + // nil extension values need to be caught early, because the + // encoder can't distinguish an ErrNil due to a nil extension + // from an ErrNil due to a missing field. Extensions are + // always optional, so the encoder would just swallow the error + // and drop all the extensions from the encoded message. + if reflect.ValueOf(value).IsNil() { + return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) + } + + pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value} + return nil +} + +// A global registry of extensions. +// The generated code will register the generated descriptors by calling RegisterExtension. + +var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) + +// RegisterExtension is called from the generated code. +func RegisterExtension(desc *ExtensionDesc) { + st := reflect.TypeOf(desc.ExtendedType).Elem() + m := extensionMaps[st] + if m == nil { + m = make(map[int32]*ExtensionDesc) + extensionMaps[st] = m + } + if _, ok := m[desc.Field]; ok { + panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) + } + m[desc.Field] = desc +} + +// RegisteredExtensions returns a map of the registered extensions of a +// protocol buffer struct, indexed by the extension number. +// The argument pb should be a nil pointer to the struct type. +func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { + return extensionMaps[reflect.TypeOf(pb).Elem()] +} diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go new file mode 100644 index 000000000..0de8f8dff --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/lib.go @@ -0,0 +1,894 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Package proto converts data structures to and from the wire format of +protocol buffers. It works in concert with the Go source code generated +for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed by the enclosing message's name, or by the + enum's type name if it is a top-level enum. Enum types have a String + method, and a Enum method to assist in message construction. + - Nested messages, groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Getters are only generated for message and oneof fields. + - Enum types do not get an Enum method. + +The simplest way to describe this is to see an example. +Given file test.proto, containing + + package example; + + enum FOO { X = 17; } + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + oneof union { + int32 number = 6; + string name = 7; + } + } + +The resulting file, test.pb.go, is: + + package example + + import proto "github.com/golang/protobuf/proto" + import math "math" + + type FOO int32 + const ( + FOO_X FOO = 17 + ) + var FOO_name = map[int32]string{ + 17: "X", + } + var FOO_value = map[string]int32{ + "X": 17, + } + + func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p + } + func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) + } + func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data) + if err != nil { + return err + } + *x = FOO(value) + return nil + } + + type Test struct { + Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` + Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` + Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` + Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` + // Types that are valid to be assigned to Union: + // *Test_Number + // *Test_Name + Union isTest_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` + } + func (m *Test) Reset() { *m = Test{} } + func (m *Test) String() string { return proto.CompactTextString(m) } + func (*Test) ProtoMessage() {} + + type isTest_Union interface { + isTest_Union() + } + + type Test_Number struct { + Number int32 `protobuf:"varint,6,opt,name=number"` + } + type Test_Name struct { + Name string `protobuf:"bytes,7,opt,name=name"` + } + + func (*Test_Number) isTest_Union() {} + func (*Test_Name) isTest_Union() {} + + func (m *Test) GetUnion() isTest_Union { + if m != nil { + return m.Union + } + return nil + } + const Default_Test_Type int32 = 77 + + func (m *Test) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" + } + + func (m *Test) GetType() int32 { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_Test_Type + } + + func (m *Test) GetOptionalgroup() *Test_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil + } + + type Test_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` + } + func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } + func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } + + func (m *Test_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" + } + + func (m *Test) GetNumber() int32 { + if x, ok := m.GetUnion().(*Test_Number); ok { + return x.Number + } + return 0 + } + + func (m *Test) GetName() string { + if x, ok := m.GetUnion().(*Test_Name); ok { + return x.Name + } + return "" + } + + func init() { + proto.RegisterEnum("example.FOO", FOO_name, FOO_value) + } + +To create and play with a Test object: + + package main + + import ( + "log" + + "github.com/golang/protobuf/proto" + pb "./example.pb" + ) + + func main() { + test := &pb.Test{ + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &pb.Test_OptionalGroup{ + RequiredField: proto.String("good bye"), + }, + Union: &pb.Test_Name{"fred"}, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &pb.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // Use a type switch to determine which oneof was set. + switch u := test.Union.(type) { + case *pb.Test_Number: // u.Number contains the number. + case *pb.Test_Name: // u.Name contains the string. + } + // etc. + } +*/ +package proto + +import ( + "encoding/json" + "fmt" + "log" + "reflect" + "sort" + "strconv" + "sync" +) + +// Message is implemented by generated protocol buffer messages. +type Message interface { + Reset() + String() string + ProtoMessage() +} + +// Stats records allocation details about the protocol buffer encoders +// and decoders. Useful for tuning the library itself. +type Stats struct { + Emalloc uint64 // mallocs in encode + Dmalloc uint64 // mallocs in decode + Encode uint64 // number of encodes + Decode uint64 // number of decodes + Chit uint64 // number of cache hits + Cmiss uint64 // number of cache misses + Size uint64 // number of sizes +} + +// Set to true to enable stats collection. +const collectStats = false + +var stats Stats + +// GetStats returns a copy of the global Stats structure. +func GetStats() Stats { return stats } + +// A Buffer is a buffer manager for marshaling and unmarshaling +// protocol buffers. It may be reused between invocations to +// reduce memory usage. It is not necessary to use a Buffer; +// the global functions Marshal and Unmarshal create a +// temporary Buffer and are fine for most applications. +type Buffer struct { + buf []byte // encode/decode byte stream + index int // write point + + // pools of basic types to amortize allocation. + bools []bool + uint32s []uint32 + uint64s []uint64 + + // extra pools, only used with pointer_reflect.go + int32s []int32 + int64s []int64 + float32s []float32 + float64s []float64 +} + +// NewBuffer allocates a new Buffer and initializes its internal data to +// the contents of the argument slice. +func NewBuffer(e []byte) *Buffer { + return &Buffer{buf: e} +} + +// Reset resets the Buffer, ready for marshaling a new protocol buffer. +func (p *Buffer) Reset() { + p.buf = p.buf[0:0] // for reading/writing + p.index = 0 // for reading +} + +// SetBuf replaces the internal buffer with the slice, +// ready for unmarshaling the contents of the slice. +func (p *Buffer) SetBuf(s []byte) { + p.buf = s + p.index = 0 +} + +// Bytes returns the contents of the Buffer. +func (p *Buffer) Bytes() []byte { return p.buf } + +/* + * Helper routines for simplifying the creation of optional fields of basic type. + */ + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + return &v +} + +// Int32 is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it. +func Int32(v int32) *int32 { + return &v +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int32 { + p := new(int32) + *p = int32(v) + return p +} + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { + return &v +} + +// Float32 is a helper routine that allocates a new float32 value +// to store v and returns a pointer to it. +func Float32(v float32) *float32 { + return &v +} + +// Float64 is a helper routine that allocates a new float64 value +// to store v and returns a pointer to it. +func Float64(v float64) *float64 { + return &v +} + +// Uint32 is a helper routine that allocates a new uint32 value +// to store v and returns a pointer to it. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint64 is a helper routine that allocates a new uint64 value +// to store v and returns a pointer to it. +func Uint64(v uint64) *uint64 { + return &v +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + return &v +} + +// EnumName is a helper function to simplify printing protocol buffer enums +// by name. Given an enum map and a value, it returns a useful string. +func EnumName(m map[int32]string, v int32) string { + s, ok := m[v] + if ok { + return s + } + return strconv.Itoa(int(v)) +} + +// UnmarshalJSONEnum is a helper function to simplify recovering enum int values +// from their JSON-encoded representation. Given a map from the enum's symbolic +// names to its int values, and a byte buffer containing the JSON-encoded +// value, it returns an int32 that can be cast to the enum type by the caller. +// +// The function can deal with both JSON representations, numeric and symbolic. +func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { + if data[0] == '"' { + // New style: enums are strings. + var repr string + if err := json.Unmarshal(data, &repr); err != nil { + return -1, err + } + val, ok := m[repr] + if !ok { + return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) + } + return val, nil + } + // Old style: enums are ints. + var val int32 + if err := json.Unmarshal(data, &val); err != nil { + return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) + } + return val, nil +} + +// DebugPrint dumps the encoded data in b in a debugging format with a header +// including the string s. Used in testing but made available for general debugging. +func (p *Buffer) DebugPrint(s string, b []byte) { + var u uint64 + + obuf := p.buf + index := p.index + p.buf = b + p.index = 0 + depth := 0 + + fmt.Printf("\n--- %s ---\n", s) + +out: + for { + for i := 0; i < depth; i++ { + fmt.Print(" ") + } + + index := p.index + if index == len(p.buf) { + break + } + + op, err := p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: fetching op err %v\n", index, err) + break out + } + tag := op >> 3 + wire := op & 7 + + switch wire { + default: + fmt.Printf("%3d: t=%3d unknown wire=%d\n", + index, tag, wire) + break out + + case WireBytes: + var r []byte + + r, err = p.DecodeRawBytes(false) + if err != nil { + break out + } + fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) + if len(r) <= 6 { + for i := 0; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } else { + for i := 0; i < 3; i++ { + fmt.Printf(" %.2x", r[i]) + } + fmt.Printf(" ..") + for i := len(r) - 3; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } + fmt.Printf("\n") + + case WireFixed32: + u, err = p.DecodeFixed32() + if err != nil { + fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) + + case WireFixed64: + u, err = p.DecodeFixed64() + if err != nil { + fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) + + case WireVarint: + u, err = p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) + + case WireStartGroup: + fmt.Printf("%3d: t=%3d start\n", index, tag) + depth++ + + case WireEndGroup: + depth-- + fmt.Printf("%3d: t=%3d end\n", index, tag) + } + } + + if depth != 0 { + fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) + } + fmt.Printf("\n") + + p.buf = obuf + p.index = index +} + +// SetDefaults sets unset protocol buffer fields to their default values. +// It only modifies fields that are both unset and have defined defaults. +// It recursively sets default values in any non-nil sub-messages. +func SetDefaults(pb Message) { + setDefaults(reflect.ValueOf(pb), true, false) +} + +// v is a pointer to a struct. +func setDefaults(v reflect.Value, recur, zeros bool) { + v = v.Elem() + + defaultMu.RLock() + dm, ok := defaults[v.Type()] + defaultMu.RUnlock() + if !ok { + dm = buildDefaultMessage(v.Type()) + defaultMu.Lock() + defaults[v.Type()] = dm + defaultMu.Unlock() + } + + for _, sf := range dm.scalars { + f := v.Field(sf.index) + if !f.IsNil() { + // field already set + continue + } + dv := sf.value + if dv == nil && !zeros { + // no explicit default, and don't want to set zeros + continue + } + fptr := f.Addr().Interface() // **T + // TODO: Consider batching the allocations we do here. + switch sf.kind { + case reflect.Bool: + b := new(bool) + if dv != nil { + *b = dv.(bool) + } + *(fptr.(**bool)) = b + case reflect.Float32: + f := new(float32) + if dv != nil { + *f = dv.(float32) + } + *(fptr.(**float32)) = f + case reflect.Float64: + f := new(float64) + if dv != nil { + *f = dv.(float64) + } + *(fptr.(**float64)) = f + case reflect.Int32: + // might be an enum + if ft := f.Type(); ft != int32PtrType { + // enum + f.Set(reflect.New(ft.Elem())) + if dv != nil { + f.Elem().SetInt(int64(dv.(int32))) + } + } else { + // int32 field + i := new(int32) + if dv != nil { + *i = dv.(int32) + } + *(fptr.(**int32)) = i + } + case reflect.Int64: + i := new(int64) + if dv != nil { + *i = dv.(int64) + } + *(fptr.(**int64)) = i + case reflect.String: + s := new(string) + if dv != nil { + *s = dv.(string) + } + *(fptr.(**string)) = s + case reflect.Uint8: + // exceptional case: []byte + var b []byte + if dv != nil { + db := dv.([]byte) + b = make([]byte, len(db)) + copy(b, db) + } else { + b = []byte{} + } + *(fptr.(*[]byte)) = b + case reflect.Uint32: + u := new(uint32) + if dv != nil { + *u = dv.(uint32) + } + *(fptr.(**uint32)) = u + case reflect.Uint64: + u := new(uint64) + if dv != nil { + *u = dv.(uint64) + } + *(fptr.(**uint64)) = u + default: + log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) + } + } + + for _, ni := range dm.nested { + f := v.Field(ni) + // f is *T or []*T or map[T]*T + switch f.Kind() { + case reflect.Ptr: + if f.IsNil() { + continue + } + setDefaults(f, recur, zeros) + + case reflect.Slice: + for i := 0; i < f.Len(); i++ { + e := f.Index(i) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + + case reflect.Map: + for _, k := range f.MapKeys() { + e := f.MapIndex(k) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + } + } +} + +var ( + // defaults maps a protocol buffer struct type to a slice of the fields, + // with its scalar fields set to their proto-declared non-zero default values. + defaultMu sync.RWMutex + defaults = make(map[reflect.Type]defaultMessage) + + int32PtrType = reflect.TypeOf((*int32)(nil)) +) + +// defaultMessage represents information about the default values of a message. +type defaultMessage struct { + scalars []scalarField + nested []int // struct field index of nested messages +} + +type scalarField struct { + index int // struct field index + kind reflect.Kind // element type (the T in *T or []T) + value interface{} // the proto-declared default value, or nil +} + +// t is a struct type. +func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { + sprop := GetProperties(t) + for _, prop := range sprop.Prop { + fi, ok := sprop.decoderTags.get(prop.Tag) + if !ok { + // XXX_unrecognized + continue + } + ft := t.Field(fi).Type + + sf, nested, err := fieldDefault(ft, prop) + switch { + case err != nil: + log.Print(err) + case nested: + dm.nested = append(dm.nested, fi) + case sf != nil: + sf.index = fi + dm.scalars = append(dm.scalars, *sf) + } + } + + return dm +} + +// fieldDefault returns the scalarField for field type ft. +// sf will be nil if the field can not have a default. +// nestedMessage will be true if this is a nested message. +// Note that sf.index is not set on return. +func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { + var canHaveDefault bool + switch ft.Kind() { + case reflect.Ptr: + if ft.Elem().Kind() == reflect.Struct { + nestedMessage = true + } else { + canHaveDefault = true // proto2 scalar field + } + + case reflect.Slice: + switch ft.Elem().Kind() { + case reflect.Ptr: + nestedMessage = true // repeated message + case reflect.Uint8: + canHaveDefault = true // bytes field + } + + case reflect.Map: + if ft.Elem().Kind() == reflect.Ptr { + nestedMessage = true // map with message values + } + } + + if !canHaveDefault { + if nestedMessage { + return nil, true, nil + } + return nil, false, nil + } + + // We now know that ft is a pointer or slice. + sf = &scalarField{kind: ft.Elem().Kind()} + + // scalar fields without defaults + if !prop.HasDefault { + return sf, false, nil + } + + // a scalar field: either *T or []byte + switch ft.Elem().Kind() { + case reflect.Bool: + x, err := strconv.ParseBool(prop.Default) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Float32: + x, err := strconv.ParseFloat(prop.Default, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) + } + sf.value = float32(x) + case reflect.Float64: + x, err := strconv.ParseFloat(prop.Default, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Int32: + x, err := strconv.ParseInt(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) + } + sf.value = int32(x) + case reflect.Int64: + x, err := strconv.ParseInt(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.String: + sf.value = prop.Default + case reflect.Uint8: + // []byte (not *uint8) + sf.value = []byte(prop.Default) + case reflect.Uint32: + x, err := strconv.ParseUint(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) + } + sf.value = uint32(x) + case reflect.Uint64: + x, err := strconv.ParseUint(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) + } + sf.value = x + default: + return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) + } + + return sf, false, nil +} + +// Map fields may have key types of non-float scalars, strings and enums. +// The easiest way to sort them in some deterministic order is to use fmt. +// If this turns out to be inefficient we can always consider other options, +// such as doing a Schwartzian transform. + +func mapKeys(vs []reflect.Value) sort.Interface { + s := mapKeySorter{ + vs: vs, + // default Less function: textual comparison + less: func(a, b reflect.Value) bool { + return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) + }, + } + + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; + // numeric keys are sorted numerically. + if len(vs) == 0 { + return s + } + switch vs[0].Kind() { + case reflect.Int32, reflect.Int64: + s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } + case reflect.Uint32, reflect.Uint64: + s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + } + + return s +} + +type mapKeySorter struct { + vs []reflect.Value + less func(a, b reflect.Value) bool +} + +func (s mapKeySorter) Len() int { return len(s.vs) } +func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } +func (s mapKeySorter) Less(i, j int) bool { + return s.less(s.vs[i], s.vs[j]) +} + +// isProto3Zero reports whether v is a zero proto3 value. +func isProto3Zero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return !v.Bool() + case reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint32, reflect.Uint64: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.String: + return v.String() == "" + } + return false +} + +// ProtoPackageIsVersion1 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion1 = true diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go new file mode 100644 index 000000000..e25e01e63 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/message_set.go @@ -0,0 +1,280 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Support for message sets. + */ + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" +) + +// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. +// A message type ID is required for storing a protocol buffer in a message set. +var errNoMessageTypeID = errors.New("proto does not have a message type ID") + +// The first two types (_MessageSet_Item and messageSet) +// model what the protocol compiler produces for the following protocol message: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } +// That is the MessageSet wire format. We can't use a proto to generate these +// because that would introduce a circular dependency between it and this package. + +type _MessageSet_Item struct { + TypeId *int32 `protobuf:"varint,2,req,name=type_id"` + Message []byte `protobuf:"bytes,3,req,name=message"` +} + +type messageSet struct { + Item []*_MessageSet_Item `protobuf:"group,1,rep"` + XXX_unrecognized []byte + // TODO: caching? +} + +// Make sure messageSet is a Message. +var _ Message = (*messageSet)(nil) + +// messageTypeIder is an interface satisfied by a protocol buffer type +// that may be stored in a MessageSet. +type messageTypeIder interface { + MessageTypeId() int32 +} + +func (ms *messageSet) find(pb Message) *_MessageSet_Item { + mti, ok := pb.(messageTypeIder) + if !ok { + return nil + } + id := mti.MessageTypeId() + for _, item := range ms.Item { + if *item.TypeId == id { + return item + } + } + return nil +} + +func (ms *messageSet) Has(pb Message) bool { + if ms.find(pb) != nil { + return true + } + return false +} + +func (ms *messageSet) Unmarshal(pb Message) error { + if item := ms.find(pb); item != nil { + return Unmarshal(item.Message, pb) + } + if _, ok := pb.(messageTypeIder); !ok { + return errNoMessageTypeID + } + return nil // TODO: return error instead? +} + +func (ms *messageSet) Marshal(pb Message) error { + msg, err := Marshal(pb) + if err != nil { + return err + } + if item := ms.find(pb); item != nil { + // reuse existing item + item.Message = msg + return nil + } + + mti, ok := pb.(messageTypeIder) + if !ok { + return errNoMessageTypeID + } + + mtid := mti.MessageTypeId() + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: &mtid, + Message: msg, + }) + return nil +} + +func (ms *messageSet) Reset() { *ms = messageSet{} } +func (ms *messageSet) String() string { return CompactTextString(ms) } +func (*messageSet) ProtoMessage() {} + +// Support for the message_set_wire_format message option. + +func skipVarint(buf []byte) []byte { + i := 0 + for ; buf[i]&0x80 != 0; i++ { + } + return buf[i+1:] +} + +// MarshalMessageSet encodes the extension map represented by m in the message set wire format. +// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { + if err := encodeExtensionMap(m); err != nil { + return nil, err + } + + // Sort extension IDs to provide a deterministic encoding. + // See also enc_map in encode.go. + ids := make([]int, 0, len(m)) + for id := range m { + ids = append(ids, int(id)) + } + sort.Ints(ids) + + ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} + for _, id := range ids { + e := m[int32(id)] + // Remove the wire type and field number varint, as well as the length varint. + msg := skipVarint(skipVarint(e.enc)) + + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: Int32(int32(id)), + Message: msg, + }) + } + return Marshal(ms) +} + +// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. +// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { + ms := new(messageSet) + if err := Unmarshal(buf, ms); err != nil { + return err + } + for _, item := range ms.Item { + id := *item.TypeId + msg := item.Message + + // Restore wire type and field number varint, plus length varint. + // Be careful to preserve duplicate items. + b := EncodeVarint(uint64(id)<<3 | WireBytes) + if ext, ok := m[id]; ok { + // Existing data; rip off the tag and length varint + // so we join the new data correctly. + // We can assume that ext.enc is set because we are unmarshaling. + o := ext.enc[len(b):] // skip wire type and field number + _, n := DecodeVarint(o) // calculate length of length varint + o = o[n:] // skip length varint + msg = append(o, msg...) // join old data and new data + } + b = append(b, EncodeVarint(uint64(len(msg)))...) + b = append(b, msg...) + + m[id] = Extension{enc: b} + } + return nil +} + +// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. +// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { + var b bytes.Buffer + b.WriteByte('{') + + // Process the map in key order for deterministic output. + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) // int32Slice defined in text.go + + for i, id := range ids { + ext := m[id] + if i > 0 { + b.WriteByte(',') + } + + msd, ok := messageSetMap[id] + if !ok { + // Unknown type; we can't render it, so skip it. + continue + } + fmt.Fprintf(&b, `"[%s]":`, msd.name) + + x := ext.value + if x == nil { + x = reflect.New(msd.t.Elem()).Interface() + if err := Unmarshal(ext.enc, x.(Message)); err != nil { + return nil, err + } + } + d, err := json.Marshal(x) + if err != nil { + return nil, err + } + b.Write(d) + } + b.WriteByte('}') + return b.Bytes(), nil +} + +// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. +// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { + // Common-case fast path. + if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { + return nil + } + + // This is fairly tricky, and it's not clear that it is needed. + return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") +} + +// A global registry of types that can be used in a MessageSet. + +var messageSetMap = make(map[int32]messageSetDesc) + +type messageSetDesc struct { + t reflect.Type // pointer to struct + name string +} + +// RegisterMessageSetType is called from the generated code. +func RegisterMessageSetType(m Message, fieldNum int32, name string) { + messageSetMap[fieldNum] = messageSetDesc{ + t: reflect.TypeOf(m), + name: name, + } +} diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go new file mode 100644 index 000000000..749919d25 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -0,0 +1,479 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build appengine + +// This file contains an implementation of proto field accesses using package reflect. +// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can +// be used on App Engine. + +package proto + +import ( + "math" + "reflect" +) + +// A structPointer is a pointer to a struct. +type structPointer struct { + v reflect.Value +} + +// toStructPointer returns a structPointer equivalent to the given reflect value. +// The reflect value must itself be a pointer to a struct. +func toStructPointer(v reflect.Value) structPointer { + return structPointer{v} +} + +// IsNil reports whether p is nil. +func structPointer_IsNil(p structPointer) bool { + return p.v.IsNil() +} + +// Interface returns the struct pointer as an interface value. +func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { + return p.v.Interface() +} + +// A field identifies a field in a struct, accessible from a structPointer. +// In this implementation, a field is identified by the sequence of field indices +// passed to reflect's FieldByIndex. +type field []int + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return f.Index +} + +// invalidField is an invalid field identifier. +var invalidField = field(nil) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { return f != nil } + +// field returns the given field in the struct as a reflect value. +func structPointer_field(p structPointer, f field) reflect.Value { + // Special case: an extension map entry with a value of type T + // passes a *T to the struct-handling code with a zero field, + // expecting that it will be treated as equivalent to *struct{ X T }, + // which has the same memory layout. We have to handle that case + // specially, because reflect will panic if we call FieldByIndex on a + // non-struct. + if f == nil { + return p.v.Elem() + } + + return p.v.Elem().FieldByIndex(f) +} + +// ifield returns the given field in the struct as an interface value. +func structPointer_ifield(p structPointer, f field) interface{} { + return structPointer_field(p, f).Addr().Interface() +} + +// Bytes returns the address of a []byte field in the struct. +func structPointer_Bytes(p structPointer, f field) *[]byte { + return structPointer_ifield(p, f).(*[]byte) +} + +// BytesSlice returns the address of a [][]byte field in the struct. +func structPointer_BytesSlice(p structPointer, f field) *[][]byte { + return structPointer_ifield(p, f).(*[][]byte) +} + +// Bool returns the address of a *bool field in the struct. +func structPointer_Bool(p structPointer, f field) **bool { + return structPointer_ifield(p, f).(**bool) +} + +// BoolVal returns the address of a bool field in the struct. +func structPointer_BoolVal(p structPointer, f field) *bool { + return structPointer_ifield(p, f).(*bool) +} + +// BoolSlice returns the address of a []bool field in the struct. +func structPointer_BoolSlice(p structPointer, f field) *[]bool { + return structPointer_ifield(p, f).(*[]bool) +} + +// String returns the address of a *string field in the struct. +func structPointer_String(p structPointer, f field) **string { + return structPointer_ifield(p, f).(**string) +} + +// StringVal returns the address of a string field in the struct. +func structPointer_StringVal(p structPointer, f field) *string { + return structPointer_ifield(p, f).(*string) +} + +// StringSlice returns the address of a []string field in the struct. +func structPointer_StringSlice(p structPointer, f field) *[]string { + return structPointer_ifield(p, f).(*[]string) +} + +// ExtMap returns the address of an extension map field in the struct. +func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { + return structPointer_ifield(p, f).(*map[int32]Extension) +} + +// NewAt returns the reflect.Value for a pointer to a field in the struct. +func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { + return structPointer_field(p, f).Addr() +} + +// SetStructPointer writes a *struct field in the struct. +func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { + structPointer_field(p, f).Set(q.v) +} + +// GetStructPointer reads a *struct field in the struct. +func structPointer_GetStructPointer(p structPointer, f field) structPointer { + return structPointer{structPointer_field(p, f)} +} + +// StructPointerSlice the address of a []*struct field in the struct. +func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { + return structPointerSlice{structPointer_field(p, f)} +} + +// A structPointerSlice represents the address of a slice of pointers to structs +// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. +type structPointerSlice struct { + v reflect.Value +} + +func (p structPointerSlice) Len() int { return p.v.Len() } +func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } +func (p structPointerSlice) Append(q structPointer) { + p.v.Set(reflect.Append(p.v, q.v)) +} + +var ( + int32Type = reflect.TypeOf(int32(0)) + uint32Type = reflect.TypeOf(uint32(0)) + float32Type = reflect.TypeOf(float32(0)) + int64Type = reflect.TypeOf(int64(0)) + uint64Type = reflect.TypeOf(uint64(0)) + float64Type = reflect.TypeOf(float64(0)) +) + +// A word32 represents a field of type *int32, *uint32, *float32, or *enum. +// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. +type word32 struct { + v reflect.Value +} + +// IsNil reports whether p is nil. +func word32_IsNil(p word32) bool { + return p.v.IsNil() +} + +// Set sets p to point at a newly allocated word with bits set to x. +func word32_Set(p word32, o *Buffer, x uint32) { + t := p.v.Type().Elem() + switch t { + case int32Type: + if len(o.int32s) == 0 { + o.int32s = make([]int32, uint32PoolSize) + } + o.int32s[0] = int32(x) + p.v.Set(reflect.ValueOf(&o.int32s[0])) + o.int32s = o.int32s[1:] + return + case uint32Type: + if len(o.uint32s) == 0 { + o.uint32s = make([]uint32, uint32PoolSize) + } + o.uint32s[0] = x + p.v.Set(reflect.ValueOf(&o.uint32s[0])) + o.uint32s = o.uint32s[1:] + return + case float32Type: + if len(o.float32s) == 0 { + o.float32s = make([]float32, uint32PoolSize) + } + o.float32s[0] = math.Float32frombits(x) + p.v.Set(reflect.ValueOf(&o.float32s[0])) + o.float32s = o.float32s[1:] + return + } + + // must be enum + p.v.Set(reflect.New(t)) + p.v.Elem().SetInt(int64(int32(x))) +} + +// Get gets the bits pointed at by p, as a uint32. +func word32_Get(p word32) uint32 { + elem := p.v.Elem() + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32(p structPointer, f field) word32 { + return word32{structPointer_field(p, f)} +} + +// A word32Val represents a field of type int32, uint32, float32, or enum. +// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. +type word32Val struct { + v reflect.Value +} + +// Set sets *p to x. +func word32Val_Set(p word32Val, x uint32) { + switch p.v.Type() { + case int32Type: + p.v.SetInt(int64(x)) + return + case uint32Type: + p.v.SetUint(uint64(x)) + return + case float32Type: + p.v.SetFloat(float64(math.Float32frombits(x))) + return + } + + // must be enum + p.v.SetInt(int64(int32(x))) +} + +// Get gets the bits pointed at by p, as a uint32. +func word32Val_Get(p word32Val) uint32 { + elem := p.v + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. +func structPointer_Word32Val(p structPointer, f field) word32Val { + return word32Val{structPointer_field(p, f)} +} + +// A word32Slice is a slice of 32-bit values. +// That is, v.Type() is []int32, []uint32, []float32, or []enum. +type word32Slice struct { + v reflect.Value +} + +func (p word32Slice) Append(x uint32) { + n, m := p.v.Len(), p.v.Cap() + if n < m { + p.v.SetLen(n + 1) + } else { + t := p.v.Type().Elem() + p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + } + elem := p.v.Index(n) + switch elem.Kind() { + case reflect.Int32: + elem.SetInt(int64(int32(x))) + case reflect.Uint32: + elem.SetUint(uint64(x)) + case reflect.Float32: + elem.SetFloat(float64(math.Float32frombits(x))) + } +} + +func (p word32Slice) Len() int { + return p.v.Len() +} + +func (p word32Slice) Index(i int) uint32 { + elem := p.v.Index(i) + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. +func structPointer_Word32Slice(p structPointer, f field) word32Slice { + return word32Slice{structPointer_field(p, f)} +} + +// word64 is like word32 but for 64-bit values. +type word64 struct { + v reflect.Value +} + +func word64_Set(p word64, o *Buffer, x uint64) { + t := p.v.Type().Elem() + switch t { + case int64Type: + if len(o.int64s) == 0 { + o.int64s = make([]int64, uint64PoolSize) + } + o.int64s[0] = int64(x) + p.v.Set(reflect.ValueOf(&o.int64s[0])) + o.int64s = o.int64s[1:] + return + case uint64Type: + if len(o.uint64s) == 0 { + o.uint64s = make([]uint64, uint64PoolSize) + } + o.uint64s[0] = x + p.v.Set(reflect.ValueOf(&o.uint64s[0])) + o.uint64s = o.uint64s[1:] + return + case float64Type: + if len(o.float64s) == 0 { + o.float64s = make([]float64, uint64PoolSize) + } + o.float64s[0] = math.Float64frombits(x) + p.v.Set(reflect.ValueOf(&o.float64s[0])) + o.float64s = o.float64s[1:] + return + } + panic("unreachable") +} + +func word64_IsNil(p word64) bool { + return p.v.IsNil() +} + +func word64_Get(p word64) uint64 { + elem := p.v.Elem() + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return elem.Uint() + case reflect.Float64: + return math.Float64bits(elem.Float()) + } + panic("unreachable") +} + +func structPointer_Word64(p structPointer, f field) word64 { + return word64{structPointer_field(p, f)} +} + +// word64Val is like word32Val but for 64-bit values. +type word64Val struct { + v reflect.Value +} + +func word64Val_Set(p word64Val, o *Buffer, x uint64) { + switch p.v.Type() { + case int64Type: + p.v.SetInt(int64(x)) + return + case uint64Type: + p.v.SetUint(x) + return + case float64Type: + p.v.SetFloat(math.Float64frombits(x)) + return + } + panic("unreachable") +} + +func word64Val_Get(p word64Val) uint64 { + elem := p.v + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return elem.Uint() + case reflect.Float64: + return math.Float64bits(elem.Float()) + } + panic("unreachable") +} + +func structPointer_Word64Val(p structPointer, f field) word64Val { + return word64Val{structPointer_field(p, f)} +} + +type word64Slice struct { + v reflect.Value +} + +func (p word64Slice) Append(x uint64) { + n, m := p.v.Len(), p.v.Cap() + if n < m { + p.v.SetLen(n + 1) + } else { + t := p.v.Type().Elem() + p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + } + elem := p.v.Index(n) + switch elem.Kind() { + case reflect.Int64: + elem.SetInt(int64(int64(x))) + case reflect.Uint64: + elem.SetUint(uint64(x)) + case reflect.Float64: + elem.SetFloat(float64(math.Float64frombits(x))) + } +} + +func (p word64Slice) Len() int { + return p.v.Len() +} + +func (p word64Slice) Index(i int) uint64 { + elem := p.v.Index(i) + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return uint64(elem.Uint()) + case reflect.Float64: + return math.Float64bits(float64(elem.Float())) + } + panic("unreachable") +} + +func structPointer_Word64Slice(p structPointer, f field) word64Slice { + return word64Slice{structPointer_field(p, f)} +} diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go new file mode 100644 index 000000000..e9be0fe92 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -0,0 +1,266 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build !appengine + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "unsafe" +) + +// NOTE: These type_Foo functions would more idiomatically be methods, +// but Go does not allow methods on pointer types, and we must preserve +// some pointer type for the garbage collector. We use these +// funcs with clunky names as our poor approximation to methods. +// +// An alternative would be +// type structPointer struct { p unsafe.Pointer } +// but that does not registerize as well. + +// A structPointer is a pointer to a struct. +type structPointer unsafe.Pointer + +// toStructPointer returns a structPointer equivalent to the given reflect value. +func toStructPointer(v reflect.Value) structPointer { + return structPointer(unsafe.Pointer(v.Pointer())) +} + +// IsNil reports whether p is nil. +func structPointer_IsNil(p structPointer) bool { + return p == nil +} + +// Interface returns the struct pointer, assumed to have element type t, +// as an interface value. +func structPointer_Interface(p structPointer, t reflect.Type) interface{} { + return reflect.NewAt(t, unsafe.Pointer(p)).Interface() +} + +// A field identifies a field in a struct, accessible from a structPointer. +// In this implementation, a field is identified by its byte offset from the start of the struct. +type field uintptr + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return field(f.Offset) +} + +// invalidField is an invalid field identifier. +const invalidField = ^field(0) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { + return f != ^field(0) +} + +// Bytes returns the address of a []byte field in the struct. +func structPointer_Bytes(p structPointer, f field) *[]byte { + return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BytesSlice returns the address of a [][]byte field in the struct. +func structPointer_BytesSlice(p structPointer, f field) *[][]byte { + return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// Bool returns the address of a *bool field in the struct. +func structPointer_Bool(p structPointer, f field) **bool { + return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BoolVal returns the address of a bool field in the struct. +func structPointer_BoolVal(p structPointer, f field) *bool { + return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BoolSlice returns the address of a []bool field in the struct. +func structPointer_BoolSlice(p structPointer, f field) *[]bool { + return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// String returns the address of a *string field in the struct. +func structPointer_String(p structPointer, f field) **string { + return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StringVal returns the address of a string field in the struct. +func structPointer_StringVal(p structPointer, f field) *string { + return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StringSlice returns the address of a []string field in the struct. +func structPointer_StringSlice(p structPointer, f field) *[]string { + return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// ExtMap returns the address of an extension map field in the struct. +func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { + return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// NewAt returns the reflect.Value for a pointer to a field in the struct. +func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { + return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) +} + +// SetStructPointer writes a *struct field in the struct. +func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { + *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q +} + +// GetStructPointer reads a *struct field in the struct. +func structPointer_GetStructPointer(p structPointer, f field) structPointer { + return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StructPointerSlice the address of a []*struct field in the struct. +func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { + return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). +type structPointerSlice []structPointer + +func (v *structPointerSlice) Len() int { return len(*v) } +func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } +func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } + +// A word32 is the address of a "pointer to 32-bit value" field. +type word32 **uint32 + +// IsNil reports whether *v is nil. +func word32_IsNil(p word32) bool { + return *p == nil +} + +// Set sets *v to point at a newly allocated word set to x. +func word32_Set(p word32, o *Buffer, x uint32) { + if len(o.uint32s) == 0 { + o.uint32s = make([]uint32, uint32PoolSize) + } + o.uint32s[0] = x + *p = &o.uint32s[0] + o.uint32s = o.uint32s[1:] +} + +// Get gets the value pointed at by *v. +func word32_Get(p word32) uint32 { + return **p +} + +// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32(p structPointer, f field) word32 { + return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// A word32Val is the address of a 32-bit value field. +type word32Val *uint32 + +// Set sets *p to x. +func word32Val_Set(p word32Val, x uint32) { + *p = x +} + +// Get gets the value pointed at by p. +func word32Val_Get(p word32Val) uint32 { + return *p +} + +// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32Val(p structPointer, f field) word32Val { + return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// A word32Slice is a slice of 32-bit values. +type word32Slice []uint32 + +func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } +func (v *word32Slice) Len() int { return len(*v) } +func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } + +// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. +func structPointer_Word32Slice(p structPointer, f field) *word32Slice { + return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// word64 is like word32 but for 64-bit values. +type word64 **uint64 + +func word64_Set(p word64, o *Buffer, x uint64) { + if len(o.uint64s) == 0 { + o.uint64s = make([]uint64, uint64PoolSize) + } + o.uint64s[0] = x + *p = &o.uint64s[0] + o.uint64s = o.uint64s[1:] +} + +func word64_IsNil(p word64) bool { + return *p == nil +} + +func word64_Get(p word64) uint64 { + return **p +} + +func structPointer_Word64(p structPointer, f field) word64 { + return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// word64Val is like word32Val but for 64-bit values. +type word64Val *uint64 + +func word64Val_Set(p word64Val, o *Buffer, x uint64) { + *p = x +} + +func word64Val_Get(p word64Val) uint64 { + return *p +} + +func structPointer_Word64Val(p structPointer, f field) word64Val { + return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// word64Slice is like word32Slice but for 64-bit values. +type word64Slice []uint64 + +func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } +func (v *word64Slice) Len() int { return len(*v) } +func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } + +func structPointer_Word64Slice(p structPointer, f field) *word64Slice { + return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go new file mode 100644 index 000000000..d4531c056 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/properties.go @@ -0,0 +1,842 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "fmt" + "log" + "os" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +const debug bool = false + +// Constants that identify the encoding of a value on the wire. +const ( + WireVarint = 0 + WireFixed64 = 1 + WireBytes = 2 + WireStartGroup = 3 + WireEndGroup = 4 + WireFixed32 = 5 +) + +const startSize = 10 // initial slice/string sizes + +// Encoders are defined in encode.go +// An encoder outputs the full representation of a field, including its +// tag and encoder type. +type encoder func(p *Buffer, prop *Properties, base structPointer) error + +// A valueEncoder encodes a single integer in a particular encoding. +type valueEncoder func(o *Buffer, x uint64) error + +// Sizers are defined in encode.go +// A sizer returns the encoded size of a field, including its tag and encoder +// type. +type sizer func(prop *Properties, base structPointer) int + +// A valueSizer returns the encoded size of a single integer in a particular +// encoding. +type valueSizer func(x uint64) int + +// Decoders are defined in decode.go +// A decoder creates a value from its wire representation. +// Unrecognized subelements are saved in unrec. +type decoder func(p *Buffer, prop *Properties, base structPointer) error + +// A valueDecoder decodes a single integer in a particular encoding. +type valueDecoder func(o *Buffer) (x uint64, err error) + +// A oneofMarshaler does the marshaling for all oneof fields in a message. +type oneofMarshaler func(Message, *Buffer) error + +// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. +type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) + +// A oneofSizer does the sizing for all oneof fields in a message. +type oneofSizer func(Message) int + +// tagMap is an optimization over map[int]int for typical protocol buffer +// use-cases. Encoded protocol buffers are often in tag order with small tag +// numbers. +type tagMap struct { + fastTags []int + slowTags map[int]int +} + +// tagMapFastLimit is the upper bound on the tag number that will be stored in +// the tagMap slice rather than its map. +const tagMapFastLimit = 1024 + +func (p *tagMap) get(t int) (int, bool) { + if t > 0 && t < tagMapFastLimit { + if t >= len(p.fastTags) { + return 0, false + } + fi := p.fastTags[t] + return fi, fi >= 0 + } + fi, ok := p.slowTags[t] + return fi, ok +} + +func (p *tagMap) put(t int, fi int) { + if t > 0 && t < tagMapFastLimit { + for len(p.fastTags) < t+1 { + p.fastTags = append(p.fastTags, -1) + } + p.fastTags[t] = fi + return + } + if p.slowTags == nil { + p.slowTags = make(map[int]int) + } + p.slowTags[t] = fi +} + +// StructProperties represents properties for all the fields of a struct. +// decoderTags and decoderOrigNames should only be used by the decoder. +type StructProperties struct { + Prop []*Properties // properties for each field + reqCount int // required count + decoderTags tagMap // map from proto tag to struct field number + decoderOrigNames map[string]int // map from original name to struct field number + order []int // list of struct field numbers in tag order + unrecField field // field id of the XXX_unrecognized []byte field + extendable bool // is this an extendable proto + + oneofMarshaler oneofMarshaler + oneofUnmarshaler oneofUnmarshaler + oneofSizer oneofSizer + stype reflect.Type + + // OneofTypes contains information about the oneof fields in this message. + // It is keyed by the original name of a field. + OneofTypes map[string]*OneofProperties +} + +// OneofProperties represents information about a specific field in a oneof. +type OneofProperties struct { + Type reflect.Type // pointer to generated struct type for this oneof field + Field int // struct field number of the containing oneof in the message + Prop *Properties +} + +// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. +// See encode.go, (*Buffer).enc_struct. + +func (sp *StructProperties) Len() int { return len(sp.order) } +func (sp *StructProperties) Less(i, j int) bool { + return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag +} +func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } + +// Properties represents the protocol-specific behavior of a single struct field. +type Properties struct { + Name string // name of the field, for error messages + OrigName string // original name before protocol compiler (always set) + Wire string + WireType int + Tag int + Required bool + Optional bool + Repeated bool + Packed bool // relevant for repeated primitives only + Enum string // set for enum types only + proto3 bool // whether this is known to be a proto3 field; set for []byte only + oneof bool // whether this is a oneof field + + Default string // default value + HasDefault bool // whether an explicit default was provided + def_uint64 uint64 + + enc encoder + valEnc valueEncoder // set for bool and numeric types only + field field + tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) + tagbuf [8]byte + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only + isMarshaler bool + isUnmarshaler bool + + mtype reflect.Type // set for map types only + mkeyprop *Properties // set for map types only + mvalprop *Properties // set for map types only + + size sizer + valSize valueSizer // set for bool and numeric types only + + dec decoder + valDec valueDecoder // set for bool and numeric types only + + // If this is a packable field, this will be the decoder for the packed version of the field. + packedDec decoder +} + +// String formats the properties in the protobuf struct field tag style. +func (p *Properties) String() string { + s := p.Wire + s = "," + s += strconv.Itoa(p.Tag) + if p.Required { + s += ",req" + } + if p.Optional { + s += ",opt" + } + if p.Repeated { + s += ",rep" + } + if p.Packed { + s += ",packed" + } + if p.OrigName != p.Name { + s += ",name=" + p.OrigName + } + if p.proto3 { + s += ",proto3" + } + if p.oneof { + s += ",oneof" + } + if len(p.Enum) > 0 { + s += ",enum=" + p.Enum + } + if p.HasDefault { + s += ",def=" + p.Default + } + return s +} + +// Parse populates p by parsing a string in the protobuf struct field tag style. +func (p *Properties) Parse(s string) { + // "bytes,49,opt,name=foo,def=hello!" + fields := strings.Split(s, ",") // breaks def=, but handled below. + if len(fields) < 2 { + fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) + return + } + + p.Wire = fields[0] + switch p.Wire { + case "varint": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeVarint + p.valDec = (*Buffer).DecodeVarint + p.valSize = sizeVarint + case "fixed32": + p.WireType = WireFixed32 + p.valEnc = (*Buffer).EncodeFixed32 + p.valDec = (*Buffer).DecodeFixed32 + p.valSize = sizeFixed32 + case "fixed64": + p.WireType = WireFixed64 + p.valEnc = (*Buffer).EncodeFixed64 + p.valDec = (*Buffer).DecodeFixed64 + p.valSize = sizeFixed64 + case "zigzag32": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeZigzag32 + p.valDec = (*Buffer).DecodeZigzag32 + p.valSize = sizeZigzag32 + case "zigzag64": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeZigzag64 + p.valDec = (*Buffer).DecodeZigzag64 + p.valSize = sizeZigzag64 + case "bytes", "group": + p.WireType = WireBytes + // no numeric converter for non-numeric types + default: + fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) + return + } + + var err error + p.Tag, err = strconv.Atoi(fields[1]) + if err != nil { + return + } + + for i := 2; i < len(fields); i++ { + f := fields[i] + switch { + case f == "req": + p.Required = true + case f == "opt": + p.Optional = true + case f == "rep": + p.Repeated = true + case f == "packed": + p.Packed = true + case strings.HasPrefix(f, "name="): + p.OrigName = f[5:] + case strings.HasPrefix(f, "enum="): + p.Enum = f[5:] + case f == "proto3": + p.proto3 = true + case f == "oneof": + p.oneof = true + case strings.HasPrefix(f, "def="): + p.HasDefault = true + p.Default = f[4:] // rest of string + if i+1 < len(fields) { + // Commas aren't escaped, and def is always last. + p.Default += "," + strings.Join(fields[i+1:], ",") + break + } + } + } +} + +func logNoSliceEnc(t1, t2 reflect.Type) { + fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) +} + +var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() + +// Initialize the fields for encoding and decoding. +func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { + p.enc = nil + p.dec = nil + p.size = nil + + switch t1 := typ; t1.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) + + // proto3 scalar types + + case reflect.Bool: + p.enc = (*Buffer).enc_proto3_bool + p.dec = (*Buffer).dec_proto3_bool + p.size = size_proto3_bool + case reflect.Int32: + p.enc = (*Buffer).enc_proto3_int32 + p.dec = (*Buffer).dec_proto3_int32 + p.size = size_proto3_int32 + case reflect.Uint32: + p.enc = (*Buffer).enc_proto3_uint32 + p.dec = (*Buffer).dec_proto3_int32 // can reuse + p.size = size_proto3_uint32 + case reflect.Int64, reflect.Uint64: + p.enc = (*Buffer).enc_proto3_int64 + p.dec = (*Buffer).dec_proto3_int64 + p.size = size_proto3_int64 + case reflect.Float32: + p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits + p.dec = (*Buffer).dec_proto3_int32 + p.size = size_proto3_uint32 + case reflect.Float64: + p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits + p.dec = (*Buffer).dec_proto3_int64 + p.size = size_proto3_int64 + case reflect.String: + p.enc = (*Buffer).enc_proto3_string + p.dec = (*Buffer).dec_proto3_string + p.size = size_proto3_string + + case reflect.Ptr: + switch t2 := t1.Elem(); t2.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) + break + case reflect.Bool: + p.enc = (*Buffer).enc_bool + p.dec = (*Buffer).dec_bool + p.size = size_bool + case reflect.Int32: + p.enc = (*Buffer).enc_int32 + p.dec = (*Buffer).dec_int32 + p.size = size_int32 + case reflect.Uint32: + p.enc = (*Buffer).enc_uint32 + p.dec = (*Buffer).dec_int32 // can reuse + p.size = size_uint32 + case reflect.Int64, reflect.Uint64: + p.enc = (*Buffer).enc_int64 + p.dec = (*Buffer).dec_int64 + p.size = size_int64 + case reflect.Float32: + p.enc = (*Buffer).enc_uint32 // can just treat them as bits + p.dec = (*Buffer).dec_int32 + p.size = size_uint32 + case reflect.Float64: + p.enc = (*Buffer).enc_int64 // can just treat them as bits + p.dec = (*Buffer).dec_int64 + p.size = size_int64 + case reflect.String: + p.enc = (*Buffer).enc_string + p.dec = (*Buffer).dec_string + p.size = size_string + case reflect.Struct: + p.stype = t1.Elem() + p.isMarshaler = isMarshaler(t1) + p.isUnmarshaler = isUnmarshaler(t1) + if p.Wire == "bytes" { + p.enc = (*Buffer).enc_struct_message + p.dec = (*Buffer).dec_struct_message + p.size = size_struct_message + } else { + p.enc = (*Buffer).enc_struct_group + p.dec = (*Buffer).dec_struct_group + p.size = size_struct_group + } + } + + case reflect.Slice: + switch t2 := t1.Elem(); t2.Kind() { + default: + logNoSliceEnc(t1, t2) + break + case reflect.Bool: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_bool + p.size = size_slice_packed_bool + } else { + p.enc = (*Buffer).enc_slice_bool + p.size = size_slice_bool + } + p.dec = (*Buffer).dec_slice_bool + p.packedDec = (*Buffer).dec_slice_packed_bool + case reflect.Int32: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int32 + p.size = size_slice_packed_int32 + } else { + p.enc = (*Buffer).enc_slice_int32 + p.size = size_slice_int32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case reflect.Uint32: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_uint32 + p.size = size_slice_packed_uint32 + } else { + p.enc = (*Buffer).enc_slice_uint32 + p.size = size_slice_uint32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case reflect.Int64, reflect.Uint64: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int64 + p.size = size_slice_packed_int64 + } else { + p.enc = (*Buffer).enc_slice_int64 + p.size = size_slice_int64 + } + p.dec = (*Buffer).dec_slice_int64 + p.packedDec = (*Buffer).dec_slice_packed_int64 + case reflect.Uint8: + p.enc = (*Buffer).enc_slice_byte + p.dec = (*Buffer).dec_slice_byte + p.size = size_slice_byte + // This is a []byte, which is either a bytes field, + // or the value of a map field. In the latter case, + // we always encode an empty []byte, so we should not + // use the proto3 enc/size funcs. + // f == nil iff this is the key/value of a map field. + if p.proto3 && f != nil { + p.enc = (*Buffer).enc_proto3_slice_byte + p.size = size_proto3_slice_byte + } + case reflect.Float32, reflect.Float64: + switch t2.Bits() { + case 32: + // can just treat them as bits + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_uint32 + p.size = size_slice_packed_uint32 + } else { + p.enc = (*Buffer).enc_slice_uint32 + p.size = size_slice_uint32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case 64: + // can just treat them as bits + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int64 + p.size = size_slice_packed_int64 + } else { + p.enc = (*Buffer).enc_slice_int64 + p.size = size_slice_int64 + } + p.dec = (*Buffer).dec_slice_int64 + p.packedDec = (*Buffer).dec_slice_packed_int64 + default: + logNoSliceEnc(t1, t2) + break + } + case reflect.String: + p.enc = (*Buffer).enc_slice_string + p.dec = (*Buffer).dec_slice_string + p.size = size_slice_string + case reflect.Ptr: + switch t3 := t2.Elem(); t3.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) + break + case reflect.Struct: + p.stype = t2.Elem() + p.isMarshaler = isMarshaler(t2) + p.isUnmarshaler = isUnmarshaler(t2) + if p.Wire == "bytes" { + p.enc = (*Buffer).enc_slice_struct_message + p.dec = (*Buffer).dec_slice_struct_message + p.size = size_slice_struct_message + } else { + p.enc = (*Buffer).enc_slice_struct_group + p.dec = (*Buffer).dec_slice_struct_group + p.size = size_slice_struct_group + } + } + case reflect.Slice: + switch t2.Elem().Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) + break + case reflect.Uint8: + p.enc = (*Buffer).enc_slice_slice_byte + p.dec = (*Buffer).dec_slice_slice_byte + p.size = size_slice_slice_byte + } + } + + case reflect.Map: + p.enc = (*Buffer).enc_new_map + p.dec = (*Buffer).dec_new_map + p.size = size_new_map + + p.mtype = t1 + p.mkeyprop = &Properties{} + p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.mvalprop = &Properties{} + vtype := p.mtype.Elem() + if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { + // The value type is not a message (*T) or bytes ([]byte), + // so we need encoders for the pointer to this type. + vtype = reflect.PtrTo(vtype) + } + p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + } + + // precalculate tag code + wire := p.WireType + if p.Packed { + wire = WireBytes + } + x := uint32(p.Tag)<<3 | uint32(wire) + i := 0 + for i = 0; x > 127; i++ { + p.tagbuf[i] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + p.tagbuf[i] = uint8(x) + p.tagcode = p.tagbuf[0 : i+1] + + if p.stype != nil { + if lockGetProp { + p.sprop = GetProperties(p.stype) + } else { + p.sprop = getPropertiesLocked(p.stype) + } + } +} + +var ( + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() + unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() +) + +// isMarshaler reports whether type t implements Marshaler. +func isMarshaler(t reflect.Type) bool { + // We're checking for (likely) pointer-receiver methods + // so if t is not a pointer, something is very wrong. + // The calls above only invoke isMarshaler on pointer types. + if t.Kind() != reflect.Ptr { + panic("proto: misuse of isMarshaler") + } + return t.Implements(marshalerType) +} + +// isUnmarshaler reports whether type t implements Unmarshaler. +func isUnmarshaler(t reflect.Type) bool { + // We're checking for (likely) pointer-receiver methods + // so if t is not a pointer, something is very wrong. + // The calls above only invoke isUnmarshaler on pointer types. + if t.Kind() != reflect.Ptr { + panic("proto: misuse of isUnmarshaler") + } + return t.Implements(unmarshalerType) +} + +// Init populates the properties from a protocol buffer struct tag. +func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { + p.init(typ, name, tag, f, true) +} + +func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { + // "bytes,49,opt,def=hello!" + p.Name = name + p.OrigName = name + if f != nil { + p.field = toField(f) + } + if tag == "" { + return + } + p.Parse(tag) + p.setEncAndDec(typ, f, lockGetProp) +} + +var ( + propertiesMu sync.RWMutex + propertiesMap = make(map[reflect.Type]*StructProperties) +) + +// GetProperties returns the list of properties for the type represented by t. +// t must represent a generated struct type of a protocol message. +func GetProperties(t reflect.Type) *StructProperties { + if t.Kind() != reflect.Struct { + panic("proto: type must have kind struct") + } + + // Most calls to GetProperties in a long-running program will be + // retrieving details for types we have seen before. + propertiesMu.RLock() + sprop, ok := propertiesMap[t] + propertiesMu.RUnlock() + if ok { + if collectStats { + stats.Chit++ + } + return sprop + } + + propertiesMu.Lock() + sprop = getPropertiesLocked(t) + propertiesMu.Unlock() + return sprop +} + +// getPropertiesLocked requires that propertiesMu is held. +func getPropertiesLocked(t reflect.Type) *StructProperties { + if prop, ok := propertiesMap[t]; ok { + if collectStats { + stats.Chit++ + } + return prop + } + if collectStats { + stats.Cmiss++ + } + + prop := new(StructProperties) + // in case of recursive protos, fill this in now. + propertiesMap[t] = prop + + // build properties + prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) + prop.unrecField = invalidField + prop.Prop = make([]*Properties, t.NumField()) + prop.order = make([]int, t.NumField()) + + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + p := new(Properties) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + + if f.Name == "XXX_extensions" { // special case + p.enc = (*Buffer).enc_map + p.dec = nil // not needed + p.size = size_map + } + if f.Name == "XXX_unrecognized" { // special case + prop.unrecField = toField(&f) + } + oneof := f.Tag.Get("protobuf_oneof") != "" // special case + prop.Prop[i] = p + prop.order[i] = i + if debug { + print(i, " ", f.Name, " ", t.String(), " ") + if p.Tag > 0 { + print(p.String()) + } + print("\n") + } + if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof { + fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") + } + } + + // Re-order prop.order. + sort.Sort(prop) + + type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + var oots []interface{} + prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() + prop.stype = t + + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), + } + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break + } + prop.OneofTypes[oop.Prop.OrigName] = oop + } + } + + // build required counts + // build tags + reqCount := 0 + prop.decoderOrigNames = make(map[string]int) + for i, p := range prop.Prop { + if strings.HasPrefix(p.Name, "XXX_") { + // Internal fields should not appear in tags/origNames maps. + // They are handled specially when encoding and decoding. + continue + } + if p.Required { + reqCount++ + } + prop.decoderTags.put(p.Tag, i) + prop.decoderOrigNames[p.OrigName] = i + } + prop.reqCount = reqCount + + return prop +} + +// Return the Properties object for the x[0]'th field of the structure. +func propByIndex(t reflect.Type, x []int) *Properties { + if len(x) != 1 { + fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) + return nil + } + prop := GetProperties(t) + return prop.Prop[x[0]] +} + +// Get the address and type of a pointer to a struct from an interface. +func getbase(pb Message) (t reflect.Type, b structPointer, err error) { + if pb == nil { + err = ErrNil + return + } + // get the reflect type of the pointer to the struct. + t = reflect.TypeOf(pb) + // get the address of the struct. + value := reflect.ValueOf(pb) + b = toStructPointer(value) + return +} + +// A global registry of enum types. +// The generated code will register the generated maps by calling RegisterEnum. + +var enumValueMaps = make(map[string]map[string]int32) + +// RegisterEnum is called from the generated code to install the enum descriptor +// maps into the global table to aid parsing text format protocol buffers. +func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { + if _, ok := enumValueMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumValueMaps[typeName] = valueMap +} + +// EnumValueMap returns the mapping from names to integers of the +// enum type enumType, or a nil if not found. +func EnumValueMap(enumType string) map[string]int32 { + return enumValueMaps[enumType] +} + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + protoTypes = make(map[string]reflect.Type) + revProtoTypes = make(map[reflect.Type]string) +) + +// RegisterType is called from generated code and maps from the fully qualified +// proto name to the type (pointer to struct) of the protocol buffer. +func RegisterType(x Message, name string) { + if _, ok := protoTypes[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoTypes[name] = t + revProtoTypes[t] = name +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] } + +// MessageType returns the message type (pointer to struct) for a named message. +func MessageType(name string) reflect.Type { return protoTypes[name] } diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go new file mode 100644 index 000000000..37c778209 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go @@ -0,0 +1,122 @@ +// Code generated by protoc-gen-go. +// source: proto3_proto/proto3.proto +// DO NOT EDIT! + +/* +Package proto3_proto is a generated protocol buffer package. + +It is generated from these files: + proto3_proto/proto3.proto + +It has these top-level messages: + Message + Nested + MessageWithMap +*/ +package proto3_proto + +import proto "github.com/golang/protobuf/proto" +import testdata "github.com/golang/protobuf/proto/testdata" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal + +type Message_Humour int32 + +const ( + Message_UNKNOWN Message_Humour = 0 + Message_PUNS Message_Humour = 1 + Message_SLAPSTICK Message_Humour = 2 + Message_BILL_BAILEY Message_Humour = 3 +) + +var Message_Humour_name = map[int32]string{ + 0: "UNKNOWN", + 1: "PUNS", + 2: "SLAPSTICK", + 3: "BILL_BAILEY", +} +var Message_Humour_value = map[string]int32{ + "UNKNOWN": 0, + "PUNS": 1, + "SLAPSTICK": 2, + "BILL_BAILEY": 3, +} + +func (x Message_Humour) String() string { + return proto.EnumName(Message_Humour_name, int32(x)) +} + +type Message struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` + HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm" json:"height_in_cm,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + ResultCount int64 `protobuf:"varint,7,opt,name=result_count" json:"result_count,omitempty"` + TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman" json:"true_scotsman,omitempty"` + Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` + Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"` + Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` + Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"` + Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} + +func (m *Message) GetNested() *Nested { + if m != nil { + return m.Nested + } + return nil +} + +func (m *Message) GetTerrain() map[string]*Nested { + if m != nil { + return m.Terrain + } + return nil +} + +func (m *Message) GetProto2Field() *testdata.SubDefaults { + if m != nil { + return m.Proto2Field + } + return nil +} + +func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { + if m != nil { + return m.Proto2Value + } + return nil +} + +type Nested struct { + Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` +} + +func (m *Nested) Reset() { *m = Nested{} } +func (m *Nested) String() string { return proto.CompactTextString(m) } +func (*Nested) ProtoMessage() {} + +type MessageWithMap struct { + ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } +func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } +func (*MessageWithMap) ProtoMessage() {} + +func (m *MessageWithMap) GetByteMapping() map[bool][]byte { + if m != nil { + return m.ByteMapping + } + return nil +} + +func init() { + proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) +} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto new file mode 100644 index 000000000..e2311d929 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto @@ -0,0 +1,68 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "testdata/test.proto"; + +package proto3_proto; + +message Message { + enum Humour { + UNKNOWN = 0; + PUNS = 1; + SLAPSTICK = 2; + BILL_BAILEY = 3; + } + + string name = 1; + Humour hilarity = 2; + uint32 height_in_cm = 3; + bytes data = 4; + int64 result_count = 7; + bool true_scotsman = 8; + float score = 9; + + repeated uint64 key = 5; + Nested nested = 6; + + map terrain = 10; + testdata.SubDefaults proto2_field = 11; + map proto2_value = 13; +} + +message Nested { + string bunny = 1; +} + +message MessageWithMap { + map byte_mapping = 1; +} diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go new file mode 100644 index 000000000..2336b144c --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text.go @@ -0,0 +1,751 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for writing the text protocol buffer format. + +import ( + "bufio" + "bytes" + "encoding" + "errors" + "fmt" + "io" + "log" + "math" + "reflect" + "sort" + "strings" +) + +var ( + newline = []byte("\n") + spaces = []byte(" ") + gtNewline = []byte(">\n") + endBraceNewline = []byte("}\n") + backslashN = []byte{'\\', 'n'} + backslashR = []byte{'\\', 'r'} + backslashT = []byte{'\\', 't'} + backslashDQ = []byte{'\\', '"'} + backslashBS = []byte{'\\', '\\'} + posInf = []byte("inf") + negInf = []byte("-inf") + nan = []byte("nan") +) + +type writer interface { + io.Writer + WriteByte(byte) error +} + +// textWriter is an io.Writer that tracks its indentation level. +type textWriter struct { + ind int + complete bool // if the current position is a complete line + compact bool // whether to write out as a one-liner + w writer +} + +func (w *textWriter) WriteString(s string) (n int, err error) { + if !strings.Contains(s, "\n") { + if !w.compact && w.complete { + w.writeIndent() + } + w.complete = false + return io.WriteString(w.w, s) + } + // WriteString is typically called without newlines, so this + // codepath and its copy are rare. We copy to avoid + // duplicating all of Write's logic here. + return w.Write([]byte(s)) +} + +func (w *textWriter) Write(p []byte) (n int, err error) { + newlines := bytes.Count(p, newline) + if newlines == 0 { + if !w.compact && w.complete { + w.writeIndent() + } + n, err = w.w.Write(p) + w.complete = false + return n, err + } + + frags := bytes.SplitN(p, newline, newlines+1) + if w.compact { + for i, frag := range frags { + if i > 0 { + if err := w.w.WriteByte(' '); err != nil { + return n, err + } + n++ + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + } + return n, nil + } + + for i, frag := range frags { + if w.complete { + w.writeIndent() + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + if i+1 < len(frags) { + if err := w.w.WriteByte('\n'); err != nil { + return n, err + } + n++ + } + } + w.complete = len(frags[len(frags)-1]) == 0 + return n, nil +} + +func (w *textWriter) WriteByte(c byte) error { + if w.compact && c == '\n' { + c = ' ' + } + if !w.compact && w.complete { + w.writeIndent() + } + err := w.w.WriteByte(c) + w.complete = c == '\n' + return err +} + +func (w *textWriter) indent() { w.ind++ } + +func (w *textWriter) unindent() { + if w.ind == 0 { + log.Printf("proto: textWriter unindented too far") + return + } + w.ind-- +} + +func writeName(w *textWriter, props *Properties) error { + if _, err := w.WriteString(props.OrigName); err != nil { + return err + } + if props.Wire != "group" { + return w.WriteByte(':') + } + return nil +} + +// raw is the interface satisfied by RawMessage. +type raw interface { + Bytes() []byte +} + +func writeStruct(w *textWriter, sv reflect.Value) error { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + props := sprops.Prop[i] + name := st.Field(i).Name + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: + // XXX_unrecognized []byte + // XXX_extensions map[int32]proto.Extension + // The first is handled here; + // the second is handled at the bottom of this function. + if name == "XXX_unrecognized" && !fv.IsNil() { + if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Field not filled in. This could be an optional field or + // a required field that wasn't filled in. Either way, there + // isn't anything we can show for it. + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + // Repeated field that is empty, or a bytes field that is unused. + continue + } + + if props.Repeated && fv.Kind() == reflect.Slice { + // Repeated field. + for j := 0; j < fv.Len(); j++ { + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + v := fv.Index(j) + if v.Kind() == reflect.Ptr && v.IsNil() { + // A nil message in a repeated field is not valid, + // but we can handle that more gracefully than panicking. + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + continue + } + if err := writeAny(w, v, props); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Map { + // Map fields are rendered as a repeated struct with key/value fields. + keys := fv.MapKeys() + sort.Sort(mapKeys(keys)) + for _, key := range keys { + val := fv.MapIndex(key) + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + // open struct + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + // key + if _, err := w.WriteString("key:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := writeAny(w, key, props.mkeyprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + // nil values aren't legal, but we can avoid panicking because of them. + if val.Kind() != reflect.Ptr || !val.IsNil() { + // value + if _, err := w.WriteString("value:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := writeAny(w, val, props.mvalprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + // close struct + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { + // empty bytes field + continue + } + if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { + // proto3 non-repeated scalar field; skip if zero value + if isProto3Zero(fv) { + continue + } + } + + if fv.Kind() == reflect.Interface { + // Check if it is a oneof. + if st.Field(i).Tag.Get("protobuf_oneof") != "" { + // fv is nil, or holds a pointer to generated struct. + // That generated struct has exactly one field, + // which has a protobuf struct tag. + if fv.IsNil() { + continue + } + inner := fv.Elem().Elem() // interface -> *T -> T + tag := inner.Type().Field(0).Tag.Get("protobuf") + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) + // Write the value in the oneof, not the oneof itself. + fv = inner.Field(0) + + // Special case to cope with malformed messages gracefully: + // If the value in the oneof is a nil pointer, don't panic + // in writeAny. + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Use errors.New so writeAny won't render quotes. + msg := errors.New("/* nil */") + fv = reflect.ValueOf(&msg).Elem() + } + } + } + + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if b, ok := fv.Interface().(raw); ok { + if err := writeRaw(w, b.Bytes()); err != nil { + return err + } + continue + } + + // Enums have a String method, so writeAny will work fine. + if err := writeAny(w, fv, props); err != nil { + return err + } + + if err := w.WriteByte('\n'); err != nil { + return err + } + } + + // Extensions (the XXX_extensions field). + pv := sv.Addr() + if pv.Type().Implements(extendableProtoType) { + if err := writeExtensions(w, pv); err != nil { + return err + } + } + + return nil +} + +// writeRaw writes an uninterpreted raw message. +func writeRaw(w *textWriter, b []byte) error { + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if err := writeUnknownStruct(w, b); err != nil { + return err + } + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + return nil +} + +// writeAny writes an arbitrary field. +func writeAny(w *textWriter, v reflect.Value, props *Properties) error { + v = reflect.Indirect(v) + + // Floats have special cases. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + x := v.Float() + var b []byte + switch { + case math.IsInf(x, 1): + b = posInf + case math.IsInf(x, -1): + b = negInf + case math.IsNaN(x): + b = nan + } + if b != nil { + _, err := w.Write(b) + return err + } + // Other values are handled below. + } + + // We don't attempt to serialise every possible value type; only those + // that can occur in protocol buffers. + switch v.Kind() { + case reflect.Slice: + // Should only be a []byte; repeated fields are handled in writeStruct. + if err := writeString(w, string(v.Interface().([]byte))); err != nil { + return err + } + case reflect.String: + if err := writeString(w, v.String()); err != nil { + return err + } + case reflect.Struct: + // Required/optional group/message. + var bra, ket byte = '<', '>' + if props != nil && props.Wire == "group" { + bra, ket = '{', '}' + } + if err := w.WriteByte(bra); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if tm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := tm.MarshalText() + if err != nil { + return err + } + if _, err = w.Write(text); err != nil { + return err + } + } else if err := writeStruct(w, v); err != nil { + return err + } + w.unindent() + if err := w.WriteByte(ket); err != nil { + return err + } + default: + _, err := fmt.Fprint(w, v.Interface()) + return err + } + return nil +} + +// equivalent to C's isprint. +func isprint(c byte) bool { + return c >= 0x20 && c < 0x7f +} + +// writeString writes a string in the protocol buffer text format. +// It is similar to strconv.Quote except we don't use Go escape sequences, +// we treat the string as a byte sequence, and we use octal escapes. +// These differences are to maintain interoperability with the other +// languages' implementations of the text format. +func writeString(w *textWriter, s string) error { + // use WriteByte here to get any needed indent + if err := w.WriteByte('"'); err != nil { + return err + } + // Loop over the bytes, not the runes. + for i := 0; i < len(s); i++ { + var err error + // Divergence from C++: we don't escape apostrophes. + // There's no need to escape them, and the C++ parser + // copes with a naked apostrophe. + switch c := s[i]; c { + case '\n': + _, err = w.w.Write(backslashN) + case '\r': + _, err = w.w.Write(backslashR) + case '\t': + _, err = w.w.Write(backslashT) + case '"': + _, err = w.w.Write(backslashDQ) + case '\\': + _, err = w.w.Write(backslashBS) + default: + if isprint(c) { + err = w.w.WriteByte(c) + } else { + _, err = fmt.Fprintf(w.w, "\\%03o", c) + } + } + if err != nil { + return err + } + } + return w.WriteByte('"') +} + +func writeUnknownStruct(w *textWriter, data []byte) (err error) { + if !w.compact { + if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { + return err + } + } + b := NewBuffer(data) + for b.index < len(b.buf) { + x, err := b.DecodeVarint() + if err != nil { + _, err := fmt.Fprintf(w, "/* %v */\n", err) + return err + } + wire, tag := x&7, x>>3 + if wire == WireEndGroup { + w.unindent() + if _, err := w.Write(endBraceNewline); err != nil { + return err + } + continue + } + if _, err := fmt.Fprint(w, tag); err != nil { + return err + } + if wire != WireStartGroup { + if err := w.WriteByte(':'); err != nil { + return err + } + } + if !w.compact || wire == WireStartGroup { + if err := w.WriteByte(' '); err != nil { + return err + } + } + switch wire { + case WireBytes: + buf, e := b.DecodeRawBytes(false) + if e == nil { + _, err = fmt.Fprintf(w, "%q", buf) + } else { + _, err = fmt.Fprintf(w, "/* %v */", e) + } + case WireFixed32: + x, err = b.DecodeFixed32() + err = writeUnknownInt(w, x, err) + case WireFixed64: + x, err = b.DecodeFixed64() + err = writeUnknownInt(w, x, err) + case WireStartGroup: + err = w.WriteByte('{') + w.indent() + case WireVarint: + x, err = b.DecodeVarint() + err = writeUnknownInt(w, x, err) + default: + _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) + } + if err != nil { + return err + } + if err = w.WriteByte('\n'); err != nil { + return err + } + } + return nil +} + +func writeUnknownInt(w *textWriter, x uint64, err error) error { + if err == nil { + _, err = fmt.Fprint(w, x) + } else { + _, err = fmt.Fprintf(w, "/* %v */", err) + } + return err +} + +type int32Slice []int32 + +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// writeExtensions writes all the extensions in pv. +// pv is assumed to be a pointer to a protocol message struct that is extendable. +func writeExtensions(w *textWriter, pv reflect.Value) error { + emap := extensionMaps[pv.Type().Elem()] + ep := pv.Interface().(extendableProto) + + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + m := ep.ExtensionMap() + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + + for _, extNum := range ids { + ext := m[extNum] + var desc *ExtensionDesc + if emap != nil { + desc = emap[extNum] + } + if desc == nil { + // Unknown extension. + if err := writeUnknownStruct(w, ext.enc); err != nil { + return err + } + continue + } + + pb, err := GetExtension(ep, desc) + if err != nil { + return fmt.Errorf("failed getting extension: %v", err) + } + + // Repeated extensions will appear as a slice. + if !desc.repeated() { + if err := writeExtension(w, desc.Name, pb); err != nil { + return err + } + } else { + v := reflect.ValueOf(pb) + for i := 0; i < v.Len(); i++ { + if err := writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + return err + } + } + } + } + return nil +} + +func writeExtension(w *textWriter, name string, pb interface{}) error { + if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := writeAny(w, reflect.ValueOf(pb), nil); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + return nil +} + +func (w *textWriter) writeIndent() { + if !w.complete { + return + } + remain := w.ind * 2 + for remain > 0 { + n := remain + if n > len(spaces) { + n = len(spaces) + } + w.w.Write(spaces[:n]) + remain -= n + } + w.complete = false +} + +func marshalText(w io.Writer, pb Message, compact bool) error { + val := reflect.ValueOf(pb) + if pb == nil || val.IsNil() { + w.Write([]byte("")) + return nil + } + var bw *bufio.Writer + ww, ok := w.(writer) + if !ok { + bw = bufio.NewWriter(w) + ww = bw + } + aw := &textWriter{ + w: ww, + complete: true, + compact: compact, + } + + if tm, ok := pb.(encoding.TextMarshaler); ok { + text, err := tm.MarshalText() + if err != nil { + return err + } + if _, err = aw.Write(text); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil + } + // Dereference the received pointer so we don't have outer < and >. + v := reflect.Indirect(val) + if err := writeStruct(aw, v); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil +} + +// MarshalText writes a given protocol buffer in text format. +// The only errors returned are from w. +func MarshalText(w io.Writer, pb Message) error { + return marshalText(w, pb, false) +} + +// MarshalTextString is the same as MarshalText, but returns the string directly. +func MarshalTextString(pb Message) string { + var buf bytes.Buffer + marshalText(&buf, pb, false) + return buf.String() +} + +// CompactText writes a given protocol buffer in compact text format (one line). +func CompactText(w io.Writer, pb Message) error { return marshalText(w, pb, true) } + +// CompactTextString is the same as CompactText, but returns the string directly. +func CompactTextString(pb Message) string { + var buf bytes.Buffer + marshalText(&buf, pb, true) + return buf.String() +} diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go new file mode 100644 index 000000000..451323262 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -0,0 +1,806 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for parsing the Text protocol buffer format. +// TODO: message sets. + +import ( + "encoding" + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "unicode/utf8" +) + +type ParseError struct { + Message string + Line int // 1-based line number + Offset int // 0-based byte offset from start of input +} + +func (p *ParseError) Error() string { + if p.Line == 1 { + // show offset only for first line + return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) + } + return fmt.Sprintf("line %d: %v", p.Line, p.Message) +} + +type token struct { + value string + err *ParseError + line int // line number + offset int // byte number from start of input, not start of line + unquoted string // the unquoted version of value, if it was a quoted string +} + +func (t *token) String() string { + if t.err == nil { + return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) + } + return fmt.Sprintf("parse error: %v", t.err) +} + +type textParser struct { + s string // remaining input + done bool // whether the parsing is finished (success or error) + backed bool // whether back() was called + offset, line int + cur token +} + +func newTextParser(s string) *textParser { + p := new(textParser) + p.s = s + p.line = 1 + p.cur.line = 1 + return p +} + +func (p *textParser) errorf(format string, a ...interface{}) *ParseError { + pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} + p.cur.err = pe + p.done = true + return pe +} + +// Numbers and identifiers are matched by [-+._A-Za-z0-9] +func isIdentOrNumberChar(c byte) bool { + switch { + case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': + return true + case '0' <= c && c <= '9': + return true + } + switch c { + case '-', '+', '.', '_': + return true + } + return false +} + +func isWhitespace(c byte) bool { + switch c { + case ' ', '\t', '\n', '\r': + return true + } + return false +} + +func isQuote(c byte) bool { + switch c { + case '"', '\'': + return true + } + return false +} + +func (p *textParser) skipWhitespace() { + i := 0 + for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { + if p.s[i] == '#' { + // comment; skip to end of line or input + for i < len(p.s) && p.s[i] != '\n' { + i++ + } + if i == len(p.s) { + break + } + } + if p.s[i] == '\n' { + p.line++ + } + i++ + } + p.offset += i + p.s = p.s[i:len(p.s)] + if len(p.s) == 0 { + p.done = true + } +} + +func (p *textParser) advance() { + // Skip whitespace + p.skipWhitespace() + if p.done { + return + } + + // Start of non-whitespace + p.cur.err = nil + p.cur.offset, p.cur.line = p.offset, p.line + p.cur.unquoted = "" + switch p.s[0] { + case '<', '>', '{', '}', ':', '[', ']', ';', ',': + // Single symbol + p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] + case '"', '\'': + // Quoted string + i := 1 + for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { + if p.s[i] == '\\' && i+1 < len(p.s) { + // skip escaped char + i++ + } + i++ + } + if i >= len(p.s) || p.s[i] != p.s[0] { + p.errorf("unmatched quote") + return + } + unq, err := unquoteC(p.s[1:i], rune(p.s[0])) + if err != nil { + p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) + return + } + p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] + p.cur.unquoted = unq + default: + i := 0 + for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { + i++ + } + if i == 0 { + p.errorf("unexpected byte %#x", p.s[0]) + return + } + p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] + } + p.offset += len(p.cur.value) +} + +var ( + errBadUTF8 = errors.New("proto: bad UTF-8") + errBadHex = errors.New("proto: bad hexadecimal") +) + +func unquoteC(s string, quote rune) (string, error) { + // This is based on C++'s tokenizer.cc. + // Despite its name, this is *not* parsing C syntax. + // For instance, "\0" is an invalid quoted string. + + // Avoid allocation in trivial cases. + simple := true + for _, r := range s { + if r == '\\' || r == quote { + simple = false + break + } + } + if simple { + return s, nil + } + + buf := make([]byte, 0, 3*len(s)/2) + for len(s) > 0 { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", errBadUTF8 + } + s = s[n:] + if r != '\\' { + if r < utf8.RuneSelf { + buf = append(buf, byte(r)) + } else { + buf = append(buf, string(r)...) + } + continue + } + + ch, tail, err := unescape(s) + if err != nil { + return "", err + } + buf = append(buf, ch...) + s = tail + } + return string(buf), nil +} + +func unescape(s string) (ch string, tail string, err error) { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", "", errBadUTF8 + } + s = s[n:] + switch r { + case 'a': + return "\a", s, nil + case 'b': + return "\b", s, nil + case 'f': + return "\f", s, nil + case 'n': + return "\n", s, nil + case 'r': + return "\r", s, nil + case 't': + return "\t", s, nil + case 'v': + return "\v", s, nil + case '?': + return "?", s, nil // trigraph workaround + case '\'', '"', '\\': + return string(r), s, nil + case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': + if len(s) < 2 { + return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) + } + base := 8 + ss := s[:2] + s = s[2:] + if r == 'x' || r == 'X' { + base = 16 + } else { + ss = string(r) + ss + } + i, err := strconv.ParseUint(ss, base, 8) + if err != nil { + return "", "", err + } + return string([]byte{byte(i)}), s, nil + case 'u', 'U': + n := 4 + if r == 'U' { + n = 8 + } + if len(s) < n { + return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) + } + + bs := make([]byte, n/2) + for i := 0; i < n; i += 2 { + a, ok1 := unhex(s[i]) + b, ok2 := unhex(s[i+1]) + if !ok1 || !ok2 { + return "", "", errBadHex + } + bs[i/2] = a<<4 | b + } + s = s[n:] + return string(bs), s, nil + } + return "", "", fmt.Errorf(`unknown escape \%c`, r) +} + +// Adapted from src/pkg/strconv/quote.go. +func unhex(b byte) (v byte, ok bool) { + switch { + case '0' <= b && b <= '9': + return b - '0', true + case 'a' <= b && b <= 'f': + return b - 'a' + 10, true + case 'A' <= b && b <= 'F': + return b - 'A' + 10, true + } + return 0, false +} + +// Back off the parser by one token. Can only be done between calls to next(). +// It makes the next advance() a no-op. +func (p *textParser) back() { p.backed = true } + +// Advances the parser and returns the new current token. +func (p *textParser) next() *token { + if p.backed || p.done { + p.backed = false + return &p.cur + } + p.advance() + if p.done { + p.cur.value = "" + } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { + // Look for multiple quoted strings separated by whitespace, + // and concatenate them. + cat := p.cur + for { + p.skipWhitespace() + if p.done || !isQuote(p.s[0]) { + break + } + p.advance() + if p.cur.err != nil { + return &p.cur + } + cat.value += " " + p.cur.value + cat.unquoted += p.cur.unquoted + } + p.done = false // parser may have seen EOF, but we want to return cat + p.cur = cat + } + return &p.cur +} + +func (p *textParser) consumeToken(s string) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != s { + p.back() + return p.errorf("expected %q, found %q", s, tok.value) + } + return nil +} + +// Return a RequiredNotSetError indicating which required field was not set. +func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < st.NumField(); i++ { + if !isNil(sv.Field(i)) { + continue + } + + props := sprops.Prop[i] + if props.Required { + return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} + } + } + return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen +} + +// Returns the index in the struct for the named field, as well as the parsed tag properties. +func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { + i, ok := sprops.decoderOrigNames[name] + if ok { + return i, sprops.Prop[i], true + } + return -1, nil, false +} + +// Consume a ':' from the input stream (if the next token is a colon), +// returning an error if a colon is needed but not present. +func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ":" { + // Colon is optional when the field is a group or message. + needColon := true + switch props.Wire { + case "group": + needColon = false + case "bytes": + // A "bytes" field is either a message, a string, or a repeated field; + // those three become *T, *string and []T respectively, so we can check for + // this field being a pointer to a non-string. + if typ.Kind() == reflect.Ptr { + // *T or *string + if typ.Elem().Kind() == reflect.String { + break + } + } else if typ.Kind() == reflect.Slice { + // []T or []*T + if typ.Elem().Kind() != reflect.Ptr { + break + } + } else if typ.Kind() == reflect.String { + // The proto3 exception is for a string field, + // which requires a colon. + break + } + needColon = false + } + if needColon { + return p.errorf("expected ':', found %q", tok.value) + } + p.back() + } + return nil +} + +func (p *textParser) readStruct(sv reflect.Value, terminator string) error { + st := sv.Type() + sprops := GetProperties(st) + reqCount := sprops.reqCount + var reqFieldErr error + fieldSet := make(map[string]bool) + // A struct is a sequence of "name: value", terminated by one of + // '>' or '}', or the end of the input. A name may also be + // "[extension]". + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + if tok.value == "[" { + // Looks like an extension. + // + // TODO: Check whether we need to handle + // namespace rooted names (e.g. ".something.Foo"). + tok = p.next() + if tok.err != nil { + return tok.err + } + var desc *ExtensionDesc + // This could be faster, but it's functional. + // TODO: Do something smarter than a linear scan. + for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { + if d.Name == tok.value { + desc = d + break + } + } + if desc == nil { + return p.errorf("unrecognized extension %q", tok.value) + } + // Check the extension terminator. + tok = p.next() + if tok.err != nil { + return tok.err + } + if tok.value != "]" { + return p.errorf("unrecognized extension terminator %q", tok.value) + } + + props := &Properties{} + props.Parse(desc.Tag) + + typ := reflect.TypeOf(desc.ExtensionType) + if err := p.checkForColon(props, typ); err != nil { + return err + } + + rep := desc.repeated() + + // Read the extension structure, and set it in + // the value we're constructing. + var ext reflect.Value + if !rep { + ext = reflect.New(typ).Elem() + } else { + ext = reflect.New(typ.Elem()).Elem() + } + if err := p.readAny(ext, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + ep := sv.Addr().Interface().(extendableProto) + if !rep { + SetExtension(ep, desc, ext.Interface()) + } else { + old, err := GetExtension(ep, desc) + var sl reflect.Value + if err == nil { + sl = reflect.ValueOf(old) // existing slice + } else { + sl = reflect.MakeSlice(typ, 0, 1) + } + sl = reflect.Append(sl, ext) + SetExtension(ep, desc, sl.Interface()) + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + continue + } + + // This is a normal, non-extension field. + name := tok.value + var dst reflect.Value + fi, props, ok := structFieldByName(sprops, name) + if ok { + dst = sv.Field(fi) + } else if oop, ok := sprops.OneofTypes[name]; ok { + // It is a oneof. + props = oop.Prop + nv := reflect.New(oop.Type.Elem()) + dst = nv.Elem().Field(0) + sv.Field(oop.Field).Set(nv) + } + if !dst.IsValid() { + return p.errorf("unknown field name %q in %v", name, st) + } + + if dst.Kind() == reflect.Map { + // Consume any colon. + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Construct the map if it doesn't already exist. + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + key := reflect.New(dst.Type().Key()).Elem() + val := reflect.New(dst.Type().Elem()).Elem() + + // The map entry should be this sequence of tokens: + // < key : KEY value : VALUE > + // Technically the "key" and "value" could come in any order, + // but in practice they won't. + + tok := p.next() + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + if err := p.consumeToken("key"); err != nil { + return err + } + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.mkeyprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + if err := p.consumeToken("value"); err != nil { + return err + } + if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.mvalprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + if err := p.consumeToken(terminator); err != nil { + return err + } + + dst.SetMapIndex(key, val) + continue + } + + // Check that it's not already set if it's not a repeated field. + if !props.Repeated && fieldSet[name] { + return p.errorf("non-repeated field %q was repeated", name) + } + + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Parse into the field. + fieldSet[name] = true + if err := p.readAny(dst, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } else if props.Required { + reqCount-- + } + + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + + } + + if reqCount > 0 { + return p.missingRequiredFieldError(sv) + } + return reqFieldErr +} + +// consumeOptionalSeparator consumes an optional semicolon or comma. +// It is used in readStruct to provide backward compatibility. +func (p *textParser) consumeOptionalSeparator() error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ";" && tok.value != "," { + p.back() + } + return nil +} + +func (p *textParser) readAny(v reflect.Value, props *Properties) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "" { + return p.errorf("unexpected EOF") + } + + switch fv := v; fv.Kind() { + case reflect.Slice: + at := v.Type() + if at.Elem().Kind() == reflect.Uint8 { + // Special case for []byte + if tok.value[0] != '"' && tok.value[0] != '\'' { + // Deliberately written out here, as the error after + // this switch statement would write "invalid []byte: ...", + // which is not as user-friendly. + return p.errorf("invalid string: %v", tok.value) + } + bytes := []byte(tok.unquoted) + fv.Set(reflect.ValueOf(bytes)) + return nil + } + // Repeated field. + if tok.value == "[" { + // Repeated field with list notation, like [1,2,3]. + for { + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + err := p.readAny(fv.Index(fv.Len()-1), props) + if err != nil { + return err + } + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "]" { + break + } + if tok.value != "," { + return p.errorf("Expected ']' or ',' found %q", tok.value) + } + } + return nil + } + // One value of the repeated field. + p.back() + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + return p.readAny(fv.Index(fv.Len()-1), props) + case reflect.Bool: + // Either "true", "false", 1 or 0. + switch tok.value { + case "true", "1": + fv.SetBool(true) + return nil + case "false", "0": + fv.SetBool(false) + return nil + } + case reflect.Float32, reflect.Float64: + v := tok.value + // Ignore 'f' for compatibility with output generated by C++, but don't + // remove 'f' when the value is "-inf" or "inf". + if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { + v = v[:len(v)-1] + } + if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { + fv.SetFloat(f) + return nil + } + case reflect.Int32: + if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { + fv.SetInt(x) + return nil + } + + if len(props.Enum) == 0 { + break + } + m, ok := enumValueMaps[props.Enum] + if !ok { + break + } + x, ok := m[tok.value] + if !ok { + break + } + fv.SetInt(int64(x)) + return nil + case reflect.Int64: + if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { + fv.SetInt(x) + return nil + } + + case reflect.Ptr: + // A basic field (indirected through pointer), or a repeated message/group + p.back() + fv.Set(reflect.New(fv.Type().Elem())) + return p.readAny(fv.Elem(), props) + case reflect.String: + if tok.value[0] == '"' || tok.value[0] == '\'' { + fv.SetString(tok.unquoted) + return nil + } + case reflect.Struct: + var terminator string + switch tok.value { + case "{": + terminator = "}" + case "<": + terminator = ">" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + // TODO: Handle nested messages which implement encoding.TextUnmarshaler. + return p.readStruct(fv, terminator) + case reflect.Uint32: + if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { + fv.SetUint(uint64(x)) + return nil + } + case reflect.Uint64: + if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { + fv.SetUint(x) + return nil + } + } + return p.errorf("invalid %v: %v", v.Type(), tok.value) +} + +// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb +// before starting to unmarshal, so any existing data in pb is always removed. +// If a required field is not set and no other error occurs, +// UnmarshalText returns *RequiredNotSetError. +func UnmarshalText(s string, pb Message) error { + if um, ok := pb.(encoding.TextUnmarshaler); ok { + err := um.UnmarshalText([]byte(s)) + return err + } + pb.Reset() + v := reflect.ValueOf(pb) + if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { + return pe + } + return nil +} diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE new file mode 100644 index 000000000..ae121a1e4 --- /dev/null +++ b/vendor/github.com/google/go-querystring/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go new file mode 100644 index 000000000..90dcabb80 --- /dev/null +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -0,0 +1,311 @@ +// Copyright 2013 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. + +// Package query implements encoding of structs into URL query parameters. +// +// As a simple example: +// +// type Options struct { +// Query string `url:"q"` +// ShowAll bool `url:"all"` +// Page int `url:"page"` +// } +// +// opt := Options{ "foo", true, 2 } +// v, _ := query.Values(opt) +// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" +// +// The exact mapping between Go values and url.Values is described in the +// documentation for the Values() function. +package query + +import ( + "bytes" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +var timeType = reflect.TypeOf(time.Time{}) + +var encoderType = reflect.TypeOf(new(Encoder)).Elem() + +// Encoder is an interface implemented by any type that wishes to encode +// itself into URL values in a non-standard way. +type Encoder interface { + EncodeValues(key string, v *url.Values) error +} + +// Values returns the url.Values encoding of v. +// +// Values expects to be passed a struct, and traverses it recursively using the +// following encoding rules. +// +// Each exported struct field is encoded as a URL parameter unless +// +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option +// +// The empty values are false, 0, any nil pointer or interface value, any array +// slice, map, or string of length zero, and any time.Time that returns true +// for IsZero(). +// +// The URL parameter name defaults to the struct field name but can be +// specified in the struct field's tag value. The "url" key in the struct +// field's tag value is the key name, followed by an optional comma and +// options. For example: +// +// // Field is ignored by this package. +// Field int `url:"-"` +// +// // Field appears as URL parameter "myName". +// Field int `url:"myName"` +// +// // Field appears as URL parameter "myName" and the field is omitted if +// // its value is empty +// Field int `url:"myName,omitempty"` +// +// // Field appears as URL parameter "Field" (the default), but the field +// // is skipped if empty. Note the leading comma. +// Field int `url:",omitempty"` +// +// For encoding individual field values, the following type-dependent rules +// apply: +// +// Boolean values default to encoding as the strings "true" or "false". +// Including the "int" option signals that the field should be encoded as the +// strings "1" or "0". +// +// time.Time values default to encoding as RFC3339 timestamps. Including the +// "unix" option signals that the field should be encoded as a Unix time (see +// time.Unix()) +// +// Slice and Array values default to encoding as multiple URL values of the +// same name. Including the "comma" option signals that the field should be +// encoded as a single comma-delimited value. Including the "space" option +// similarly encodes the value as a single space-delimited string. Including +// the "brackets" option signals that the multiple URL values should have "[]" +// appended to the value name. +// +// Anonymous struct fields are usually encoded as if their inner exported +// fields were fields in the outer struct, subject to the standard Go +// visibility rules. An anonymous struct field with a name given in its URL +// tag is treated as having that name, rather than being anonymous. +// +// Non-nil pointer values are encoded as the value pointed to. +// +// Nested structs are encoded including parent fields in value names for +// scoping. e.g: +// +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// +// All other values are encoded using their default string representation. +// +// Multiple fields that encode to the same URL parameter name will be included +// as multiple URL values of the same name. +func Values(v interface{}) (url.Values, error) { + values := make(url.Values) + val := reflect.ValueOf(v) + for val.Kind() == reflect.Ptr { + if val.IsNil() { + return values, nil + } + val = val.Elem() + } + + if v == nil { + return values, nil + } + + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) + } + + err := reflectValue(values, val, "") + return values, err +} + +// reflectValue populates the values parameter from the struct fields in val. +// Embedded structs are followed recursively (using the rules defined in the +// Values function documentation) breadth-first. +func reflectValue(values url.Values, val reflect.Value, scope string) error { + var embedded []reflect.Value + + typ := val.Type() + for i := 0; i < typ.NumField(); i++ { + sf := typ.Field(i) + if sf.PkgPath != "" { // unexported + continue + } + + sv := val.Field(i) + tag := sf.Tag.Get("url") + if tag == "-" { + continue + } + name, opts := parseTag(tag) + if name == "" { + if sf.Anonymous && sv.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, sv) + continue + } + + name = sf.Name + } + + if scope != "" { + name = scope + "[" + name + "]" + } + + if opts.Contains("omitempty") && isEmptyValue(sv) { + continue + } + + if sv.Type().Implements(encoderType) { + if !reflect.Indirect(sv).IsValid() { + sv = reflect.New(sv.Type().Elem()) + } + + m := sv.Interface().(Encoder) + if err := m.EncodeValues(name, &values); err != nil { + return err + } + continue + } + + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { + var del byte + if opts.Contains("comma") { + del = ',' + } else if opts.Contains("space") { + del = ' ' + } else if opts.Contains("brackets") { + name = name + "[]" + } + + if del != 0 { + s := new(bytes.Buffer) + first := true + for i := 0; i < sv.Len(); i++ { + if first { + first = false + } else { + s.WriteByte(del) + } + s.WriteString(valueString(sv.Index(i), opts)) + } + values.Add(name, s.String()) + } else { + for i := 0; i < sv.Len(); i++ { + values.Add(name, valueString(sv.Index(i), opts)) + } + } + continue + } + + if sv.Type() == timeType { + values.Add(name, valueString(sv, opts)) + continue + } + + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + + if sv.Kind() == reflect.Struct { + reflectValue(values, sv, name) + continue + } + + values.Add(name, valueString(sv, opts)) + } + + for _, f := range embedded { + if err := reflectValue(values, f, scope); err != nil { + return err + } + } + + return nil +} + +// valueString returns the string representation of a value. +func valueString(v reflect.Value, opts tagOptions) string { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + return "" + } + v = v.Elem() + } + + if v.Kind() == reflect.Bool && opts.Contains("int") { + if v.Bool() { + return "1" + } + return "0" + } + + if v.Type() == timeType { + t := v.Interface().(time.Time) + if opts.Contains("unix") { + return strconv.FormatInt(t.Unix(), 10) + } + return t.Format(time.RFC3339) + } + + return fmt.Sprint(v.Interface()) +} + +// isEmptyValue checks if a value should be considered empty for the purposes +// of omitting fields with the "omitempty" option. +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + + if v.Type() == timeType { + return v.Interface().(time.Time).IsZero() + } + + return false +} + +// tagOptions is the string following a comma in a struct field's "url" tag, or +// the empty string. It does not include the leading comma. +type tagOptions []string + +// parseTag splits a struct field's url tag into its name and comma-separated +// options. +func parseTag(tag string) (string, tagOptions) { + s := strings.Split(tag, ",") + return s[0], s[1:] +} + +// Contains checks whether the tagOptions contains the specified option. +func (o tagOptions) Contains(option string) bool { + for _, s := range o { + if s == option { + return true + } + } + return false +} diff --git a/vendor/github.com/hashicorp/atlas-go/LICENSE b/vendor/github.com/hashicorp/atlas-go/LICENSE new file mode 100644 index 000000000..82b4de97c --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/atlas-go/archive/archive.go b/vendor/github.com/hashicorp/atlas-go/archive/archive.go new file mode 100644 index 000000000..d9232b4f0 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/archive.go @@ -0,0 +1,500 @@ +// archive is package that helps create archives in a format that +// Atlas expects with its various upload endpoints. +package archive + +import ( + "archive/tar" + "bufio" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +// Archive is the resulting archive. The archive data is generally streamed +// so the io.ReadCloser can be used to backpressure the archive progress +// and avoid memory pressure. +type Archive struct { + io.ReadCloser + + Size int64 + Metadata map[string]string +} + +// ArchiveOpts are the options for defining how the archive will be built. +type ArchiveOpts struct { + // Exclude and Include are filters of files to include/exclude in + // the archive when creating it from a directory. These filters should + // be relative to the packaging directory and should be basic glob + // patterns. + Exclude []string + Include []string + + // Extra is a mapping of extra files to include within the archive. The + // key should be the path within the archive and the value should be + // an absolute path to the file to put into the archive. These extra + // files will override any other files in the archive. + Extra map[string]string + + // VCS, if true, will detect and use a VCS system to determine what + // files to include the archive. + VCS bool +} + +// IsSet says whether any options were set. +func (o *ArchiveOpts) IsSet() bool { + return len(o.Exclude) > 0 || len(o.Include) > 0 || o.VCS +} + +// CreateArchive takes the given path and ArchiveOpts and archives it. +// +// The archive will be fully completed and put into a temporary file. +// This must be done to retrieve the content length of the archive which +// is needed for almost all operations involving archives with Atlas. Because +// of this, sufficient disk space will be required to buffer the archive. +func CreateArchive(path string, opts *ArchiveOpts) (*Archive, error) { + log.Printf("[INFO] creating archive from %s", path) + + // Dereference any symlinks and determine the real path and info + fi, err := os.Lstat(path) + if err != nil { + return nil, err + } + if fi.Mode()&os.ModeSymlink != 0 { + path, fi, err = readLinkFull(path, fi) + if err != nil { + return nil, err + } + } + + // Windows + path = filepath.ToSlash(path) + + // Direct file paths cannot have archive options + if !fi.IsDir() && opts.IsSet() { + return nil, fmt.Errorf( + "options such as exclude, include, and VCS can't be set when " + + "the path is a file.") + } + + if fi.IsDir() { + return archiveDir(path, opts) + } else { + return archiveFile(path) + } +} + +func archiveFile(path string) (*Archive, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + + if _, err := gzip.NewReader(f); err == nil { + // Reset the read offset for future reading + if _, err := f.Seek(0, 0); err != nil { + f.Close() + return nil, err + } + + // Get the file info for the size + fi, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + + // This is a gzip file, let it through. + return &Archive{ReadCloser: f, Size: fi.Size()}, nil + } + + // Close the file, no use for it anymore + f.Close() + + // We have a single file that is not gzipped. Compress it. + path, err = filepath.Abs(path) + if err != nil { + return nil, err + } + + // Act like we're compressing a directory, but only include this one + // file. + return archiveDir(filepath.Dir(path), &ArchiveOpts{ + Include: []string{filepath.Base(path)}, + }) +} + +func archiveDir(root string, opts *ArchiveOpts) (*Archive, error) { + + var vcsInclude []string + var metadata map[string]string + if opts.VCS { + var err error + + if err = vcsPreflight(root); err != nil { + return nil, err + } + + vcsInclude, err = vcsFiles(root) + if err != nil { + return nil, err + } + + metadata, err = vcsMetadata(root) + if err != nil { + return nil, err + } + } + + // Make sure the root path is absolute + root, err := filepath.Abs(root) + if err != nil { + return nil, err + } + + // Create the temporary file that we'll send the archive data to. + archiveF, err := ioutil.TempFile("", "atlas-archive") + if err != nil { + return nil, err + } + + // Create the wrapper for the result which will automatically + // remove the temporary file on close. + archiveWrapper := &readCloseRemover{F: archiveF} + + // Buffer the writer so that we can push as much data to disk at + // a time as possible. 4M should be good. + bufW := bufio.NewWriterSize(archiveF, 4096*1024) + + // Gzip compress all the output data + gzipW := gzip.NewWriter(bufW) + + // Tar the file contents + tarW := tar.NewWriter(gzipW) + + // First, walk the path and do the normal files + werr := filepath.Walk(root, copyDirWalkFn( + tarW, root, "", opts, vcsInclude)) + if werr == nil { + // If that succeeded, handle the extra files + werr = copyExtras(tarW, opts.Extra) + } + + // Attempt to close all the things. If we get an error on the way + // and we haven't had an error yet, then record that as the critical + // error. But we still try to close everything. + + // Close the tar writer + if err := tarW.Close(); err != nil && werr == nil { + werr = err + } + + // Close the gzip writer + if err := gzipW.Close(); err != nil && werr == nil { + werr = err + } + + // Flush the buffer + if err := bufW.Flush(); err != nil && werr == nil { + werr = err + } + + // If we had an error, then close the file (removing it) and + // return the error. + if werr != nil { + archiveWrapper.Close() + return nil, werr + } + + // Seek to the beginning + if _, err := archiveWrapper.F.Seek(0, 0); err != nil { + archiveWrapper.Close() + return nil, err + } + + // Get the file information so we can get the size + fi, err := archiveWrapper.F.Stat() + if err != nil { + archiveWrapper.Close() + return nil, err + } + + return &Archive{ + ReadCloser: archiveWrapper, + Size: fi.Size(), + Metadata: metadata, + }, nil +} + +func copyDirWalkFn( + tarW *tar.Writer, root string, prefix string, + opts *ArchiveOpts, vcsInclude []string) filepath.WalkFunc { + + errFunc := func(err error) filepath.WalkFunc { + return func(string, os.FileInfo, error) error { + return err + } + } + + // Windows + root = filepath.ToSlash(root) + + var includeMap map[string]struct{} + + // If we have an include/exclude pattern set, then setup the lookup + // table to determine what we want to include. + if opts != nil && len(opts.Include) > 0 { + includeMap = make(map[string]struct{}) + for _, pattern := range opts.Include { + matches, err := filepath.Glob(filepath.Join(root, pattern)) + if err != nil { + return errFunc(fmt.Errorf( + "error checking include glob '%s': %s", + pattern, err)) + } + + for _, path := range matches { + // Windows + path = filepath.ToSlash(path) + subpath, err := filepath.Rel(root, path) + subpath = filepath.ToSlash(subpath) + + if err != nil { + return errFunc(err) + } + + for { + includeMap[subpath] = struct{}{} + subpath = filepath.Dir(subpath) + if subpath == "." { + break + } + } + } + } + } + + return func(path string, info os.FileInfo, err error) error { + path = filepath.ToSlash(path) + + if err != nil { + return err + } + + // Get the relative path from the path since it contains the root + // plus the path. + subpath, err := filepath.Rel(root, path) + if err != nil { + return err + } + if subpath == "." { + return nil + } + if prefix != "" { + subpath = filepath.Join(prefix, subpath) + } + // Windows + subpath = filepath.ToSlash(subpath) + + // If we have a list of VCS files, check that first + skip := false + if len(vcsInclude) > 0 { + skip = true + for _, f := range vcsInclude { + if f == subpath { + skip = false + break + } + + if info.IsDir() && strings.HasPrefix(f, subpath+"/") { + skip = false + break + } + } + } + + // If include is present, we only include what is listed + if len(includeMap) > 0 { + if _, ok := includeMap[subpath]; !ok { + skip = true + } + } + + // If exclude, it is one last gate to excluding files + if opts != nil { + for _, exclude := range opts.Exclude { + match, err := filepath.Match(exclude, subpath) + if err != nil { + return err + } + if match { + skip = true + break + } + } + } + + // If we have to skip this file, then skip it, properly skipping + // children if we're a directory. + if skip { + if info.IsDir() { + return filepath.SkipDir + } + + return nil + } + + // If this is a symlink, then we need to get the symlink target + // rather than the symlink itself. + if info.Mode()&os.ModeSymlink != 0 { + target, info, err := readLinkFull(path, info) + if err != nil { + return err + } + + // Copy the concrete entry for this path. This will either + // be the file itself or just a directory entry. + if err := copyConcreteEntry(tarW, subpath, target, info); err != nil { + return err + } + + if info.IsDir() { + return filepath.Walk(target, copyDirWalkFn( + tarW, target, subpath, opts, vcsInclude)) + } + } + + return copyConcreteEntry(tarW, subpath, path, info) + } +} + +func copyConcreteEntry( + tarW *tar.Writer, entry string, + path string, info os.FileInfo) error { + // Windows + path = filepath.ToSlash(path) + + // Build the file header for the tar entry + header, err := tar.FileInfoHeader(info, path) + if err != nil { + return fmt.Errorf( + "failed creating archive header: %s", path) + } + + // Modify the header to properly be the full entry name + header.Name = entry + if info.IsDir() { + header.Name += "/" + } + + // Write the header first to the archive. + if err := tarW.WriteHeader(header); err != nil { + return fmt.Errorf( + "failed writing archive header: %s", path) + } + + // If it is a directory, then we're done (no body to write) + if info.IsDir() { + return nil + } + + // Open the real file to write the data + f, err := os.Open(path) + if err != nil { + return fmt.Errorf( + "failed opening file '%s' to write compressed archive.", path) + } + defer f.Close() + + if _, err = io.Copy(tarW, f); err != nil { + return fmt.Errorf( + "failed copying file to archive: %s", path) + } + + return nil +} + +func copyExtras(w *tar.Writer, extra map[string]string) error { + for entry, path := range extra { + info, err := os.Stat(path) + if err != nil { + return err + } + + // No matter what, write the entry. If this is a directory, + // it'll just write the directory header. + if err := copyConcreteEntry(w, entry, path, info); err != nil { + return err + } + + // If this is a directory, then we walk the internal contents + // and copy those as well. + if info.IsDir() { + err := filepath.Walk(path, copyDirWalkFn( + w, path, entry, nil, nil)) + if err != nil { + return err + } + } + } + + return nil +} + +func readLinkFull(path string, info os.FileInfo) (string, os.FileInfo, error) { + // Read the symlink continously until we reach a concrete file. + target := path + tries := 0 + for info.Mode()&os.ModeSymlink != 0 { + var err error + target, err = os.Readlink(target) + if err != nil { + return "", nil, err + } + if !filepath.IsAbs(target) { + target, err = filepath.Abs(target) + if err != nil { + return "", nil, err + } + } + info, err = os.Lstat(target) + if err != nil { + return "", nil, err + } + + tries++ + if tries > 100 { + return "", nil, fmt.Errorf( + "Symlink for %s is too deep, over 100 levels deep", + path) + } + } + + return target, info, nil +} + +// readCloseRemover is an io.ReadCloser implementation that will remove +// the file on Close(). We use this to clean up our temporary file for +// the archive. +type readCloseRemover struct { + F *os.File +} + +func (r *readCloseRemover) Read(p []byte) (int, error) { + return r.F.Read(p) +} + +func (r *readCloseRemover) Close() error { + // First close the file + err := r.F.Close() + + // Next make sure to remove it, or at least try, regardless of error + // above. + os.Remove(r.F.Name()) + + return err +} diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-dir-mode/file.txt b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-dir-mode/file.txt new file mode 100644 index 000000000..dc2507e82 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-dir-mode/file.txt @@ -0,0 +1 @@ +I should be mode 0777 diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file-compressed/file.tar.gz b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file-compressed/file.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bed30fb489d3440b929dd74eb3ec89a341e8d8ea GIT binary patch literal 144 zcmb2|=3rP86%fL}{Pv4G`|0>{1{6?}&-ggIkDWn-fdK%*`#(ki literal 0 HcmV?d00001 diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file/foo.txt b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file/foo.txt new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-file/foo.txt @@ -0,0 +1 @@ +foo diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/baz.txt b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/baz.txt new file mode 100644 index 000000000..76018072e --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/baz.txt @@ -0,0 +1 @@ +baz diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/foo.txt b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/foo.txt new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-flat/foo.txt @@ -0,0 +1 @@ +foo diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/COMMIT_EDITMSG b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/COMMIT_EDITMSG new file mode 100644 index 000000000..e7e768a4a --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/COMMIT_EDITMSG @@ -0,0 +1,12 @@ +Those files tho +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# On branch master +# +# Initial commit +# +# Changes to be committed: +# new file: bar.txt +# new file: foo.txt +# new file: subdir/hello.txt +# diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/HEAD b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/config b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/config new file mode 100644 index 000000000..252f2e347 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true +[remote "origin"] + url = https://github.com/hashicorp/origin.git + fetch = +refs/heads/*:refs/remotes/origin/* +[remote "upstream"] + url = https://github.com/hashicorp/upstream.git + fetch = +refs/heads/*:refs/remotes/upstream/* diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/description b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/applypatch-msg.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/applypatch-msg.sample new file mode 100644 index 000000000..8b2a2fe84 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +test -x "$GIT_DIR/hooks/commit-msg" && + exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} +: diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/commit-msg.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/commit-msg.sample new file mode 100644 index 000000000..b58d1184a --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/post-update.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/post-update.sample new file mode 100644 index 000000000..ec17ec193 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-applypatch.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-applypatch.sample new file mode 100644 index 000000000..b1f187c2e --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} +: diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-commit.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-commit.sample new file mode 100644 index 000000000..68d62d544 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-push.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-push.sample new file mode 100644 index 000000000..1f3bcebfd --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-push.sample @@ -0,0 +1,54 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +z40=0000000000000000000000000000000000000000 + +IFS=' ' +while read local_ref local_sha remote_ref remote_sha +do + if [ "$local_sha" = $z40 ] + then + # Handle delete + : + else + if [ "$remote_sha" = $z40 ] + then + # New branch, examine all commits + range="$local_sha" + else + # Update to existing branch, examine new commits + range="$remote_sha..$local_sha" + fi + + # Check for WIP commit + commit=`git rev-list -n 1 --grep '^WIP' "$range"` + if [ -n "$commit" ] + then + echo "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-rebase.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-rebase.sample new file mode 100644 index 000000000..9773ed4cb --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up-to-date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +exit 0 + +################################################################ + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/prepare-commit-msg.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/prepare-commit-msg.sample new file mode 100644 index 000000000..f093a02ec --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/prepare-commit-msg.sample @@ -0,0 +1,36 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first comments out the +# "Conflicts:" part of a merge commit. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +case "$2,$3" in + merge,) + /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; + +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$1" ;; + + *) ;; +esac + +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/update.sample b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/update.sample new file mode 100644 index 000000000..d84758373 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to blocks unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/index b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/index new file mode 100644 index 0000000000000000000000000000000000000000..b9699684975201d64c8d308bce4f5cc14180b965 GIT binary patch literal 256 zcmZ?q402{*U|<4b=8)pHZXnG7qZt_(SQy+7MlvuoE@5C`{0fv30b-VLu~U)lr+?OF zZ}n8zw`}b_72Wn{4D3mXMS3L_B}n?w%&A8=N44f?iq6IbAs>29*y~QQ3;S!gZzcnK wT7Eu$a~g> 1414446684 -0700 commit (initial): Those files tho diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/logs/refs/heads/master b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/logs/refs/heads/master new file mode 100644 index 000000000..1c469022b --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 7525d17cbbb56f3253a20903ffddc07c6c935c76 Mitchell Hashimoto 1414446684 -0700 commit (initial): Those files tho diff --git a/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 b/vendor/github.com/hashicorp/atlas-go/archive/test-fixtures/archive-git/DOTgit/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 new file mode 100644 index 0000000000000000000000000000000000000000..bdcf704c9e663f3a11b3146b1b455bc2581b4761 GIT binary patch literal 19 acmb9XD~D{Ff%bx$Vkn}$=55XC}B{oIhvxgaY4w3o)h-EQ|!Y2 M+U=VO08e!hF+vm7FlI0`FfcPQQAkQG(krPbVF(vH71@6JXKnUYPlbKU*4|Um zZGQ$;l9rzjR-#&SG(~6Qf{+hAC+u~n*oFPI+c(q100 https://github.com/foo/bar.git + urlSplit := strings.Split(split[1], " ") + result[remote] = strings.TrimSpace(urlSplit[0]) + } + } + + return result, nil +} + +// gitPreflight is the pre-flight command that runs for Git-based VCSs +func gitPreflight(path string) error { + var stderr, stdout bytes.Buffer + + cmd := exec.Command("git", "--version") + cmd.Dir = path + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("error getting git version: %s\nstdout: %s\nstderr: %s", + err, stdout.String(), stderr.String()) + } + + // Check if the output is valid + output := strings.Split(strings.TrimSpace(stdout.String()), " ") + if len(output) < 1 { + log.Printf("[WARN] could not extract version output from Git") + return nil + } + + // Parse the version + gitv, err := version.NewVersion(output[len(output)-1]) + if err != nil { + log.Printf("[WARN] could not parse version output from Git") + return nil + } + + constraint, err := version.NewConstraint("> 1.8") + if err != nil { + log.Printf("[WARN] could not create version constraint to check") + return nil + } + if !constraint.Check(gitv) { + return fmt.Errorf("git version (%s) is too old, please upgrade", gitv.String()) + } + + return nil +} + +// gitMetadata is the function to parse and return Git metadata +func gitMetadata(path string) (map[string]string, error) { + // Future-self note: Git is NOT threadsafe, so we cannot run these + // operations in go routines or else you're going to have a really really + // bad day and Panda.State == "Sad" :( + + branch, err := gitBranch(path) + if err != nil { + return nil, err + } + + commit, err := gitCommit(path) + if err != nil { + return nil, err + } + + remotes, err := gitRemotes(path) + if err != nil { + return nil, err + } + + // Make the return result (we already know the size) + result := make(map[string]string, 2+len(remotes)) + + result["branch"] = branch + result["commit"] = commit + for remote, value := range remotes { + result[remote] = value + } + + return result, nil +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/application.go b/vendor/github.com/hashicorp/atlas-go/v1/application.go new file mode 100644 index 000000000..42cf88201 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/application.go @@ -0,0 +1,164 @@ +package atlas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" +) + +// appWrapper is the API wrapper since the server wraps the resulting object. +type appWrapper struct { + Application *App `json:"application"` +} + +// App represents a single instance of an application on the Atlas server. +type App struct { + // User is the namespace (username or organization) under which the + // Atlas application resides + User string `json:"username"` + + // Name is the name of the application + Name string `json:"name"` +} + +// Slug returns the slug format for this App (User/Name) +func (a *App) Slug() string { + return fmt.Sprintf("%s/%s", a.User, a.Name) +} + +// App gets the App by the given user space and name. In the event the App is +// not found (404), or for any other non-200 responses, an error is returned. +func (c *Client) App(user, name string) (*App, error) { + log.Printf("[INFO] getting application %s/%s", user, name) + + endpoint := fmt.Sprintf("/api/v1/vagrant/applications/%s/%s", user, name) + request, err := c.Request("GET", endpoint, nil) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var app App + if err := decodeJSON(response, &app); err != nil { + return nil, err + } + + return &app, nil +} + +// CreateApp creates a new App under the given user with the given name. If the +// App is created successfully, it is returned. If the server returns any +// errors, an error is returned. +func (c *Client) CreateApp(user, name string) (*App, error) { + log.Printf("[INFO] creating application %s/%s", user, name) + + body, err := json.Marshal(&appWrapper{&App{ + User: user, + Name: name, + }}) + if err != nil { + return nil, err + } + + endpoint := "/api/v1/vagrant/applications" + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var app App + if err := decodeJSON(response, &app); err != nil { + return nil, err + } + + return &app, nil +} + +// appVersion represents a specific version of an App in Atlas. It is actually +// an upload container/wrapper. +type appVersion struct { + UploadPath string `json:"upload_path"` + Token string `json:"token"` + Version uint64 `json:"version"` +} + +// appMetadataWrapper is a wrapper around a map the prefixes the json key with +// "metadata" when marshalled to format requests to the API properly. +type appMetadataWrapper struct { + Metadata map[string]interface{} `json:"metadata,omitempty"` +} + +// UploadApp creates and uploads a new version for the App. If the server does not +// find the application, an error is returned. If the server does not accept the +// data, an error is returned. +// +// It is the responsibility of the caller to create a properly-formed data +// object; this method blindly passes along the contents of the io.Reader. +func (c *Client) UploadApp(app *App, metadata map[string]interface{}, + data io.Reader, size int64) (uint64, error) { + + log.Printf("[INFO] uploading application %s (%d bytes) with metadata %q", + app.Slug(), size, metadata) + + endpoint := fmt.Sprintf("/api/v1/vagrant/applications/%s/%s/versions", + app.User, app.Name) + + // If metadata was given, setup the RequestOptions to pass in the metadata + // with the request. + var ro *RequestOptions + if metadata != nil { + // wrap the struct into the correct JSON format + wrapper := struct { + Application *appMetadataWrapper `json:"application"` + }{ + &appMetadataWrapper{metadata}, + } + m, err := json.Marshal(wrapper) + if err != nil { + return 0, err + } + + // Create the request options. + ro = &RequestOptions{ + Body: bytes.NewReader(m), + BodyLength: int64(len(m)), + } + } + + request, err := c.Request("POST", endpoint, ro) + if err != nil { + return 0, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return 0, err + } + + var av appVersion + if err := decodeJSON(response, &av); err != nil { + return 0, err + } + + if err := c.putFile(av.UploadPath, data, size); err != nil { + return 0, err + } + + return av.Version, nil +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/artifact.go b/vendor/github.com/hashicorp/atlas-go/v1/artifact.go new file mode 100644 index 000000000..28273df28 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/artifact.go @@ -0,0 +1,248 @@ +package atlas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" + "net/url" +) + +// Artifact represents a single instance of an artifact. +type Artifact struct { + // User and name are self-explanatory. Tag is the combination + // of both into "username/name" + User string `json:"username"` + Name string `json:"name"` + Tag string `json:",omitempty"` +} + +// ArtifactVersion represents a single version of an artifact. +type ArtifactVersion struct { + User string `json:"username"` + Name string `json:"name"` + Tag string `json:",omitempty"` + Type string `json:"artifact_type"` + ID string `json:"id"` + Version int `json:"version"` + Metadata map[string]string `json:"metadata"` + File bool `json:"file"` + Slug string `json:"slug"` + + UploadPath string `json:"upload_path"` + UploadToken string `json:"upload_token"` +} + +// ArtifactSearchOpts are the options used to search for an artifact. +type ArtifactSearchOpts struct { + User string + Name string + Type string + + Build string + Version string + Metadata map[string]string +} + +// UploadArtifactOpts are the options used to upload an artifact. +type UploadArtifactOpts struct { + User string + Name string + Type string + ID string + File io.Reader + FileSize int64 + Metadata map[string]string + BuildID int + CompileID int +} + +// MarshalJSON converts the UploadArtifactOpts into a JSON struct. +func (o *UploadArtifactOpts) MarshalJSON() ([]byte, error) { + return json.Marshal(map[string]interface{}{ + "artifact_version": map[string]interface{}{ + "id": o.ID, + "file": o.File != nil, + "metadata": o.Metadata, + "build_id": o.BuildID, + "compile_id": o.CompileID, + }, + }) +} + +// This is the value that should be used for metadata in ArtifactSearchOpts +// if you don't care what the value is. +const MetadataAnyValue = "943febbf-589f-401b-8f25-58f6d8786848" + +// Artifact finds the Atlas artifact by the given name and returns it. Any +// errors that occur are returned, including ErrAuth and ErrNotFound special +// exceptions which the user may want to handle separately. +func (c *Client) Artifact(user, name string) (*Artifact, error) { + endpoint := fmt.Sprintf("/api/v1/artifacts/%s/%s", user, name) + request, err := c.Request("GET", endpoint, nil) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var aw artifactWrapper + if err := decodeJSON(response, &aw); err != nil { + return nil, err + } + + return aw.Artifact, nil +} + +// ArtifactSearch searches Atlas for the given ArtifactSearchOpts and returns +// a slice of ArtifactVersions. +func (c *Client) ArtifactSearch(opts *ArtifactSearchOpts) ([]*ArtifactVersion, error) { + log.Printf("[INFO] searching artifacts: %#v", opts) + + params := make(map[string]string) + if opts.Version != "" { + params["version"] = opts.Version + } + if opts.Build != "" { + params["build"] = opts.Build + } + + i := 1 + for k, v := range opts.Metadata { + prefix := fmt.Sprintf("metadata.%d.", i) + params[prefix+"key"] = k + if v != MetadataAnyValue { + params[prefix+"value"] = v + } + + i++ + } + + endpoint := fmt.Sprintf("/api/v1/artifacts/%s/%s/%s/search", + opts.User, opts.Name, opts.Type) + request, err := c.Request("GET", endpoint, &RequestOptions{ + Params: params, + }) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var w artifactSearchWrapper + if err := decodeJSON(response, &w); err != nil { + return nil, err + } + + return w.Versions, nil +} + +// CreateArtifact creates and returns a new Artifact in Atlas. Any errors that +// occurr are returned. +func (c *Client) CreateArtifact(user, name string) (*Artifact, error) { + log.Printf("[INFO] creating artifact: %s/%s", user, name) + body, err := json.Marshal(&artifactWrapper{&Artifact{ + User: user, + Name: name, + }}) + if err != nil { + return nil, err + } + + endpoint := "/api/v1/artifacts" + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var aw artifactWrapper + if err := decodeJSON(response, &aw); err != nil { + return nil, err + } + + return aw.Artifact, nil +} + +// ArtifactFileURL is a helper method for getting the URL for an ArtifactVersion +// from the Client. +func (c *Client) ArtifactFileURL(av *ArtifactVersion) (*url.URL, error) { + if !av.File { + return nil, nil + } + + u := *c.URL + u.Path = fmt.Sprintf("/api/v1/artifacts/%s/%s/%s/file", + av.User, av.Name, av.Type) + return &u, nil +} + +// UploadArtifact streams the upload of a file on disk using the given +// UploadArtifactOpts. Any errors that occur are returned. +func (c *Client) UploadArtifact(opts *UploadArtifactOpts) (*ArtifactVersion, error) { + log.Printf("[INFO] uploading artifact: %s/%s (%s)", opts.User, opts.Name, opts.Type) + + endpoint := fmt.Sprintf("/api/v1/artifacts/%s/%s/%s", + opts.User, opts.Name, opts.Type) + + body, err := json.Marshal(opts) + if err != nil { + return nil, err + } + + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var av ArtifactVersion + if err := decodeJSON(response, &av); err != nil { + return nil, err + } + + if opts.File != nil { + if err := c.putFile(av.UploadPath, opts.File, opts.FileSize); err != nil { + return nil, err + } + } + + return &av, nil +} + +type artifactWrapper struct { + Artifact *Artifact `json:"artifact"` +} + +type artifactSearchWrapper struct { + Versions []*ArtifactVersion +} + +type artifactVersionWrapper struct { + Version *ArtifactVersion +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/authentication.go b/vendor/github.com/hashicorp/atlas-go/v1/authentication.go new file mode 100644 index 000000000..613eaefcc --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/authentication.go @@ -0,0 +1,88 @@ +package atlas + +import ( + "fmt" + "log" + "net/url" + "strings" +) + +// Login accepts a username and password as string arguments. Both username and +// password must be non-nil, non-empty values. Atlas does not permit +// passwordless authentication. +// +// If authentication is unsuccessful, an error is returned with the body of the +// error containing the server's response. +// +// If authentication is successful, this method sets the Token value on the +// Client and returns the Token as a string. +func (c *Client) Login(username, password string) (string, error) { + log.Printf("[INFO] logging in user %s", username) + + if len(username) == 0 { + return "", fmt.Errorf("client: missing username") + } + + if len(password) == 0 { + return "", fmt.Errorf("client: missing password") + } + + // Make a request + request, err := c.Request("POST", "/api/v1/authenticate", &RequestOptions{ + Body: strings.NewReader(url.Values{ + "user[login]": []string{username}, + "user[password]": []string{password}, + "user[description]": []string{"Created by the Atlas Go Client"}, + }.Encode()), + Headers: map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + }, + }) + if err != nil { + return "", err + } + + // Make the request + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return "", err + } + + // Decode the body + var tResponse struct{ Token string } + if err := decodeJSON(response, &tResponse); err != nil { + return "", nil + } + + // Set the token + log.Printf("[DEBUG] setting atlas token (%s)", maskString(tResponse.Token)) + c.Token = tResponse.Token + + // Return the token + return c.Token, nil +} + +// Verify verifies that authentication and communication with Atlas +// is properly functioning. +func (c *Client) Verify() error { + log.Printf("[INFO] verifying authentication") + + request, err := c.Request("GET", "/api/v1/authenticate", nil) + if err != nil { + return err + } + + _, err = checkResp(c.HTTPClient.Do(request)) + return err +} + +// maskString masks all but the first few characters of a string for display +// output. This is useful for tokens so we can display them to the user without +// showing the full output. +func maskString(s string) string { + if len(s) <= 3 { + return "*** (masked)" + } + + return s[0:3] + "*** (masked)" +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/build_config.go b/vendor/github.com/hashicorp/atlas-go/v1/build_config.go new file mode 100644 index 000000000..53b6c1125 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/build_config.go @@ -0,0 +1,183 @@ +package atlas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" +) + +// bcWrapper is the API wrapper since the server wraps the resulting object. +type bcWrapper struct { + BuildConfig *BuildConfig `json:"build_configuration"` +} + +// BuildConfig represents a Packer build configuration. +type BuildConfig struct { + // User is the namespace under which the build config lives + User string `json:"username"` + + // Name is the actual name of the build config, unique in the scope + // of the username. + Name string `json:"name"` +} + +// Slug returns the slug format for this BuildConfig (User/Name) +func (b *BuildConfig) Slug() string { + return fmt.Sprintf("%s/%s", b.User, b.Name) +} + +// BuildConfigVersion represents a single uploaded (or uploadable) version +// of a build configuration. +type BuildConfigVersion struct { + // The fields below are the username/name combo to uniquely identify + // a build config. + User string `json:"username"` + Name string `json:"name"` + + // Builds is the list of builds that this version supports. + Builds []BuildConfigBuild +} + +// Slug returns the slug format for this BuildConfigVersion (User/Name) +func (bv *BuildConfigVersion) Slug() string { + return fmt.Sprintf("%s/%s", bv.User, bv.Name) +} + +// BuildConfigBuild is a single build that is present in an uploaded +// build configuration. +type BuildConfigBuild struct { + // Name is a unique name for this build + Name string `json:"name"` + + // Type is the type of builder that this build needs to run on, + // such as "amazon-ebs" or "qemu". + Type string `json:"type"` + + // Artifact is true if this build results in one or more artifacts + // being sent to Atlas + Artifact bool `json:"artifact"` +} + +// BuildConfig gets a single build configuration by user and name. +func (c *Client) BuildConfig(user, name string) (*BuildConfig, error) { + log.Printf("[INFO] getting build configuration %s/%s", user, name) + + endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s", user, name) + request, err := c.Request("GET", endpoint, nil) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var bc BuildConfig + if err := decodeJSON(response, &bc); err != nil { + return nil, err + } + + return &bc, nil +} + +// CreateBuildConfig creates a new build configuration. +func (c *Client) CreateBuildConfig(user, name string) (*BuildConfig, error) { + log.Printf("[INFO] creating build configuration %s/%s", user, name) + + endpoint := "/api/v1/packer/build-configurations" + body, err := json.Marshal(&bcWrapper{ + BuildConfig: &BuildConfig{ + User: user, + Name: name, + }, + }) + if err != nil { + return nil, err + } + + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return nil, err + } + + var bc BuildConfig + if err := decodeJSON(response, &bc); err != nil { + return nil, err + } + + return &bc, nil +} + +// UploadBuildConfigVersion creates a single build configuration version +// and uploads the template associated with it. +// +// Actual API: "Create Build Config Version" +func (c *Client) UploadBuildConfigVersion(v *BuildConfigVersion, metadata map[string]interface{}, + data io.Reader, size int64) error { + + log.Printf("[INFO] uploading build configuration version %s (%d bytes), with metadata %q", + v.Slug(), size, metadata) + + endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s/versions", + v.User, v.Name) + + var bodyData bcCreateWrapper + bodyData.Version.Builds = v.Builds + bodyData.Version.Metadata = metadata + body, err := json.Marshal(bodyData) + if err != nil { + return err + } + + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return err + } + + var bv bcCreate + if err := decodeJSON(response, &bv); err != nil { + return err + } + + if err := c.putFile(bv.UploadPath, data, size); err != nil { + return err + } + + return nil +} + +// bcCreate is the struct returned when creating a build configuration. +type bcCreate struct { + UploadPath string `json:"upload_path"` +} + +// bcCreateWrapper is the wrapper for creating a build config. +type bcCreateWrapper struct { + Version struct { + Metadata map[string]interface{} `json:"metadata,omitempty"` + Builds []BuildConfigBuild `json:"builds"` + } `json:"version"` +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/client.go b/vendor/github.com/hashicorp/atlas-go/v1/client.go new file mode 100644 index 000000000..abae4fe56 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/client.go @@ -0,0 +1,301 @@ +package atlas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "net/url" + "os" + "path" + "runtime" + "strings" + + "github.com/hashicorp/go-cleanhttp" +) + +const ( + // atlasDefaultEndpoint is the default base URL for connecting to Atlas. + atlasDefaultEndpoint = "https://atlas.hashicorp.com" + + // atlasEndpointEnvVar is the environment variable that overrrides the + // default Atlas address. + atlasEndpointEnvVar = "ATLAS_ADDRESS" + + // atlasTokenHeader is the header key used for authenticating with Atlas + atlasTokenHeader = "X-Atlas-Token" +) + +var projectURL = "https://github.com/hashicorp/atlas-go" +var userAgent = fmt.Sprintf("AtlasGo/1.0 (+%s; %s)", + projectURL, runtime.Version()) + +// ErrAuth is the error returned if a 401 is returned by an API request. +var ErrAuth = fmt.Errorf("authentication failed") + +// ErrNotFound is the error returned if a 404 is returned by an API request. +var ErrNotFound = fmt.Errorf("resource not found") + +// RailsError represents an error that was returned from the Rails server. +type RailsError struct { + Errors []string `json:"errors"` +} + +// Error collects all of the errors in the RailsError and returns a comma- +// separated list of the errors that were returned from the server. +func (re *RailsError) Error() string { + return strings.Join(re.Errors, ", ") +} + +// Client represents a single connection to a Atlas API endpoint. +type Client struct { + // URL is the full endpoint address to the Atlas server including the + // protocol, port, and path. + URL *url.URL + + // Token is the Atlas authentication token + Token string + + // HTTPClient is the underlying http client with which to make requests. + HTTPClient *http.Client +} + +// DefaultClient returns a client that connects to the Atlas API. +func DefaultClient() *Client { + atlasEndpoint := os.Getenv(atlasEndpointEnvVar) + if atlasEndpoint == "" { + atlasEndpoint = atlasDefaultEndpoint + } + + client, err := NewClient(atlasEndpoint) + if err != nil { + panic(err) + } + + return client +} + +// NewClient creates a new Atlas Client from the given URL (as a string). If +// the URL cannot be parsed, an error is returned. The HTTPClient is set to +// an empty http.Client, but this can be changed programmatically by setting +// client.HTTPClient. The user can also programmatically set the URL as a +// *url.URL. +func NewClient(urlString string) (*Client, error) { + if len(urlString) == 0 { + return nil, fmt.Errorf("client: missing url") + } + + parsedURL, err := url.Parse(urlString) + if err != nil { + return nil, err + } + + token := os.Getenv("ATLAS_TOKEN") + if token != "" { + log.Printf("[DEBUG] using ATLAS_TOKEN (%s)", maskString(token)) + } + + client := &Client{ + URL: parsedURL, + Token: token, + } + + if err := client.init(); err != nil { + return nil, err + } + + return client, nil +} + +// init() sets defaults on the client. +func (c *Client) init() error { + c.HTTPClient = cleanhttp.DefaultClient() + return nil +} + +// RequestOptions is the list of options to pass to the request. +type RequestOptions struct { + // Params is a map of key-value pairs that will be added to the Request. + Params map[string]string + + // Headers is a map of key-value pairs that will be added to the Request. + Headers map[string]string + + // Body is an io.Reader object that will be streamed or uploaded with the + // Request. BodyLength is the final size of the Body. + Body io.Reader + BodyLength int64 +} + +// Request creates a new HTTP request using the given verb and sub path. +func (c *Client) Request(verb, spath string, ro *RequestOptions) (*http.Request, error) { + log.Printf("[INFO] request: %s %s", verb, spath) + + // Ensure we have a RequestOptions struct (passing nil is an acceptable) + if ro == nil { + ro = new(RequestOptions) + } + + // Create a new URL with the appended path + u := *c.URL + u.Path = path.Join(c.URL.Path, spath) + + // Add the token and other params + if c.Token != "" { + log.Printf("[DEBUG] request: appending token (%s)", maskString(c.Token)) + if ro.Headers == nil { + ro.Headers = make(map[string]string) + } + + ro.Headers[atlasTokenHeader] = c.Token + } + + return c.rawRequest(verb, &u, ro) +} + +func (c *Client) putFile(rawURL string, r io.Reader, size int64) error { + log.Printf("[INFO] putting file: %s", rawURL) + + url, err := url.Parse(rawURL) + if err != nil { + return err + } + + request, err := c.rawRequest("PUT", url, &RequestOptions{ + Body: r, + BodyLength: size, + }) + if err != nil { + return err + } + + if _, err := checkResp(c.HTTPClient.Do(request)); err != nil { + return err + } + + return nil +} + +// rawRequest accepts a verb, URL, and RequestOptions struct and returns the +// constructed http.Request and any errors that occurred +func (c *Client) rawRequest(verb string, u *url.URL, ro *RequestOptions) (*http.Request, error) { + if verb == "" { + return nil, fmt.Errorf("client: missing verb") + } + + if u == nil { + return nil, fmt.Errorf("client: missing URL.url") + } + + if ro == nil { + return nil, fmt.Errorf("client: missing RequestOptions") + } + + // Add the token and other params + var params = make(url.Values) + for k, v := range ro.Params { + params.Add(k, v) + } + u.RawQuery = params.Encode() + + // Create the request object + request, err := http.NewRequest(verb, u.String(), ro.Body) + if err != nil { + return nil, err + } + + // Set the User-Agent + request.Header.Set("User-Agent", userAgent) + + // Add any headers (auth will be here if set) + for k, v := range ro.Headers { + request.Header.Add(k, v) + } + + // Add content-length if we have it + if ro.BodyLength > 0 { + request.ContentLength = ro.BodyLength + } + + log.Printf("[DEBUG] raw request: %#v", request) + + return request, nil +} + +// checkResp wraps http.Client.Do() and verifies that the request was +// successful. A non-200 request returns an error formatted to included any +// validation problems or otherwise. +func checkResp(resp *http.Response, err error) (*http.Response, error) { + // If the err is already there, there was an error higher up the chain, so + // just return that + if err != nil { + return resp, err + } + + log.Printf("[INFO] response: %d (%s)", resp.StatusCode, resp.Status) + var buf bytes.Buffer + if _, err := io.Copy(&buf, resp.Body); err != nil { + log.Printf("[ERR] response: error copying response body") + } else { + log.Printf("[DEBUG] response: %s", buf.String()) + + // We are going to reset the response body, so we need to close the old + // one or else it will leak. + resp.Body.Close() + resp.Body = &bytesReadCloser{&buf} + } + + switch resp.StatusCode { + case 200: + return resp, nil + case 201: + return resp, nil + case 202: + return resp, nil + case 204: + return resp, nil + case 400: + return nil, parseErr(resp) + case 401: + return nil, ErrAuth + case 404: + return nil, ErrNotFound + case 422: + return nil, parseErr(resp) + default: + return nil, fmt.Errorf("client: %s", resp.Status) + } +} + +// parseErr is used to take an error JSON response and return a single string +// for use in error messages. +func parseErr(r *http.Response) error { + re := &RailsError{} + + if err := decodeJSON(r, &re); err != nil { + return fmt.Errorf("error decoding JSON body: %s", err) + } + + return re +} + +// decodeJSON is used to JSON decode a body into an interface. +func decodeJSON(resp *http.Response, out interface{}) error { + defer resp.Body.Close() + dec := json.NewDecoder(resp.Body) + return dec.Decode(out) +} + +// bytesReadCloser is a simple wrapper around a bytes buffer that implements +// Close as a noop. +type bytesReadCloser struct { + *bytes.Buffer +} + +func (nrc *bytesReadCloser) Close() error { + // we don't actually have to do anything here, since the buffer is just some + // data in memory and the error is initialized to no-error + return nil +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/terraform.go b/vendor/github.com/hashicorp/atlas-go/v1/terraform.go new file mode 100644 index 000000000..adeba2a11 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/terraform.go @@ -0,0 +1,97 @@ +package atlas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" +) + +// TerraformConfigVersion represents a single uploaded version of a +// Terraform configuration. +type TerraformConfigVersion struct { + Version int + Remotes []string `json:"remotes"` + Metadata map[string]string `json:"metadata"` + Variables map[string]string `json:"variables"` +} + +// TerraformConfigLatest returns the latest Terraform configuration version. +func (c *Client) TerraformConfigLatest(user, name string) (*TerraformConfigVersion, error) { + log.Printf("[INFO] getting terraform configuration %s/%s", user, name) + + endpoint := fmt.Sprintf("/api/v1/terraform/configurations/%s/%s/versions/latest", user, name) + request, err := c.Request("GET", endpoint, nil) + if err != nil { + return nil, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err == ErrNotFound { + return nil, nil + } + if err != nil { + return nil, err + } + + var wrapper tfConfigVersionWrapper + if err := decodeJSON(response, &wrapper); err != nil { + return nil, err + } + + return wrapper.Version, nil +} + +// CreateTerraformConfigVersion creatse a new Terraform configuration +// versions and uploads a slug with it. +func (c *Client) CreateTerraformConfigVersion( + user string, name string, + version *TerraformConfigVersion, + data io.Reader, size int64) (int, error) { + log.Printf("[INFO] creating terraform configuration %s/%s", user, name) + + endpoint := fmt.Sprintf( + "/api/v1/terraform/configurations/%s/%s/versions", user, name) + body, err := json.Marshal(&tfConfigVersionWrapper{ + Version: version, + }) + if err != nil { + return 0, err + } + + request, err := c.Request("POST", endpoint, &RequestOptions{ + Body: bytes.NewReader(body), + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return 0, err + } + + response, err := checkResp(c.HTTPClient.Do(request)) + if err != nil { + return 0, err + } + + var result tfConfigVersionCreate + if err := decodeJSON(response, &result); err != nil { + return 0, err + } + + if err := c.putFile(result.UploadPath, data, size); err != nil { + return 0, err + } + + return result.Version, nil +} + +type tfConfigVersionCreate struct { + UploadPath string `json:"upload_path"` + Version int +} + +type tfConfigVersionWrapper struct { + Version *TerraformConfigVersion `json:"version"` +} diff --git a/vendor/github.com/hashicorp/atlas-go/v1/util.go b/vendor/github.com/hashicorp/atlas-go/v1/util.go new file mode 100644 index 000000000..9aa0d2886 --- /dev/null +++ b/vendor/github.com/hashicorp/atlas-go/v1/util.go @@ -0,0 +1,22 @@ +package atlas + +import ( + "fmt" + "strings" +) + +// ParseSlug parses a slug of the format (x/y) into the x and y components. It +// accepts a string of the format "x/y" ("user/name" for example). If an empty +// string is given, an error is returned. If the given string is not a valid +// slug format, an error is returned. +func ParseSlug(slug string) (string, string, error) { + if slug == "" { + return "", "", fmt.Errorf("missing slug") + } + + parts := strings.Split(slug, "/") + if len(parts) != 2 { + return "", "", fmt.Errorf("malformed slug %q", slug) + } + return parts[0], parts[1], nil +} diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md new file mode 100644 index 000000000..1c95f5978 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -0,0 +1,89 @@ +# errwrap + +`errwrap` is a package for Go that formalizes the pattern of wrapping errors +and checking if an error contains another error. + +There is a common pattern in Go of taking a returned `error` value and +then wrapping it (such as with `fmt.Errorf`) before returning it. The problem +with this pattern is that you completely lose the original `error` structure. + +Arguably the _correct_ approach is that you should make a custom structure +implementing the `error` interface, and have the original error as a field +on that structure, such [as this example](http://golang.org/pkg/os/#PathError). +This is a good approach, but you have to know the entire chain of possible +rewrapping that happens, when you might just care about one. + +`errwrap` formalizes this pattern (it doesn't matter what approach you use +above) by giving a single interface for wrapping errors, checking if a specific +error is wrapped, and extracting that error. + +## Installation and Docs + +Install using `go get github.com/hashicorp/errwrap`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/errwrap + +## Usage + +#### Basic Usage + +Below is a very basic example of its usage: + +```go +// A function that always returns an error, but wraps it, like a real +// function might. +func tryOpen() error { + _, err := os.Open("/i/dont/exist") + if err != nil { + return errwrap.Wrapf("Doesn't exist: {{err}}", err) + } + + return nil +} + +func main() { + err := tryOpen() + + // We can use the Contains helpers to check if an error contains + // another error. It is safe to do this with a nil error, or with + // an error that doesn't even use the errwrap package. + if errwrap.Contains(err, ErrNotExist) { + // Do something + } + if errwrap.ContainsType(err, new(os.PathError)) { + // Do something + } + + // Or we can use the associated `Get` functions to just extract + // a specific error. This would return nil if that specific error doesn't + // exist. + perr := errwrap.GetType(err, new(os.PathError)) +} +``` + +#### Custom Types + +If you're already making custom types that properly wrap errors, then +you can get all the functionality of `errwraps.Contains` and such by +implementing the `Wrapper` interface with just one function. Example: + +```go +type AppError { + Code ErrorCode + Err error +} + +func (e *AppError) WrappedErrors() []error { + return []error{e.Err} +} +``` + +Now this works: + +```go +err := &AppError{Err: fmt.Errorf("an error")} +if errwrap.ContainsType(err, fmt.Errorf("")) { + // This will work! +} +``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go new file mode 100644 index 000000000..a733bef18 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/errwrap.go @@ -0,0 +1,169 @@ +// Package errwrap implements methods to formalize error wrapping in Go. +// +// All of the top-level functions that take an `error` are built to be able +// to take any error, not just wrapped errors. This allows you to use errwrap +// without having to type-check and type-cast everywhere. +package errwrap + +import ( + "errors" + "reflect" + "strings" +) + +// WalkFunc is the callback called for Walk. +type WalkFunc func(error) + +// Wrapper is an interface that can be implemented by custom types to +// have all the Contains, Get, etc. functions in errwrap work. +// +// When Walk reaches a Wrapper, it will call the callback for every +// wrapped error in addition to the wrapper itself. Since all the top-level +// functions in errwrap use Walk, this means that all those functions work +// with your custom type. +type Wrapper interface { + WrappedErrors() []error +} + +// Wrap defines that outer wraps inner, returning an error type that +// can be cleanly used with the other methods in this package, such as +// Contains, GetAll, etc. +// +// This function won't modify the error message at all (the outer message +// will be used). +func Wrap(outer, inner error) error { + return &wrappedError{ + Outer: outer, + Inner: inner, + } +} + +// Wrapf wraps an error with a formatting message. This is similar to using +// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap +// errors, you should replace it with this. +// +// format is the format of the error message. The string '{{err}}' will +// be replaced with the original error message. +func Wrapf(format string, err error) error { + outerMsg := "" + if err != nil { + outerMsg = err.Error() + } + + outer := errors.New(strings.Replace( + format, "{{err}}", outerMsg, -1)) + + return Wrap(outer, err) +} + +// Contains checks if the given error contains an error with the +// message msg. If err is not a wrapped error, this will always return +// false unless the error itself happens to match this msg. +func Contains(err error, msg string) bool { + return len(GetAll(err, msg)) > 0 +} + +// ContainsType checks if the given error contains an error with +// the same concrete type as v. If err is not a wrapped error, this will +// check the err itself. +func ContainsType(err error, v interface{}) bool { + return len(GetAllType(err, v)) > 0 +} + +// Get is the same as GetAll but returns the deepest matching error. +func Get(err error, msg string) error { + es := GetAll(err, msg) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetType is the same as GetAllType but returns the deepest matching error. +func GetType(err error, v interface{}) error { + es := GetAllType(err, v) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetAll gets all the errors that might be wrapped in err with the +// given message. The order of the errors is such that the outermost +// matching error (the most recent wrap) is index zero, and so on. +func GetAll(err error, msg string) []error { + var result []error + + Walk(err, func(err error) { + if err.Error() == msg { + result = append(result, err) + } + }) + + return result +} + +// GetAllType gets all the errors that are the same type as v. +// +// The order of the return value is the same as described in GetAll. +func GetAllType(err error, v interface{}) []error { + var result []error + + var search string + if v != nil { + search = reflect.TypeOf(v).String() + } + Walk(err, func(err error) { + var needle string + if err != nil { + needle = reflect.TypeOf(err).String() + } + + if needle == search { + result = append(result, err) + } + }) + + return result +} + +// Walk walks all the wrapped errors in err and calls the callback. If +// err isn't a wrapped error, this will be called once for err. If err +// is a wrapped error, the callback will be called for both the wrapper +// that implements error as well as the wrapped error itself. +func Walk(err error, cb WalkFunc) { + if err == nil { + return + } + + switch e := err.(type) { + case *wrappedError: + cb(e.Outer) + Walk(e.Inner, cb) + case Wrapper: + cb(err) + + for _, err := range e.WrappedErrors() { + Walk(err, cb) + } + default: + cb(err) + } +} + +// wrappedError is an implementation of error that has both the +// outer and inner errors. +type wrappedError struct { + Outer error + Inner error +} + +func (w *wrappedError) Error() string { + return w.Outer.Error() +} + +func (w *wrappedError) WrappedErrors() []error { + return []error{w.Outer, w.Inner} +} diff --git a/vendor/github.com/hashicorp/go-checkpoint/LICENSE b/vendor/github.com/hashicorp/go-checkpoint/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-checkpoint/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/go-checkpoint/README.md b/vendor/github.com/hashicorp/go-checkpoint/README.md new file mode 100644 index 000000000..ab8ebc0d3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-checkpoint/README.md @@ -0,0 +1,22 @@ +# Go Checkpoint Client + +[Checkpoint](http://checkpoint.hashicorp.com) is an internal service at +Hashicorp that we use to check version information, broadcoast security +bulletins, etc. + +We understand that software making remote calls over the internet +for any reason can be undesirable. Because of this, Checkpoint can be +disabled in all of our software that includes it. You can view the source +of this client to see that we're not sending any private information. + +Each Hashicorp application has it's specific configuration option +to disable chekpoint calls, but the `CHECKPOINT_DISABLE` makes +the underlying checkpoint component itself disabled. For example +in the case of packer: +``` +CHECKPOINT_DISABLE=1 packer build +``` + +**Note:** This repository is probably useless outside of internal HashiCorp +use. It is open source for disclosure and because our open source projects +must be able to link to it. diff --git a/vendor/github.com/hashicorp/go-checkpoint/checkpoint.go b/vendor/github.com/hashicorp/go-checkpoint/checkpoint.go new file mode 100644 index 000000000..abea934bf --- /dev/null +++ b/vendor/github.com/hashicorp/go-checkpoint/checkpoint.go @@ -0,0 +1,359 @@ +// checkpoint is a package for checking version information and alerts +// for a HashiCorp product. +package checkpoint + +import ( + "crypto/rand" + "encoding/binary" + "encoding/json" + "fmt" + "io" + "io/ioutil" + mrand "math/rand" + "net/http" + "net/url" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "time" + + "github.com/hashicorp/go-cleanhttp" +) + +var magicBytes [4]byte = [4]byte{0x35, 0x77, 0x69, 0xFB} + +// CheckParams are the parameters for configuring a check request. +type CheckParams struct { + // Product and version are used to lookup the correct product and + // alerts for the proper version. The version is also used to perform + // a version check. + Product string + Version string + + // Arch and OS are used to filter alerts potentially only to things + // affecting a specific os/arch combination. If these aren't specified, + // they'll be automatically filled in. + Arch string + OS string + + // Signature is some random signature that should be stored and used + // as a cookie-like value. This ensures that alerts aren't repeated. + // If the signature is changed, repeat alerts may be sent down. The + // signature should NOT be anything identifiable to a user (such as + // a MAC address). It should be random. + // + // If SignatureFile is given, then the signature will be read from this + // file. If the file doesn't exist, then a random signature will + // automatically be generated and stored here. SignatureFile will be + // ignored if Signature is given. + Signature string + SignatureFile string + + // CacheFile, if specified, will cache the result of a check. The + // duration of the cache is specified by CacheDuration, and defaults + // to 48 hours if not specified. If the CacheFile is newer than the + // CacheDuration, than the Check will short-circuit and use those + // results. + // + // If the CacheFile directory doesn't exist, it will be created with + // permissions 0755. + CacheFile string + CacheDuration time.Duration + + // Force, if true, will force the check even if CHECKPOINT_DISABLE + // is set. Within HashiCorp products, this is ONLY USED when the user + // specifically requests it. This is never automatically done without + // the user's consent. + Force bool +} + +// CheckResponse is the response for a check request. +type CheckResponse struct { + Product string + CurrentVersion string `json:"current_version"` + CurrentReleaseDate int `json:"current_release_date"` + CurrentDownloadURL string `json:"current_download_url"` + CurrentChangelogURL string `json:"current_changelog_url"` + ProjectWebsite string `json:"project_website"` + Outdated bool `json:"outdated"` + Alerts []*CheckAlert +} + +// CheckAlert is a single alert message from a check request. +// +// These never have to be manually constructed, and are typically populated +// into a CheckResponse as a result of the Check request. +type CheckAlert struct { + ID int + Date int + Message string + URL string + Level string +} + +// Check checks for alerts and new version information. +func Check(p *CheckParams) (*CheckResponse, error) { + if disabled := os.Getenv("CHECKPOINT_DISABLE"); disabled != "" && !p.Force { + return &CheckResponse{}, nil + } + + // If we have a cached result, then use that + if r, err := checkCache(p.Version, p.CacheFile, p.CacheDuration); err != nil { + return nil, err + } else if r != nil { + defer r.Close() + return checkResult(r) + } + + var u url.URL + + if p.Arch == "" { + p.Arch = runtime.GOARCH + } + if p.OS == "" { + p.OS = runtime.GOOS + } + + // If we're given a SignatureFile, then attempt to read that. + signature := p.Signature + if p.Signature == "" && p.SignatureFile != "" { + var err error + signature, err = checkSignature(p.SignatureFile) + if err != nil { + return nil, err + } + } + + v := u.Query() + v.Set("version", p.Version) + v.Set("arch", p.Arch) + v.Set("os", p.OS) + v.Set("signature", signature) + + u.Scheme = "https" + u.Host = "checkpoint-api.hashicorp.com" + u.Path = fmt.Sprintf("/v1/check/%s", p.Product) + u.RawQuery = v.Encode() + + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, err + } + req.Header.Add("Accept", "application/json") + req.Header.Add("User-Agent", "HashiCorp/go-checkpoint") + + client := cleanhttp.DefaultClient() + resp, err := client.Do(req) + if err != nil { + return nil, err + } + if resp.StatusCode != 200 { + return nil, fmt.Errorf("Unknown status: %d", resp.StatusCode) + } + + var r io.Reader = resp.Body + if p.CacheFile != "" { + // Make sure the directory holding our cache exists. + if err := os.MkdirAll(filepath.Dir(p.CacheFile), 0755); err != nil { + return nil, err + } + + // We have to cache the result, so write the response to the + // file as we read it. + f, err := os.Create(p.CacheFile) + if err != nil { + return nil, err + } + + // Write the cache header + if err := writeCacheHeader(f, p.Version); err != nil { + f.Close() + os.Remove(p.CacheFile) + return nil, err + } + + defer f.Close() + r = io.TeeReader(r, f) + } + + return checkResult(r) +} + +// CheckInterval is used to check for a response on a given interval duration. +// The interval is not exact, and checks are randomized to prevent a thundering +// herd. However, it is expected that on average one check is performed per +// interval. The returned channel may be closed to stop background checks. +func CheckInterval(p *CheckParams, interval time.Duration, cb func(*CheckResponse, error)) chan struct{} { + doneCh := make(chan struct{}) + + if disabled := os.Getenv("CHECKPOINT_DISABLE"); disabled != "" { + return doneCh + } + + go func() { + for { + select { + case <-time.After(randomStagger(interval)): + resp, err := Check(p) + cb(resp, err) + case <-doneCh: + return + } + } + }() + + return doneCh +} + +// randomStagger returns an interval that is between 3/4 and 5/4 of +// the given interval. The expected value is the interval. +func randomStagger(interval time.Duration) time.Duration { + stagger := time.Duration(mrand.Int63()) % (interval / 2) + return 3*(interval/4) + stagger +} + +func checkCache(current string, path string, d time.Duration) (io.ReadCloser, error) { + fi, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + // File doesn't exist, not a problem + return nil, nil + } + + return nil, err + } + + if d == 0 { + d = 48 * time.Hour + } + + if fi.ModTime().Add(d).Before(time.Now()) { + // Cache is busted, delete the old file and re-request. We ignore + // errors here because re-creating the file is fine too. + os.Remove(path) + return nil, nil + } + + // File looks good so far, open it up so we can inspect the contents. + f, err := os.Open(path) + if err != nil { + return nil, err + } + + // Check the signature of the file + var sig [4]byte + if err := binary.Read(f, binary.LittleEndian, sig[:]); err != nil { + f.Close() + return nil, err + } + if !reflect.DeepEqual(sig, magicBytes) { + // Signatures don't match. Reset. + f.Close() + return nil, nil + } + + // Check the version. If it changed, then rewrite + var length uint32 + if err := binary.Read(f, binary.LittleEndian, &length); err != nil { + f.Close() + return nil, err + } + data := make([]byte, length) + if _, err := io.ReadFull(f, data); err != nil { + f.Close() + return nil, err + } + if string(data) != current { + // Version changed, reset + f.Close() + return nil, nil + } + + return f, nil +} + +func checkResult(r io.Reader) (*CheckResponse, error) { + var result CheckResponse + dec := json.NewDecoder(r) + if err := dec.Decode(&result); err != nil { + return nil, err + } + + return &result, nil +} + +func checkSignature(path string) (string, error) { + _, err := os.Stat(path) + if err == nil { + // The file exists, read it out + sigBytes, err := ioutil.ReadFile(path) + if err != nil { + return "", err + } + + // Split the file into lines + lines := strings.SplitN(string(sigBytes), "\n", 2) + if len(lines) > 0 { + return strings.TrimSpace(lines[0]), nil + } + } + + // If this isn't a non-exist error, then return that. + if !os.IsNotExist(err) { + return "", err + } + + // The file doesn't exist, so create a signature. + var b [16]byte + n := 0 + for n < 16 { + n2, err := rand.Read(b[n:]) + if err != nil { + return "", err + } + + n += n2 + } + signature := fmt.Sprintf( + "%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + + // Make sure the directory holding our signature exists. + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return "", err + } + + // Write the signature + if err := ioutil.WriteFile(path, []byte(signature+"\n\n"+userMessage+"\n"), 0644); err != nil { + return "", err + } + + return signature, nil +} + +func writeCacheHeader(f io.Writer, v string) error { + // Write our signature first + if err := binary.Write(f, binary.LittleEndian, magicBytes); err != nil { + return err + } + + // Write out our current version length + var length uint32 = uint32(len(v)) + if err := binary.Write(f, binary.LittleEndian, length); err != nil { + return err + } + + _, err := f.Write([]byte(v)) + return err +} + +// userMessage is suffixed to the signature file to provide feedback. +var userMessage = ` +This signature is a randomly generated UUID used to de-duplicate +alerts and version information. This signature is random, it is +not based on any personally identifiable information. To create +a new signature, you can simply delete this file at any time. +See the documentation for the software using Checkpoint for more +information on how to disable it. +` diff --git a/vendor/github.com/hashicorp/go-cleanhttp/LICENSE b/vendor/github.com/hashicorp/go-cleanhttp/LICENSE new file mode 100644 index 000000000..e87a115e4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-cleanhttp/LICENSE @@ -0,0 +1,363 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/go-cleanhttp/README.md b/vendor/github.com/hashicorp/go-cleanhttp/README.md new file mode 100644 index 000000000..036e5313f --- /dev/null +++ b/vendor/github.com/hashicorp/go-cleanhttp/README.md @@ -0,0 +1,30 @@ +# cleanhttp + +Functions for accessing "clean" Go http.Client values + +------------- + +The Go standard library contains a default `http.Client` called +`http.DefaultClient`. It is a common idiom in Go code to start with +`http.DefaultClient` and tweak it as necessary, and in fact, this is +encouraged; from the `http` package documentation: + +> The Client's Transport typically has internal state (cached TCP connections), +so Clients should be reused instead of created as needed. Clients are safe for +concurrent use by multiple goroutines. + +Unfortunately, this is a shared value, and it is not uncommon for libraries to +assume that they are free to modify it at will. With enough dependencies, it +can be very easy to encounter strange problems and race conditions due to +manipulation of this shared value across libraries and goroutines (clients are +safe for concurrent use, but writing values to the client struct itself is not +protected). + +Making things worse is the fact that a bare `http.Client` will use a default +`http.Transport` called `http.DefaultTransport`, which is another global value +that behaves the same way. So it is not simply enough to replace +`http.DefaultClient` with `&http.Client{}`. + +This repository provides some simple functions to get a "clean" `http.Client` +-- one that uses the same default values as the Go standard library, but +returns a client that does not share any state with other clients. diff --git a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go new file mode 100644 index 000000000..c692e23f4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go @@ -0,0 +1,40 @@ +package cleanhttp + +import ( + "net" + "net/http" + "runtime" + "time" +) + +// DefaultTransport returns a new http.Transport with the same default values +// as http.DefaultTransport +func DefaultTransport() *http.Transport { + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + } + SetTransportFinalizer(transport) + return transport +} + +// DefaultClient returns a new http.Client with the same default values as +// http.Client, but with a non-shared Transport +func DefaultClient() *http.Client { + return &http.Client{ + Transport: DefaultTransport(), + } +} + +// SetTransportFinalizer sets a finalizer on the transport to ensure that +// idle connections are closed prior to garbage collection; otherwise +// these may leak +func SetTransportFinalizer(transport *http.Transport) { + runtime.SetFinalizer(&transport, func(t **http.Transport) { + (*t).CloseIdleConnections() + }) +} diff --git a/vendor/github.com/hashicorp/go-multierror/LICENSE b/vendor/github.com/hashicorp/go-multierror/LICENSE new file mode 100644 index 000000000..82b4de97c --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md new file mode 100644 index 000000000..e81be50e0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/README.md @@ -0,0 +1,91 @@ +# go-multierror + +`go-multierror` is a package for Go that provides a mechanism for +representing a list of `error` values as a single `error`. + +This allows a function in Go to return an `error` that might actually +be a list of errors. If the caller knows this, they can unwrap the +list and access the errors. If the caller doesn't know, the error +formats to a nice human-readable format. + +`go-multierror` implements the +[errwrap](https://github.com/hashicorp/errwrap) interface so that it can +be used with that library, as well. + +## Installation and Docs + +Install using `go get github.com/hashicorp/go-multierror`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/go-multierror + +## Usage + +go-multierror is easy to use and purposely built to be unobtrusive in +existing Go applications/libraries that may not be aware of it. + +**Building a list of errors** + +The `Append` function is used to create a list of errors. This function +behaves a lot like the Go built-in `append` function: it doesn't matter +if the first argument is nil, a `multierror.Error`, or any other `error`, +the function behaves as you would expect. + +```go +var result error + +if err := step1(); err != nil { + result = multierror.Append(result, err) +} +if err := step2(); err != nil { + result = multierror.Append(result, err) +} + +return result +``` + +**Customizing the formatting of the errors** + +By specifying a custom `ErrorFormat`, you can customize the format +of the `Error() string` function: + +```go +var result *multierror.Error + +// ... accumulate errors here, maybe using Append + +if result != nil { + result.ErrorFormat = func([]error) string { + return "errors!" + } +} +``` + +**Accessing the list of errors** + +`multierror.Error` implements `error` so if the caller doesn't know about +multierror, it will work just fine. But if you're aware a multierror might +be returned, you can use type switches to access the list of errors: + +```go +if err := something(); err != nil { + if merr, ok := err.(*multierror.Error); ok { + // Use merr.Errors + } +} +``` + +**Returning a multierror only if there are errors** + +If you build a `multierror.Error`, you can use the `ErrorOrNil` function +to return an `error` implementation only if there are errors to return: + +```go +var result *multierror.Error + +// ... accumulate errors here + +// Return the `error` only if errors were added to the multierror, otherwise +// return nil since there are no errors. +return result.ErrorOrNil() +``` diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go new file mode 100644 index 000000000..00afa9b35 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/append.go @@ -0,0 +1,37 @@ +package multierror + +// Append is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +func Append(err error, errs ...error) *Error { + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Go through each error and flatten + for _, e := range errs { + switch e := e.(type) { + case *Error: + err.Errors = append(err.Errors, e.Errors...) + default: + err.Errors = append(err.Errors, e) + } + } + + return err + default: + newErrs := make([]error, 0, len(errs)+1) + if err != nil { + newErrs = append(newErrs, err) + } + newErrs = append(newErrs, errs...) + + return Append(&Error{}, newErrs...) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten.go b/vendor/github.com/hashicorp/go-multierror/flatten.go new file mode 100644 index 000000000..aab8e9abe --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/flatten.go @@ -0,0 +1,26 @@ +package multierror + +// Flatten flattens the given error, merging any *Errors together into +// a single *Error. +func Flatten(err error) error { + // If it isn't an *Error, just return the error as-is + if _, ok := err.(*Error); !ok { + return err + } + + // Otherwise, make the result and flatten away! + flatErr := new(Error) + flatten(err, flatErr) + return flatErr +} + +func flatten(err error, flatErr *Error) { + switch err := err.(type) { + case *Error: + for _, e := range err.Errors { + flatten(e, flatErr) + } + default: + flatErr.Errors = append(flatErr.Errors, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go new file mode 100644 index 000000000..bb65a12e7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/format.go @@ -0,0 +1,23 @@ +package multierror + +import ( + "fmt" + "strings" +) + +// ErrorFormatFunc is a function callback that is called by Error to +// turn the list of errors into a string. +type ErrorFormatFunc func([]error) string + +// ListFormatFunc is a basic formatter that outputs the number of errors +// that occurred along with a bullet point list of the errors. +func ListFormatFunc(es []error) string { + points := make([]string, len(es)) + for i, err := range es { + points[i] = fmt.Sprintf("* %s", err) + } + + return fmt.Sprintf( + "%d error(s) occurred:\n\n%s", + len(es), strings.Join(points, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go new file mode 100644 index 000000000..2ea082732 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/multierror.go @@ -0,0 +1,51 @@ +package multierror + +import ( + "fmt" +) + +// Error is an error type to track multiple errors. This is used to +// accumulate errors in cases and return them as a single "error". +type Error struct { + Errors []error + ErrorFormat ErrorFormatFunc +} + +func (e *Error) Error() string { + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } + + return fn(e.Errors) +} + +// ErrorOrNil returns an error interface if this Error represents +// a list of errors, or returns nil if the list of errors is empty. This +// function is useful at the end of accumulation to make sure that the value +// returned represents the existence of errors. +func (e *Error) ErrorOrNil() error { + if e == nil { + return nil + } + if len(e.Errors) == 0 { + return nil + } + + return e +} + +func (e *Error) GoString() string { + return fmt.Sprintf("*%#v", *e) +} + +// WrappedErrors returns the list of errors that this Error is wrapping. +// It is an implementatin of the errwrap.Wrapper interface so that +// multierror.Error can be used with that library. +// +// This method is not safe to be called concurrently and is no different +// than accessing the Errors field directly. It is implementd only to +// satisfy the errwrap.Wrapper interface. +func (e *Error) WrappedErrors() []error { + return e.Errors +} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix.go b/vendor/github.com/hashicorp/go-multierror/prefix.go new file mode 100644 index 000000000..5c477abe4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/prefix.go @@ -0,0 +1,37 @@ +package multierror + +import ( + "fmt" + + "github.com/hashicorp/errwrap" +) + +// Prefix is a helper function that will prefix some text +// to the given error. If the error is a multierror.Error, then +// it will be prefixed to each wrapped error. +// +// This is useful to use when appending multiple multierrors +// together in order to give better scoping. +func Prefix(err error, prefix string) error { + if err == nil { + return nil + } + + format := fmt.Sprintf("%s {{err}}", prefix) + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Wrap each of the errors + for i, e := range err.Errors { + err.Errors[i] = errwrap.Wrapf(format, e) + } + + return err + default: + return errwrap.Wrapf(format, err) + } +} diff --git a/vendor/github.com/hashicorp/go-version/.travis.yml b/vendor/github.com/hashicorp/go-version/.travis.yml new file mode 100644 index 000000000..9f30eecd7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - 1.0 + - 1.1 + - 1.2 + - 1.3 + - 1.4 + +script: + - go test diff --git a/vendor/github.com/hashicorp/go-version/LICENSE b/vendor/github.com/hashicorp/go-version/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/go-version/README.md b/vendor/github.com/hashicorp/go-version/README.md new file mode 100644 index 000000000..1d50070f1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/README.md @@ -0,0 +1,65 @@ +# Versioning Library for Go +[![Build Status](https://travis-ci.org/hashicorp/go-version.svg?branch=master)](https://travis-ci.org/hashicorp/go-version) + +go-version is a library for parsing versions and version constraints, +and verifying versions against a set of constraints. go-version +can sort a collection of versions properly, handles prerelease/beta +versions, can increment versions, etc. + +Versions used with go-version must follow [SemVer](http://semver.org/). + +## Installation and Usage + +Package documentation can be found on +[GoDoc](http://godoc.org/github.com/hashicorp/go-version). + +Installation can be done with a normal `go get`: + +``` +$ go get github.com/hashicorp/go-version +``` + +#### Version Parsing and Comparison + +```go +v1, err := version.NewVersion("1.2") +v2, err := version.NewVersion("1.5+metadata") + +// Comparison example. There is also GreaterThan, Equal, and just +// a simple Compare that returns an int allowing easy >=, <=, etc. +if v1.LessThan(v2) { + fmt.Printf("%s is less than %s", v1, v2) +} +``` + +#### Version Constraints + +```go +v1, err := version.NewVersion("1.2") + +// Constraints example. +constraints, err := version.NewConstraint(">= 1.0, < 1.4") +if constraints.Check(v1) { + fmt.Printf("%s satisfies constraints %s", v1, constraints) +} +``` + +#### Version Sorting + +```go +versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"} +versions := make([]*version.Version, len(versionsRaw)) +for i, raw := range versionsRaw { + v, _ := version.NewVersion(raw) + versions[i] = v +} + +// After this, the versions are properly sorted +sort.Sort(version.Collection(versions)) +``` + +## Issues and Contributing + +If you find an issue with this library, please report an issue. If you'd +like, we welcome any contributions. Fork this library and submit a pull +request. diff --git a/vendor/github.com/hashicorp/go-version/constraint.go b/vendor/github.com/hashicorp/go-version/constraint.go new file mode 100644 index 000000000..091cfab38 --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/constraint.go @@ -0,0 +1,156 @@ +package version + +import ( + "fmt" + "regexp" + "strings" +) + +// Constraint represents a single constraint for a version, such as +// ">= 1.0". +type Constraint struct { + f constraintFunc + check *Version + original string +} + +// Constraints is a slice of constraints. We make a custom type so that +// we can add methods to it. +type Constraints []*Constraint + +type constraintFunc func(v, c *Version) bool + +var constraintOperators map[string]constraintFunc + +var constraintRegexp *regexp.Regexp + +func init() { + constraintOperators = map[string]constraintFunc{ + "": constraintEqual, + "=": constraintEqual, + "!=": constraintNotEqual, + ">": constraintGreaterThan, + "<": constraintLessThan, + ">=": constraintGreaterThanEqual, + "<=": constraintLessThanEqual, + "~>": constraintPessimistic, + } + + ops := make([]string, 0, len(constraintOperators)) + for k, _ := range constraintOperators { + ops = append(ops, regexp.QuoteMeta(k)) + } + + constraintRegexp = regexp.MustCompile(fmt.Sprintf( + `^\s*(%s)\s*(%s)\s*$`, + strings.Join(ops, "|"), + VersionRegexpRaw)) +} + +// NewConstraint will parse one or more constraints from the given +// constraint string. The string must be a comma-separated list of +// constraints. +func NewConstraint(v string) (Constraints, error) { + vs := strings.Split(v, ",") + result := make([]*Constraint, len(vs)) + for i, single := range vs { + c, err := parseSingle(single) + if err != nil { + return nil, err + } + + result[i] = c + } + + return Constraints(result), nil +} + +// Check tests if a version satisfies all the constraints. +func (cs Constraints) Check(v *Version) bool { + for _, c := range cs { + if !c.Check(v) { + return false + } + } + + return true +} + +// Returns the string format of the constraints +func (cs Constraints) String() string { + csStr := make([]string, len(cs)) + for i, c := range cs { + csStr[i] = c.String() + } + + return strings.Join(csStr, ",") +} + +// Check tests if a constraint is validated by the given version. +func (c *Constraint) Check(v *Version) bool { + return c.f(v, c.check) +} + +func (c *Constraint) String() string { + return c.original +} + +func parseSingle(v string) (*Constraint, error) { + matches := constraintRegexp.FindStringSubmatch(v) + if matches == nil { + return nil, fmt.Errorf("Malformed constraint: %s", v) + } + + check, err := NewVersion(matches[2]) + if err != nil { + return nil, err + } + + return &Constraint{ + f: constraintOperators[matches[1]], + check: check, + original: v, + }, nil +} + +//------------------------------------------------------------------- +// Constraint functions +//------------------------------------------------------------------- + +func constraintEqual(v, c *Version) bool { + return v.Equal(c) +} + +func constraintNotEqual(v, c *Version) bool { + return !v.Equal(c) +} + +func constraintGreaterThan(v, c *Version) bool { + return v.Compare(c) == 1 +} + +func constraintLessThan(v, c *Version) bool { + return v.Compare(c) == -1 +} + +func constraintGreaterThanEqual(v, c *Version) bool { + return v.Compare(c) >= 0 +} + +func constraintLessThanEqual(v, c *Version) bool { + return v.Compare(c) <= 0 +} + +func constraintPessimistic(v, c *Version) bool { + if v.LessThan(c) { + return false + } + + for i := 0; i < c.si-1; i++ { + if v.segments[i] != c.segments[i] { + return false + } + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-version/version.go b/vendor/github.com/hashicorp/go-version/version.go new file mode 100644 index 000000000..d0e0b0c8f --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/version.go @@ -0,0 +1,251 @@ +package version + +import ( + "bytes" + "fmt" + "reflect" + "regexp" + "strconv" + "strings" +) + +// The compiled regular expression used to test the validity of a version. +var versionRegexp *regexp.Regexp + +// The raw regular expression string used for testing the validity +// of a version. +const VersionRegexpRaw string = `([0-9]+(\.[0-9]+){0,2})` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `?` + +// Version represents a single version. +type Version struct { + metadata string + pre string + segments []int + si int +} + +func init() { + versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$") +} + +// NewVersion parses the given version and returns a new +// Version. +func NewVersion(v string) (*Version, error) { + matches := versionRegexp.FindStringSubmatch(v) + if matches == nil { + return nil, fmt.Errorf("Malformed version: %s", v) + } + + segmentsStr := strings.Split(matches[1], ".") + segments := make([]int, len(segmentsStr), 3) + si := 0 + for i, str := range segmentsStr { + val, err := strconv.ParseInt(str, 10, 32) + if err != nil { + return nil, fmt.Errorf( + "Error parsing version: %s", err) + } + + segments[i] = int(val) + si += 1 + } + for i := len(segments); i < 3; i++ { + segments = append(segments, 0) + } + + return &Version{ + metadata: matches[7], + pre: matches[4], + segments: segments, + si: si, + }, nil +} + +// Must is a helper that wraps a call to a function returning (*Version, error) +// and panics if error is non-nil. +func Must(v *Version, err error) *Version { + if err != nil { + panic(err) + } + + return v +} + +// Compare compares this version to another version. This +// returns -1, 0, or 1 if this version is smaller, equal, +// or larger than the other version, respectively. +// +// If you want boolean results, use the LessThan, Equal, +// or GreaterThan methods. +func (v *Version) Compare(other *Version) int { + // A quick, efficient equality check + if v.String() == other.String() { + return 0 + } + + segmentsSelf := v.Segments() + segmentsOther := other.Segments() + + // If the segments are the same, we must compare on prerelease info + if reflect.DeepEqual(segmentsSelf, segmentsOther) { + preSelf := v.Prerelease() + preOther := other.Prerelease() + if preSelf == "" && preOther == "" { + return 0 + } + if preSelf == "" { + return 1 + } + if preOther == "" { + return -1 + } + + return comparePrereleases(preSelf, preOther) + } + + // Compare the segments + for i := 0; i < len(segmentsSelf); i++ { + lhs := segmentsSelf[i] + rhs := segmentsOther[i] + + if lhs == rhs { + continue + } else if lhs < rhs { + return -1 + } else { + return 1 + } + } + + panic("should not be reached") +} + +func comparePart(preSelf string, preOther string) int { + if preSelf == preOther { + return 0 + } + + // if a part is empty, we use the other to decide + if preSelf == "" { + _, notIsNumeric := strconv.ParseInt(preOther, 10, 64) + if notIsNumeric == nil { + return -1 + } + return 1 + } + + if preOther == "" { + _, notIsNumeric := strconv.ParseInt(preSelf, 10, 64) + if notIsNumeric == nil { + return 1 + } + return -1 + } + + if preSelf > preOther { + return 1 + } + + return -1 +} + +func comparePrereleases(v string, other string) int { + // the same pre release! + if v == other { + return 0 + } + + // split both pre releases for analyse their parts + selfPreReleaseMeta := strings.Split(v, ".") + otherPreReleaseMeta := strings.Split(other, ".") + + selfPreReleaseLen := len(selfPreReleaseMeta) + otherPreReleaseLen := len(otherPreReleaseMeta) + + biggestLen := otherPreReleaseLen + if selfPreReleaseLen > otherPreReleaseLen { + biggestLen = selfPreReleaseLen + } + + // loop for parts to find the first difference + for i := 0; i < biggestLen; i = i + 1 { + partSelfPre := "" + if i < selfPreReleaseLen { + partSelfPre = selfPreReleaseMeta[i] + } + + partOtherPre := "" + if i < otherPreReleaseLen { + partOtherPre = otherPreReleaseMeta[i] + } + + compare := comparePart(partSelfPre, partOtherPre) + // if parts are equals, continue the loop + if compare != 0 { + return compare + } + } + + return 0 +} + +// Equal tests if two versions are equal. +func (v *Version) Equal(o *Version) bool { + return v.Compare(o) == 0 +} + +// GreaterThan tests if this version is greater than another version. +func (v *Version) GreaterThan(o *Version) bool { + return v.Compare(o) > 0 +} + +// LessThan tests if this version is less than another version. +func (v *Version) LessThan(o *Version) bool { + return v.Compare(o) < 0 +} + +// Metadata returns any metadata that was part of the version +// string. +// +// Metadata is anything that comes after the "+" in the version. +// For example, with "1.2.3+beta", the metadata is "beta". +func (v *Version) Metadata() string { + return v.metadata +} + +// Prerelease returns any prerelease data that is part of the version, +// or blank if there is no prerelease data. +// +// Prerelease information is anything that comes after the "-" in the +// version (but before any metadata). For example, with "1.2.3-beta", +// the prerelease information is "beta". +func (v *Version) Prerelease() string { + return v.pre +} + +// Segments returns the numeric segments of the version as a slice. +// +// This excludes any metadata or pre-release information. For example, +// for a version "1.2.3-beta", segments will return a slice of +// 1, 2, 3. +func (v *Version) Segments() []int { + return v.segments +} + +// String returns the full version string included pre-release +// and metadata information. +func (v *Version) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%d.%d.%d", v.segments[0], v.segments[1], v.segments[2]) + if v.pre != "" { + fmt.Fprintf(&buf, "-%s", v.pre) + } + if v.metadata != "" { + fmt.Fprintf(&buf, "+%s", v.metadata) + } + + return buf.String() +} diff --git a/vendor/github.com/hashicorp/go-version/version_collection.go b/vendor/github.com/hashicorp/go-version/version_collection.go new file mode 100644 index 000000000..cc888d43e --- /dev/null +++ b/vendor/github.com/hashicorp/go-version/version_collection.go @@ -0,0 +1,17 @@ +package version + +// Collection is a type that implements the sort.Interface interface +// so that versions can be sorted. +type Collection []*Version + +func (v Collection) Len() int { + return len(v) +} + +func (v Collection) Less(i, j int) bool { + return v[i].LessThan(v[j]) +} + +func (v Collection) Swap(i, j int) { + v[i], v[j] = v[j], v[i] +} diff --git a/vendor/github.com/hashicorp/yamux/.gitignore b/vendor/github.com/hashicorp/yamux/.gitignore new file mode 100644 index 000000000..836562412 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/.gitignore @@ -0,0 +1,23 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test diff --git a/vendor/github.com/hashicorp/yamux/LICENSE b/vendor/github.com/hashicorp/yamux/LICENSE new file mode 100644 index 000000000..f0e5c79e1 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/LICENSE @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/vendor/github.com/hashicorp/yamux/README.md b/vendor/github.com/hashicorp/yamux/README.md new file mode 100644 index 000000000..d4db7fc99 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/README.md @@ -0,0 +1,86 @@ +# Yamux + +Yamux (Yet another Multiplexer) is a multiplexing library for Golang. +It relies on an underlying connection to provide reliability +and ordering, such as TCP or Unix domain sockets, and provides +stream-oriented multiplexing. It is inspired by SPDY but is not +interoperable with it. + +Yamux features include: + +* Bi-directional streams + * Streams can be opened by either client or server + * Useful for NAT traversal + * Server-side push support +* Flow control + * Avoid starvation + * Back-pressure to prevent overwhelming a receiver +* Keep Alives + * Enables persistent connections over a load balancer +* Efficient + * Enables thousands of logical streams with low overhead + +## Documentation + +For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/yamux). + +## Specification + +The full specification for Yamux is provided in the `spec.md` file. +It can be used as a guide to implementors of interoperable libraries. + +## Usage + +Using Yamux is remarkably simple: + +```go + +func client() { + // Get a TCP connection + conn, err := net.Dial(...) + if err != nil { + panic(err) + } + + // Setup client side of yamux + session, err := yamux.Client(conn, nil) + if err != nil { + panic(err) + } + + // Open a new stream + stream, err := session.Open() + if err != nil { + panic(err) + } + + // Stream implements net.Conn + stream.Write([]byte("ping")) +} + +func server() { + // Accept a TCP connection + conn, err := listener.Accept() + if err != nil { + panic(err) + } + + // Setup server side of yamux + session, err := yamux.Server(conn, nil) + if err != nil { + panic(err) + } + + // Accept a stream + stream, err := session.Accept() + if err != nil { + panic(err) + } + + // Listen for a message + buf := make([]byte, 4) + stream.Read(buf) +} + +``` + diff --git a/vendor/github.com/hashicorp/yamux/addr.go b/vendor/github.com/hashicorp/yamux/addr.go new file mode 100644 index 000000000..be6ebca9c --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/addr.go @@ -0,0 +1,60 @@ +package yamux + +import ( + "fmt" + "net" +) + +// hasAddr is used to get the address from the underlying connection +type hasAddr interface { + LocalAddr() net.Addr + RemoteAddr() net.Addr +} + +// yamuxAddr is used when we cannot get the underlying address +type yamuxAddr struct { + Addr string +} + +func (*yamuxAddr) Network() string { + return "yamux" +} + +func (y *yamuxAddr) String() string { + return fmt.Sprintf("yamux:%s", y.Addr) +} + +// Addr is used to get the address of the listener. +func (s *Session) Addr() net.Addr { + return s.LocalAddr() +} + +// LocalAddr is used to get the local address of the +// underlying connection. +func (s *Session) LocalAddr() net.Addr { + addr, ok := s.conn.(hasAddr) + if !ok { + return &yamuxAddr{"local"} + } + return addr.LocalAddr() +} + +// RemoteAddr is used to get the address of remote end +// of the underlying connection +func (s *Session) RemoteAddr() net.Addr { + addr, ok := s.conn.(hasAddr) + if !ok { + return &yamuxAddr{"remote"} + } + return addr.RemoteAddr() +} + +// LocalAddr returns the local address +func (s *Stream) LocalAddr() net.Addr { + return s.session.LocalAddr() +} + +// LocalAddr returns the remote address +func (s *Stream) RemoteAddr() net.Addr { + return s.session.RemoteAddr() +} diff --git a/vendor/github.com/hashicorp/yamux/const.go b/vendor/github.com/hashicorp/yamux/const.go new file mode 100644 index 000000000..4f5293828 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/const.go @@ -0,0 +1,157 @@ +package yamux + +import ( + "encoding/binary" + "fmt" +) + +var ( + // ErrInvalidVersion means we received a frame with an + // invalid version + ErrInvalidVersion = fmt.Errorf("invalid protocol version") + + // ErrInvalidMsgType means we received a frame with an + // invalid message type + ErrInvalidMsgType = fmt.Errorf("invalid msg type") + + // ErrSessionShutdown is used if there is a shutdown during + // an operation + ErrSessionShutdown = fmt.Errorf("session shutdown") + + // ErrStreamsExhausted is returned if we have no more + // stream ids to issue + ErrStreamsExhausted = fmt.Errorf("streams exhausted") + + // ErrDuplicateStream is used if a duplicate stream is + // opened inbound + ErrDuplicateStream = fmt.Errorf("duplicate stream initiated") + + // ErrReceiveWindowExceeded indicates the window was exceeded + ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded") + + // ErrTimeout is used when we reach an IO deadline + ErrTimeout = fmt.Errorf("i/o deadline reached") + + // ErrStreamClosed is returned when using a closed stream + ErrStreamClosed = fmt.Errorf("stream closed") + + // ErrUnexpectedFlag is set when we get an unexpected flag + ErrUnexpectedFlag = fmt.Errorf("unexpected flag") + + // ErrRemoteGoAway is used when we get a go away from the other side + ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections") + + // ErrConnectionReset is sent if a stream is reset. This can happen + // if the backlog is exceeded, or if there was a remote GoAway. + ErrConnectionReset = fmt.Errorf("connection reset") + + // ErrConnectionWriteTimeout indicates that we hit the "safety valve" + // timeout writing to the underlying stream connection. + ErrConnectionWriteTimeout = fmt.Errorf("connection write timeout") + + // ErrKeepAliveTimeout is sent if a missed keepalive caused the stream close + ErrKeepAliveTimeout = fmt.Errorf("keepalive timeout") +) + +const ( + // protoVersion is the only version we support + protoVersion uint8 = 0 +) + +const ( + // Data is used for data frames. They are followed + // by length bytes worth of payload. + typeData uint8 = iota + + // WindowUpdate is used to change the window of + // a given stream. The length indicates the delta + // update to the window. + typeWindowUpdate + + // Ping is sent as a keep-alive or to measure + // the RTT. The StreamID and Length value are echoed + // back in the response. + typePing + + // GoAway is sent to terminate a session. The StreamID + // should be 0 and the length is an error code. + typeGoAway +) + +const ( + // SYN is sent to signal a new stream. May + // be sent with a data payload + flagSYN uint16 = 1 << iota + + // ACK is sent to acknowledge a new stream. May + // be sent with a data payload + flagACK + + // FIN is sent to half-close the given stream. + // May be sent with a data payload. + flagFIN + + // RST is used to hard close a given stream. + flagRST +) + +const ( + // initialStreamWindow is the initial stream window size + initialStreamWindow uint32 = 256 * 1024 +) + +const ( + // goAwayNormal is sent on a normal termination + goAwayNormal uint32 = iota + + // goAwayProtoErr sent on a protocol error + goAwayProtoErr + + // goAwayInternalErr sent on an internal error + goAwayInternalErr +) + +const ( + sizeOfVersion = 1 + sizeOfType = 1 + sizeOfFlags = 2 + sizeOfStreamID = 4 + sizeOfLength = 4 + headerSize = sizeOfVersion + sizeOfType + sizeOfFlags + + sizeOfStreamID + sizeOfLength +) + +type header []byte + +func (h header) Version() uint8 { + return h[0] +} + +func (h header) MsgType() uint8 { + return h[1] +} + +func (h header) Flags() uint16 { + return binary.BigEndian.Uint16(h[2:4]) +} + +func (h header) StreamID() uint32 { + return binary.BigEndian.Uint32(h[4:8]) +} + +func (h header) Length() uint32 { + return binary.BigEndian.Uint32(h[8:12]) +} + +func (h header) String() string { + return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d", + h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length()) +} + +func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) { + h[0] = protoVersion + h[1] = msgType + binary.BigEndian.PutUint16(h[2:4], flags) + binary.BigEndian.PutUint32(h[4:8], streamID) + binary.BigEndian.PutUint32(h[8:12], length) +} diff --git a/vendor/github.com/hashicorp/yamux/mux.go b/vendor/github.com/hashicorp/yamux/mux.go new file mode 100644 index 000000000..7abc7c744 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/mux.go @@ -0,0 +1,87 @@ +package yamux + +import ( + "fmt" + "io" + "os" + "time" +) + +// Config is used to tune the Yamux session +type Config struct { + // AcceptBacklog is used to limit how many streams may be + // waiting an accept. + AcceptBacklog int + + // EnableKeepalive is used to do a period keep alive + // messages using a ping. + EnableKeepAlive bool + + // KeepAliveInterval is how often to perform the keep alive + KeepAliveInterval time.Duration + + // ConnectionWriteTimeout is meant to be a "safety valve" timeout after + // we which will suspect a problem with the underlying connection and + // close it. This is only applied to writes, where's there's generally + // an expectation that things will move along quickly. + ConnectionWriteTimeout time.Duration + + // MaxStreamWindowSize is used to control the maximum + // window size that we allow for a stream. + MaxStreamWindowSize uint32 + + // LogOutput is used to control the log destination + LogOutput io.Writer +} + +// DefaultConfig is used to return a default configuration +func DefaultConfig() *Config { + return &Config{ + AcceptBacklog: 256, + EnableKeepAlive: true, + KeepAliveInterval: 30 * time.Second, + ConnectionWriteTimeout: 10 * time.Second, + MaxStreamWindowSize: initialStreamWindow, + LogOutput: os.Stderr, + } +} + +// VerifyConfig is used to verify the sanity of configuration +func VerifyConfig(config *Config) error { + if config.AcceptBacklog <= 0 { + return fmt.Errorf("backlog must be positive") + } + if config.KeepAliveInterval == 0 { + return fmt.Errorf("keep-alive interval must be positive") + } + if config.MaxStreamWindowSize < initialStreamWindow { + return fmt.Errorf("MaxStreamWindowSize must be larger than %d", initialStreamWindow) + } + return nil +} + +// Server is used to initialize a new server-side connection. +// There must be at most one server-side connection. If a nil config is +// provided, the DefaultConfiguration will be used. +func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) { + if config == nil { + config = DefaultConfig() + } + if err := VerifyConfig(config); err != nil { + return nil, err + } + return newSession(config, conn, false), nil +} + +// Client is used to initialize a new client-side connection. +// There must be at most one client-side connection. +func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) { + if config == nil { + config = DefaultConfig() + } + + if err := VerifyConfig(config); err != nil { + return nil, err + } + return newSession(config, conn, true), nil +} diff --git a/vendor/github.com/hashicorp/yamux/session.go b/vendor/github.com/hashicorp/yamux/session.go new file mode 100644 index 000000000..20369bdd9 --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/session.go @@ -0,0 +1,598 @@ +package yamux + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "net" + "strings" + "sync" + "sync/atomic" + "time" +) + +// Session is used to wrap a reliable ordered connection and to +// multiplex it into multiple streams. +type Session struct { + // remoteGoAway indicates the remote side does + // not want futher connections. Must be first for alignment. + remoteGoAway int32 + + // localGoAway indicates that we should stop + // accepting futher connections. Must be first for alignment. + localGoAway int32 + + // nextStreamID is the next stream we should + // send. This depends if we are a client/server. + nextStreamID uint32 + + // config holds our configuration + config *Config + + // logger is used for our logs + logger *log.Logger + + // conn is the underlying connection + conn io.ReadWriteCloser + + // bufRead is a buffered reader + bufRead *bufio.Reader + + // pings is used to track inflight pings + pings map[uint32]chan struct{} + pingID uint32 + pingLock sync.Mutex + + // streams maps a stream id to a stream + streams map[uint32]*Stream + streamLock sync.Mutex + + // synCh acts like a semaphore. It is sized to the AcceptBacklog which + // is assumed to be symmetric between the client and server. This allows + // the client to avoid exceeding the backlog and instead blocks the open. + synCh chan struct{} + + // acceptCh is used to pass ready streams to the client + acceptCh chan *Stream + + // sendCh is used to mark a stream as ready to send, + // or to send a header out directly. + sendCh chan sendReady + + // recvDoneCh is closed when recv() exits to avoid a race + // between stream registration and stream shutdown + recvDoneCh chan struct{} + + // shutdown is used to safely close a session + shutdown bool + shutdownErr error + shutdownCh chan struct{} + shutdownLock sync.Mutex +} + +// sendReady is used to either mark a stream as ready +// or to directly send a header +type sendReady struct { + Hdr []byte + Body io.Reader + Err chan error +} + +// newSession is used to construct a new session +func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session { + s := &Session{ + config: config, + logger: log.New(config.LogOutput, "", log.LstdFlags), + conn: conn, + bufRead: bufio.NewReader(conn), + pings: make(map[uint32]chan struct{}), + streams: make(map[uint32]*Stream), + synCh: make(chan struct{}, config.AcceptBacklog), + acceptCh: make(chan *Stream, config.AcceptBacklog), + sendCh: make(chan sendReady, 64), + recvDoneCh: make(chan struct{}), + shutdownCh: make(chan struct{}), + } + if client { + s.nextStreamID = 1 + } else { + s.nextStreamID = 2 + } + go s.recv() + go s.send() + if config.EnableKeepAlive { + go s.keepalive() + } + return s +} + +// IsClosed does a safe check to see if we have shutdown +func (s *Session) IsClosed() bool { + select { + case <-s.shutdownCh: + return true + default: + return false + } +} + +// NumStreams returns the number of currently open streams +func (s *Session) NumStreams() int { + s.streamLock.Lock() + num := len(s.streams) + s.streamLock.Unlock() + return num +} + +// Open is used to create a new stream as a net.Conn +func (s *Session) Open() (net.Conn, error) { + conn, err := s.OpenStream() + if err != nil { + return nil, err + } + return conn, nil +} + +// OpenStream is used to create a new stream +func (s *Session) OpenStream() (*Stream, error) { + if s.IsClosed() { + return nil, ErrSessionShutdown + } + if atomic.LoadInt32(&s.remoteGoAway) == 1 { + return nil, ErrRemoteGoAway + } + + // Block if we have too many inflight SYNs + select { + case s.synCh <- struct{}{}: + case <-s.shutdownCh: + return nil, ErrSessionShutdown + } + +GET_ID: + // Get and ID, and check for stream exhaustion + id := atomic.LoadUint32(&s.nextStreamID) + if id >= math.MaxUint32-1 { + return nil, ErrStreamsExhausted + } + if !atomic.CompareAndSwapUint32(&s.nextStreamID, id, id+2) { + goto GET_ID + } + + // Register the stream + stream := newStream(s, id, streamInit) + s.streamLock.Lock() + s.streams[id] = stream + s.streamLock.Unlock() + + // Send the window update to create + if err := stream.sendWindowUpdate(); err != nil { + return nil, err + } + return stream, nil +} + +// Accept is used to block until the next available stream +// is ready to be accepted. +func (s *Session) Accept() (net.Conn, error) { + conn, err := s.AcceptStream() + if err != nil { + return nil, err + } + return conn, err +} + +// AcceptStream is used to block until the next available stream +// is ready to be accepted. +func (s *Session) AcceptStream() (*Stream, error) { + select { + case stream := <-s.acceptCh: + if err := stream.sendWindowUpdate(); err != nil { + return nil, err + } + return stream, nil + case <-s.shutdownCh: + return nil, s.shutdownErr + } +} + +// Close is used to close the session and all streams. +// Attempts to send a GoAway before closing the connection. +func (s *Session) Close() error { + s.shutdownLock.Lock() + defer s.shutdownLock.Unlock() + + if s.shutdown { + return nil + } + s.shutdown = true + if s.shutdownErr == nil { + s.shutdownErr = ErrSessionShutdown + } + close(s.shutdownCh) + s.conn.Close() + <-s.recvDoneCh + + s.streamLock.Lock() + defer s.streamLock.Unlock() + for _, stream := range s.streams { + stream.forceClose() + } + return nil +} + +// exitErr is used to handle an error that is causing the +// session to terminate. +func (s *Session) exitErr(err error) { + s.shutdownLock.Lock() + if s.shutdownErr == nil { + s.shutdownErr = err + } + s.shutdownLock.Unlock() + s.Close() +} + +// GoAway can be used to prevent accepting further +// connections. It does not close the underlying conn. +func (s *Session) GoAway() error { + return s.waitForSend(s.goAway(goAwayNormal), nil) +} + +// goAway is used to send a goAway message +func (s *Session) goAway(reason uint32) header { + atomic.SwapInt32(&s.localGoAway, 1) + hdr := header(make([]byte, headerSize)) + hdr.encode(typeGoAway, 0, 0, reason) + return hdr +} + +// Ping is used to measure the RTT response time +func (s *Session) Ping() (time.Duration, error) { + // Get a channel for the ping + ch := make(chan struct{}) + + // Get a new ping id, mark as pending + s.pingLock.Lock() + id := s.pingID + s.pingID++ + s.pings[id] = ch + s.pingLock.Unlock() + + // Send the ping request + hdr := header(make([]byte, headerSize)) + hdr.encode(typePing, flagSYN, 0, id) + if err := s.waitForSend(hdr, nil); err != nil { + return 0, err + } + + // Wait for a response + start := time.Now() + select { + case <-ch: + case <-time.After(s.config.ConnectionWriteTimeout): + s.pingLock.Lock() + delete(s.pings, id) // Ignore it if a response comes later. + s.pingLock.Unlock() + return 0, ErrTimeout + case <-s.shutdownCh: + return 0, ErrSessionShutdown + } + + // Compute the RTT + return time.Now().Sub(start), nil +} + +// keepalive is a long running goroutine that periodically does +// a ping to keep the connection alive. +func (s *Session) keepalive() { + for { + select { + case <-time.After(s.config.KeepAliveInterval): + _, err := s.Ping() + if err != nil { + s.logger.Printf("[ERR] yamux: keepalive failed: %v", err) + s.exitErr(ErrKeepAliveTimeout) + return + } + case <-s.shutdownCh: + return + } + } +} + +// waitForSendErr waits to send a header, checking for a potential shutdown +func (s *Session) waitForSend(hdr header, body io.Reader) error { + errCh := make(chan error, 1) + return s.waitForSendErr(hdr, body, errCh) +} + +// waitForSendErr waits to send a header with optional data, checking for a +// potential shutdown. Since there's the expectation that sends can happen +// in a timely manner, we enforce the connection write timeout here. +func (s *Session) waitForSendErr(hdr header, body io.Reader, errCh chan error) error { + timer := time.NewTimer(s.config.ConnectionWriteTimeout) + defer timer.Stop() + + ready := sendReady{Hdr: hdr, Body: body, Err: errCh} + select { + case s.sendCh <- ready: + case <-s.shutdownCh: + return ErrSessionShutdown + case <-timer.C: + return ErrConnectionWriteTimeout + } + + select { + case err := <-errCh: + return err + case <-s.shutdownCh: + return ErrSessionShutdown + case <-timer.C: + return ErrConnectionWriteTimeout + } +} + +// sendNoWait does a send without waiting. Since there's the expectation that +// the send happens right here, we enforce the connection write timeout if we +// can't queue the header to be sent. +func (s *Session) sendNoWait(hdr header) error { + timer := time.NewTimer(s.config.ConnectionWriteTimeout) + defer timer.Stop() + + select { + case s.sendCh <- sendReady{Hdr: hdr}: + return nil + case <-s.shutdownCh: + return ErrSessionShutdown + case <-timer.C: + return ErrConnectionWriteTimeout + } +} + +// send is a long running goroutine that sends data +func (s *Session) send() { + for { + select { + case ready := <-s.sendCh: + // Send a header if ready + if ready.Hdr != nil { + sent := 0 + for sent < len(ready.Hdr) { + n, err := s.conn.Write(ready.Hdr[sent:]) + if err != nil { + s.logger.Printf("[ERR] yamux: Failed to write header: %v", err) + asyncSendErr(ready.Err, err) + s.exitErr(err) + return + } + sent += n + } + } + + // Send data from a body if given + if ready.Body != nil { + _, err := io.Copy(s.conn, ready.Body) + if err != nil { + s.logger.Printf("[ERR] yamux: Failed to write body: %v", err) + asyncSendErr(ready.Err, err) + s.exitErr(err) + return + } + } + + // No error, successful send + asyncSendErr(ready.Err, nil) + case <-s.shutdownCh: + return + } + } +} + +// recv is a long running goroutine that accepts new data +func (s *Session) recv() { + if err := s.recvLoop(); err != nil { + s.exitErr(err) + } +} + +// recvLoop continues to receive data until a fatal error is encountered +func (s *Session) recvLoop() error { + defer close(s.recvDoneCh) + hdr := header(make([]byte, headerSize)) + var handler func(header) error + for { + // Read the header + if _, err := io.ReadFull(s.bufRead, hdr); err != nil { + if err != io.EOF && !strings.Contains(err.Error(), "closed") && !strings.Contains(err.Error(), "reset by peer") { + s.logger.Printf("[ERR] yamux: Failed to read header: %v", err) + } + return err + } + + // Verify the version + if hdr.Version() != protoVersion { + s.logger.Printf("[ERR] yamux: Invalid protocol version: %d", hdr.Version()) + return ErrInvalidVersion + } + + // Switch on the type + switch hdr.MsgType() { + case typeData: + handler = s.handleStreamMessage + case typeWindowUpdate: + handler = s.handleStreamMessage + case typeGoAway: + handler = s.handleGoAway + case typePing: + handler = s.handlePing + default: + return ErrInvalidMsgType + } + + // Invoke the handler + if err := handler(hdr); err != nil { + return err + } + } +} + +// handleStreamMessage handles either a data or window update frame +func (s *Session) handleStreamMessage(hdr header) error { + // Check for a new stream creation + id := hdr.StreamID() + flags := hdr.Flags() + if flags&flagSYN == flagSYN { + if err := s.incomingStream(id); err != nil { + return err + } + } + + // Get the stream + s.streamLock.Lock() + stream := s.streams[id] + s.streamLock.Unlock() + + // If we do not have a stream, likely we sent a RST + if stream == nil { + // Drain any data on the wire + if hdr.MsgType() == typeData && hdr.Length() > 0 { + s.logger.Printf("[WARN] yamux: Discarding data for stream: %d", id) + if _, err := io.CopyN(ioutil.Discard, s.bufRead, int64(hdr.Length())); err != nil { + s.logger.Printf("[ERR] yamux: Failed to discard data: %v", err) + return nil + } + } else { + s.logger.Printf("[WARN] yamux: frame for missing stream: %v", hdr) + } + return nil + } + + // Check if this is a window update + if hdr.MsgType() == typeWindowUpdate { + if err := stream.incrSendWindow(hdr, flags); err != nil { + if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { + s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) + } + return err + } + return nil + } + + // Read the new data + if err := stream.readData(hdr, flags, s.bufRead); err != nil { + if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { + s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) + } + return err + } + return nil +} + +// handlePing is invokde for a typePing frame +func (s *Session) handlePing(hdr header) error { + flags := hdr.Flags() + pingID := hdr.Length() + + // Check if this is a query, respond back in a separate context so we + // don't interfere with the receiving thread blocking for the write. + if flags&flagSYN == flagSYN { + go func() { + hdr := header(make([]byte, headerSize)) + hdr.encode(typePing, flagACK, 0, pingID) + if err := s.sendNoWait(hdr); err != nil { + s.logger.Printf("[WARN] yamux: failed to send ping reply: %v", err) + } + }() + return nil + } + + // Handle a response + s.pingLock.Lock() + ch := s.pings[pingID] + if ch != nil { + delete(s.pings, pingID) + close(ch) + } + s.pingLock.Unlock() + return nil +} + +// handleGoAway is invokde for a typeGoAway frame +func (s *Session) handleGoAway(hdr header) error { + code := hdr.Length() + switch code { + case goAwayNormal: + atomic.SwapInt32(&s.remoteGoAway, 1) + case goAwayProtoErr: + s.logger.Printf("[ERR] yamux: received protocol error go away") + return fmt.Errorf("yamux protocol error") + case goAwayInternalErr: + s.logger.Printf("[ERR] yamux: received internal error go away") + return fmt.Errorf("remote yamux internal error") + default: + s.logger.Printf("[ERR] yamux: received unexpected go away") + return fmt.Errorf("unexpected go away received") + } + return nil +} + +// incomingStream is used to create a new incoming stream +func (s *Session) incomingStream(id uint32) error { + // Reject immediately if we are doing a go away + if atomic.LoadInt32(&s.localGoAway) == 1 { + hdr := header(make([]byte, headerSize)) + hdr.encode(typeWindowUpdate, flagRST, id, 0) + return s.sendNoWait(hdr) + } + + // Allocate a new stream + stream := newStream(s, id, streamSYNReceived) + + s.streamLock.Lock() + defer s.streamLock.Unlock() + + // Check if stream already exists + if _, ok := s.streams[id]; ok { + s.logger.Printf("[ERR] yamux: duplicate stream declared") + if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { + s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) + } + return ErrDuplicateStream + } + + // Register the stream + s.streams[id] = stream + + // Check if we've exceeded the backlog + select { + case s.acceptCh <- stream: + return nil + default: + // Backlog exceeded! RST the stream + s.logger.Printf("[WARN] yamux: backlog exceeded, forcing connection reset") + delete(s.streams, id) + stream.sendHdr.encode(typeWindowUpdate, flagRST, id, 0) + return s.sendNoWait(stream.sendHdr) + } +} + +// closeStream is used to close a stream once both sides have +// issued a close. +func (s *Session) closeStream(id uint32) { + s.streamLock.Lock() + delete(s.streams, id) + s.streamLock.Unlock() +} + +// establishStream is used to mark a stream that was in the +// SYN Sent state as established. +func (s *Session) establishStream() { + select { + case <-s.synCh: + default: + panic("established stream without inflight syn") + } +} diff --git a/vendor/github.com/hashicorp/yamux/spec.md b/vendor/github.com/hashicorp/yamux/spec.md new file mode 100644 index 000000000..419470b7f --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/spec.md @@ -0,0 +1,141 @@ +# Specification + +We use this document to detail the internal specification of Yamux. +This is used both as a guide for implementing Yamux, but also for +alternative interoperable libraries to be built. + +# Framing + +Yamux uses a streaming connection underneath, but imposes a message +framing so that it can be shared between many logical streams. Each +frame contains a header like: + +* Version (8 bits) +* Type (8 bits) +* Flags (16 bits) +* StreamID (32 bits) +* Length (32 bits) + +This means that each header has a 12 byte overhead. +All fields are encoded in network order (big endian). +Each field is described below: + +## Version Field + +The version field is used for future backwards compatibily. At the +current time, the field is always set to 0, to indicate the initial +version. + +## Type Field + +The type field is used to switch the frame message type. The following +message types are supported: + +* 0x0 Data - Used to transmit data. May transmit zero length payloads + depending on the flags. + +* 0x1 Window Update - Used to updated the senders receive window size. + This is used to implement per-session flow control. + +* 0x2 Ping - Used to measure RTT. It can also be used to heart-beat + and do keep-alives over TCP. + +* 0x3 Go Away - Used to close a session. + +## Flag Field + +The flags field is used to provide additional information related +to the message type. The following flags are supported: + +* 0x1 SYN - Signals the start of a new stream. May be sent with a data or + window update message. Also sent with a ping to indicate outbound. + +* 0x2 ACK - Acknowledges the start of a new stream. May be sent with a data + or window update message. Also sent with a ping to indicate response. + +* 0x4 FIN - Performs a half-close of a stream. May be sent with a data + message or window update. + +* 0x8 RST - Reset a stream immediately. May be sent with a data or + window update message. + +## StreamID Field + +The StreamID field is used to identify the logical stream the frame +is addressing. The client side should use odd ID's, and the server even. +This prevents any collisions. Additionally, the 0 ID is reserved to represent +the session. + +Both Ping and Go Away messages should always use the 0 StreamID. + +## Length Field + +The meaning of the length field depends on the message type: + +* Data - provides the length of bytes following the header +* Window update - provides a delta update to the window size +* Ping - Contains an opaque value, echoed back +* Go Away - Contains an error code + +# Message Flow + +There is no explicit connection setup, as Yamux relies on an underlying +transport to be provided. However, there is a distinction between client +and server side of the connection. + +## Opening a stream + +To open a stream, an initial data or window update frame is sent +with a new StreamID. The SYN flag should be set to signal a new stream. + +The receiver must then reply with either a data or window update frame +with the StreamID along with the ACK flag to accept the stream or with +the RST flag to reject the stream. + +Because we are relying on the reliable stream underneath, a connection +can begin sending data once the SYN flag is sent. The corresponding +ACK does not need to be received. This is particularly well suited +for an RPC system where a client wants to open a stream and immediately +fire a request without wiating for the RTT of the ACK. + +This does introduce the possibility of a connection being rejected +after data has been sent already. This is a slight semantic difference +from TCP, where the conection cannot be refused after it is opened. +Clients should be prepared to handle this by checking for an error +that indicates a RST was received. + +## Closing a stream + +To close a stream, either side sends a data or window update frame +along with the FIN flag. This does a half-close indicating the sender +will send no further data. + +Once both sides have closed the connection, the stream is closed. + +Alternatively, if an error occurs, the RST flag can be used to +hard close a stream immediately. + +## Flow Control + +When Yamux is initially starts each stream with a 256KB window size. +There is no window size for the session. + +To prevent the streams from stalling, window update frames should be +sent regularly. Yamux can be configured to provide a larger limit for +windows sizes. Both sides assume the initial 256KB window, but can +immediately send a window update as part of the SYN/ACK indicating a +larger window. + +Both sides should track the number of bytes sent in Data frames +only, as only they are tracked as part of the window size. + +## Session termination + +When a session is being terminated, the Go Away message should +be sent. The Length should be set to one of the following to +provide an error code: + +* 0x0 Normal termination +* 0x1 Protocol error +* 0x2 Internal error + diff --git a/vendor/github.com/hashicorp/yamux/stream.go b/vendor/github.com/hashicorp/yamux/stream.go new file mode 100644 index 000000000..4c3242d3e --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/stream.go @@ -0,0 +1,452 @@ +package yamux + +import ( + "bytes" + "io" + "sync" + "sync/atomic" + "time" +) + +type streamState int + +const ( + streamInit streamState = iota + streamSYNSent + streamSYNReceived + streamEstablished + streamLocalClose + streamRemoteClose + streamClosed + streamReset +) + +// Stream is used to represent a logical stream +// within a session. +type Stream struct { + recvWindow uint32 + sendWindow uint32 + + id uint32 + session *Session + + state streamState + stateLock sync.Mutex + + recvBuf *bytes.Buffer + recvLock sync.Mutex + + controlHdr header + controlErr chan error + controlHdrLock sync.Mutex + + sendHdr header + sendErr chan error + sendLock sync.Mutex + + recvNotifyCh chan struct{} + sendNotifyCh chan struct{} + + readDeadline time.Time + writeDeadline time.Time +} + +// newStream is used to construct a new stream within +// a given session for an ID +func newStream(session *Session, id uint32, state streamState) *Stream { + s := &Stream{ + id: id, + session: session, + state: state, + controlHdr: header(make([]byte, headerSize)), + controlErr: make(chan error, 1), + sendHdr: header(make([]byte, headerSize)), + sendErr: make(chan error, 1), + recvWindow: initialStreamWindow, + sendWindow: initialStreamWindow, + recvNotifyCh: make(chan struct{}, 1), + sendNotifyCh: make(chan struct{}, 1), + } + return s +} + +// Session returns the associated stream session +func (s *Stream) Session() *Session { + return s.session +} + +// StreamID returns the ID of this stream +func (s *Stream) StreamID() uint32 { + return s.id +} + +// Read is used to read from the stream +func (s *Stream) Read(b []byte) (n int, err error) { + defer asyncNotify(s.recvNotifyCh) +START: + s.stateLock.Lock() + switch s.state { + case streamLocalClose: + fallthrough + case streamRemoteClose: + fallthrough + case streamClosed: + if s.recvBuf == nil || s.recvBuf.Len() == 0 { + s.stateLock.Unlock() + return 0, io.EOF + } + case streamReset: + s.stateLock.Unlock() + return 0, ErrConnectionReset + } + s.stateLock.Unlock() + + // If there is no data available, block + s.recvLock.Lock() + if s.recvBuf == nil || s.recvBuf.Len() == 0 { + s.recvLock.Unlock() + goto WAIT + } + + // Read any bytes + n, _ = s.recvBuf.Read(b) + s.recvLock.Unlock() + + // Send a window update potentially + err = s.sendWindowUpdate() + return n, err + +WAIT: + var timeout <-chan time.Time + if !s.readDeadline.IsZero() { + delay := s.readDeadline.Sub(time.Now()) + timeout = time.After(delay) + } + select { + case <-s.recvNotifyCh: + goto START + case <-timeout: + return 0, ErrTimeout + } +} + +// Write is used to write to the stream +func (s *Stream) Write(b []byte) (n int, err error) { + s.sendLock.Lock() + defer s.sendLock.Unlock() + total := 0 + for total < len(b) { + n, err := s.write(b[total:]) + total += n + if err != nil { + return total, err + } + } + return total, nil +} + +// write is used to write to the stream, may return on +// a short write. +func (s *Stream) write(b []byte) (n int, err error) { + var flags uint16 + var max uint32 + var body io.Reader +START: + s.stateLock.Lock() + switch s.state { + case streamLocalClose: + fallthrough + case streamClosed: + s.stateLock.Unlock() + return 0, ErrStreamClosed + case streamReset: + s.stateLock.Unlock() + return 0, ErrConnectionReset + } + s.stateLock.Unlock() + + // If there is no data available, block + window := atomic.LoadUint32(&s.sendWindow) + if window == 0 { + goto WAIT + } + + // Determine the flags if any + flags = s.sendFlags() + + // Send up to our send window + max = min(window, uint32(len(b))) + body = bytes.NewReader(b[:max]) + + // Send the header + s.sendHdr.encode(typeData, flags, s.id, max) + if err := s.session.waitForSendErr(s.sendHdr, body, s.sendErr); err != nil { + return 0, err + } + + // Reduce our send window + atomic.AddUint32(&s.sendWindow, ^uint32(max-1)) + + // Unlock + return int(max), err + +WAIT: + var timeout <-chan time.Time + if !s.writeDeadline.IsZero() { + delay := s.writeDeadline.Sub(time.Now()) + timeout = time.After(delay) + } + select { + case <-s.sendNotifyCh: + goto START + case <-timeout: + return 0, ErrTimeout + } + return 0, nil +} + +// sendFlags determines any flags that are appropriate +// based on the current stream state +func (s *Stream) sendFlags() uint16 { + s.stateLock.Lock() + defer s.stateLock.Unlock() + var flags uint16 + switch s.state { + case streamInit: + flags |= flagSYN + s.state = streamSYNSent + case streamSYNReceived: + flags |= flagACK + s.state = streamEstablished + } + return flags +} + +// sendWindowUpdate potentially sends a window update enabling +// further writes to take place. Must be invoked with the lock. +func (s *Stream) sendWindowUpdate() error { + s.controlHdrLock.Lock() + defer s.controlHdrLock.Unlock() + + // Determine the delta update + max := s.session.config.MaxStreamWindowSize + delta := max - atomic.LoadUint32(&s.recvWindow) + + // Determine the flags if any + flags := s.sendFlags() + + // Check if we can omit the update + if delta < (max/2) && flags == 0 { + return nil + } + + // Update our window + atomic.AddUint32(&s.recvWindow, delta) + + // Send the header + s.controlHdr.encode(typeWindowUpdate, flags, s.id, delta) + if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil { + return err + } + return nil +} + +// sendClose is used to send a FIN +func (s *Stream) sendClose() error { + s.controlHdrLock.Lock() + defer s.controlHdrLock.Unlock() + + flags := s.sendFlags() + flags |= flagFIN + s.controlHdr.encode(typeWindowUpdate, flags, s.id, 0) + if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil { + return err + } + return nil +} + +// Close is used to close the stream +func (s *Stream) Close() error { + closeStream := false + s.stateLock.Lock() + switch s.state { + // Opened means we need to signal a close + case streamSYNSent: + fallthrough + case streamSYNReceived: + fallthrough + case streamEstablished: + s.state = streamLocalClose + goto SEND_CLOSE + + case streamLocalClose: + case streamRemoteClose: + s.state = streamClosed + closeStream = true + goto SEND_CLOSE + + case streamClosed: + case streamReset: + default: + panic("unhandled state") + } + s.stateLock.Unlock() + return nil +SEND_CLOSE: + s.stateLock.Unlock() + s.sendClose() + s.notifyWaiting() + if closeStream { + s.session.closeStream(s.id) + } + return nil +} + +// forceClose is used for when the session is exiting +func (s *Stream) forceClose() { + s.stateLock.Lock() + s.state = streamClosed + s.stateLock.Unlock() + s.notifyWaiting() +} + +// processFlags is used to update the state of the stream +// based on set flags, if any. Lock must be held +func (s *Stream) processFlags(flags uint16) error { + // Close the stream without holding the state lock + closeStream := false + defer func() { + if closeStream { + s.session.closeStream(s.id) + } + }() + + s.stateLock.Lock() + defer s.stateLock.Unlock() + if flags&flagACK == flagACK { + if s.state == streamSYNSent { + s.state = streamEstablished + } + s.session.establishStream() + } + if flags&flagFIN == flagFIN { + switch s.state { + case streamSYNSent: + fallthrough + case streamSYNReceived: + fallthrough + case streamEstablished: + s.state = streamRemoteClose + s.notifyWaiting() + case streamLocalClose: + s.state = streamClosed + closeStream = true + s.notifyWaiting() + default: + s.session.logger.Printf("[ERR] yamux: unexpected FIN flag in state %d", s.state) + return ErrUnexpectedFlag + } + } + if flags&flagRST == flagRST { + if s.state == streamSYNSent { + s.session.establishStream() + } + s.state = streamReset + closeStream = true + s.notifyWaiting() + } + return nil +} + +// notifyWaiting notifies all the waiting channels +func (s *Stream) notifyWaiting() { + asyncNotify(s.recvNotifyCh) + asyncNotify(s.sendNotifyCh) +} + +// incrSendWindow updates the size of our send window +func (s *Stream) incrSendWindow(hdr header, flags uint16) error { + if err := s.processFlags(flags); err != nil { + return err + } + + // Increase window, unblock a sender + atomic.AddUint32(&s.sendWindow, hdr.Length()) + asyncNotify(s.sendNotifyCh) + return nil +} + +// readData is used to handle a data frame +func (s *Stream) readData(hdr header, flags uint16, conn io.Reader) error { + if err := s.processFlags(flags); err != nil { + return err + } + + // Check that our recv window is not exceeded + length := hdr.Length() + if length == 0 { + return nil + } + if remain := atomic.LoadUint32(&s.recvWindow); length > remain { + s.session.logger.Printf("[ERR] yamux: receive window exceeded (stream: %d, remain: %d, recv: %d)", s.id, remain, length) + return ErrRecvWindowExceeded + } + + // Wrap in a limited reader + conn = &io.LimitedReader{R: conn, N: int64(length)} + + // Copy into buffer + s.recvLock.Lock() + if s.recvBuf == nil { + // Allocate the receive buffer just-in-time to fit the full data frame. + // This way we can read in the whole packet without further allocations. + s.recvBuf = bytes.NewBuffer(make([]byte, 0, length)) + } + if _, err := io.Copy(s.recvBuf, conn); err != nil { + s.session.logger.Printf("[ERR] yamux: Failed to read stream data: %v", err) + s.recvLock.Unlock() + return err + } + + // Decrement the receive window + atomic.AddUint32(&s.recvWindow, ^uint32(length-1)) + s.recvLock.Unlock() + + // Unblock any readers + asyncNotify(s.recvNotifyCh) + return nil +} + +// SetDeadline sets the read and write deadlines +func (s *Stream) SetDeadline(t time.Time) error { + if err := s.SetReadDeadline(t); err != nil { + return err + } + if err := s.SetWriteDeadline(t); err != nil { + return err + } + return nil +} + +// SetReadDeadline sets the deadline for future Read calls. +func (s *Stream) SetReadDeadline(t time.Time) error { + s.readDeadline = t + return nil +} + +// SetWriteDeadline sets the deadline for future Write calls +func (s *Stream) SetWriteDeadline(t time.Time) error { + s.writeDeadline = t + return nil +} + +// Shrink is used to compact the amount of buffers utilized +// This is useful when using Yamux in a connection pool to reduce +// the idle memory utilization. +func (s *Stream) Shrink() { + s.recvLock.Lock() + if s.recvBuf != nil && s.recvBuf.Len() == 0 { + s.recvBuf = nil + } + s.recvLock.Unlock() +} diff --git a/vendor/github.com/hashicorp/yamux/util.go b/vendor/github.com/hashicorp/yamux/util.go new file mode 100644 index 000000000..5fe45afcd --- /dev/null +++ b/vendor/github.com/hashicorp/yamux/util.go @@ -0,0 +1,28 @@ +package yamux + +// asyncSendErr is used to try an async send of an error +func asyncSendErr(ch chan error, err error) { + if ch == nil { + return + } + select { + case ch <- err: + default: + } +} + +// asyncNotify is used to signal a waiting goroutine +func asyncNotify(ch chan struct{}) { + select { + case ch <- struct{}{}: + default: + } +} + +// min computes the minimum of two values +func min(a, b uint32) uint32 { + if a < b { + return a + } + return b +} diff --git a/vendor/github.com/hpcloud/tail/LICENSE.txt b/vendor/github.com/hpcloud/tail/LICENSE.txt new file mode 100644 index 000000000..ea07fde89 --- /dev/null +++ b/vendor/github.com/hpcloud/tail/LICENSE.txt @@ -0,0 +1,23 @@ +# This is the MIT license + +# Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/Licence b/vendor/github.com/hpcloud/tail/ratelimiter/Licence new file mode 100644 index 000000000..434aab19f --- /dev/null +++ b/vendor/github.com/hpcloud/tail/ratelimiter/Licence @@ -0,0 +1,7 @@ +Copyright (C) 2013 99designs + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go b/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go new file mode 100644 index 000000000..358b69e7f --- /dev/null +++ b/vendor/github.com/hpcloud/tail/ratelimiter/leakybucket.go @@ -0,0 +1,97 @@ +// Package ratelimiter implements the Leaky Bucket ratelimiting algorithm with memcached and in-memory backends. +package ratelimiter + +import ( + "time" +) + +type LeakyBucket struct { + Size uint16 + Fill float64 + LeakInterval time.Duration // time.Duration for 1 unit of size to leak + Lastupdate time.Time + Now func() time.Time +} + +func NewLeakyBucket(size uint16, leakInterval time.Duration) *LeakyBucket { + bucket := LeakyBucket{ + Size: size, + Fill: 0, + LeakInterval: leakInterval, + Now: time.Now, + Lastupdate: time.Now(), + } + + return &bucket +} + +func (b *LeakyBucket) updateFill() { + now := b.Now() + if b.Fill > 0 { + elapsed := now.Sub(b.Lastupdate) + + b.Fill -= float64(elapsed) / float64(b.LeakInterval) + if b.Fill < 0 { + b.Fill = 0 + } + } + b.Lastupdate = now +} + +func (b *LeakyBucket) Pour(amount uint16) bool { + b.updateFill() + + var newfill float64 = b.Fill + float64(amount) + + if newfill > float64(b.Size) { + return false + } + + b.Fill = newfill + + return true +} + +// The time at which this bucket will be completely drained +func (b *LeakyBucket) DrainedAt() time.Time { + return b.Lastupdate.Add(time.Duration(b.Fill * float64(b.LeakInterval))) +} + +// The duration until this bucket is completely drained +func (b *LeakyBucket) TimeToDrain() time.Duration { + return b.DrainedAt().Sub(b.Now()) +} + +func (b *LeakyBucket) TimeSinceLastUpdate() time.Duration { + return b.Now().Sub(b.Lastupdate) +} + +type LeakyBucketSer struct { + Size uint16 + Fill float64 + LeakInterval time.Duration // time.Duration for 1 unit of size to leak + Lastupdate time.Time +} + +func (b *LeakyBucket) Serialise() *LeakyBucketSer { + bucket := LeakyBucketSer{ + Size: b.Size, + Fill: b.Fill, + LeakInterval: b.LeakInterval, + Lastupdate: b.Lastupdate, + } + + return &bucket +} + +func (b *LeakyBucketSer) DeSerialise() *LeakyBucket { + bucket := LeakyBucket{ + Size: b.Size, + Fill: b.Fill, + LeakInterval: b.LeakInterval, + Lastupdate: b.Lastupdate, + Now: time.Now, + } + + return &bucket +} diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/memory.go b/vendor/github.com/hpcloud/tail/ratelimiter/memory.go new file mode 100644 index 000000000..8f6a5784a --- /dev/null +++ b/vendor/github.com/hpcloud/tail/ratelimiter/memory.go @@ -0,0 +1,58 @@ +package ratelimiter + +import ( + "errors" + "time" +) + +const GC_SIZE int = 100 + +type Memory struct { + store map[string]LeakyBucket + lastGCCollected time.Time +} + +func NewMemory() *Memory { + m := new(Memory) + m.store = make(map[string]LeakyBucket) + m.lastGCCollected = time.Now() + return m +} + +func (m *Memory) GetBucketFor(key string) (*LeakyBucket, error) { + + bucket, ok := m.store[key] + if !ok { + return nil, errors.New("miss") + } + + return &bucket, nil +} + +func (m *Memory) SetBucketFor(key string, bucket LeakyBucket) error { + + if len(m.store) > GC_SIZE { + m.GarbageCollect() + } + + m.store[key] = bucket + + return nil +} + +func (m *Memory) GarbageCollect() { + now := time.Now() + + // rate limit GC to once per minute + if now.Add(60*time.Second).Unix() > m.lastGCCollected.Unix() { + + for key, bucket := range m.store { + // if the bucket is drained, then GC + if bucket.DrainedAt().Unix() > now.Unix() { + delete(m.store, key) + } + } + + m.lastGCCollected = now + } +} diff --git a/vendor/github.com/hpcloud/tail/ratelimiter/storage.go b/vendor/github.com/hpcloud/tail/ratelimiter/storage.go new file mode 100644 index 000000000..89b2fe882 --- /dev/null +++ b/vendor/github.com/hpcloud/tail/ratelimiter/storage.go @@ -0,0 +1,6 @@ +package ratelimiter + +type Storage interface { + GetBucketFor(string) (*LeakyBucket, error) + SetBucketFor(string, LeakyBucket) error +} diff --git a/vendor/github.com/hpcloud/tail/util/util.go b/vendor/github.com/hpcloud/tail/util/util.go new file mode 100644 index 000000000..f58b3ee9d --- /dev/null +++ b/vendor/github.com/hpcloud/tail/util/util.go @@ -0,0 +1,47 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package util + +import ( + "fmt" + "log" + "os" + "runtime/debug" +) + +type Logger struct { + *log.Logger +} + +var LOGGER = &Logger{log.New(os.Stderr, "", log.LstdFlags)} + +// fatal is like panic except it displays only the current goroutine's stack. +func Fatal(format string, v ...interface{}) { + // https://github.com/ActiveState/log/blob/master/log.go#L45 + LOGGER.Output(2, fmt.Sprintf("FATAL -- "+format, v...)+"\n"+string(debug.Stack())) + os.Exit(1) +} + +// partitionString partitions the string into chunks of given size, +// with the last chunk of variable size. +func PartitionString(s string, chunkSize int) []string { + if chunkSize <= 0 { + panic("invalid chunkSize") + } + length := len(s) + chunks := 1 + length/chunkSize + start := 0 + end := chunkSize + parts := make([]string, 0, chunks) + for { + if end > length { + end = length + } + parts = append(parts, s[start:end]) + if end == length { + break + } + start, end = end, end+chunkSize + } + return parts +} diff --git a/vendor/github.com/hpcloud/tail/watch/filechanges.go b/vendor/github.com/hpcloud/tail/watch/filechanges.go new file mode 100644 index 000000000..fb0f9ef53 --- /dev/null +++ b/vendor/github.com/hpcloud/tail/watch/filechanges.go @@ -0,0 +1,42 @@ +package watch + +type FileChanges struct { + Modified chan bool // Channel to get notified of modifications + Truncated chan bool // Channel to get notified of truncations + Deleted chan bool // Channel to get notified of deletions/renames +} + +func NewFileChanges() *FileChanges { + return &FileChanges{ + make(chan bool), make(chan bool), make(chan bool)} +} + +func (fc *FileChanges) NotifyModified() { + sendOnlyIfEmpty(fc.Modified) +} + +func (fc *FileChanges) NotifyTruncated() { + sendOnlyIfEmpty(fc.Truncated) +} + +func (fc *FileChanges) NotifyDeleted() { + sendOnlyIfEmpty(fc.Deleted) +} + +func (fc *FileChanges) Close() { + close(fc.Modified) + close(fc.Truncated) + close(fc.Deleted) +} + +// sendOnlyIfEmpty sends on a bool channel only if the channel has no +// backlog to be read by other goroutines. This concurrency pattern +// can be used to notify other goroutines if and only if they are +// looking for it (i.e., subsequent notifications can be compressed +// into one). +func sendOnlyIfEmpty(ch chan bool) { + select { + case ch <- true: + default: + } +} diff --git a/vendor/github.com/hpcloud/tail/watch/inotify.go b/vendor/github.com/hpcloud/tail/watch/inotify.go new file mode 100644 index 000000000..58efc10a3 --- /dev/null +++ b/vendor/github.com/hpcloud/tail/watch/inotify.go @@ -0,0 +1,119 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/hpcloud/tail/util" + + "gopkg.in/fsnotify.v1" + "gopkg.in/tomb.v1" +) + +// InotifyFileWatcher uses inotify to monitor file changes. +type InotifyFileWatcher struct { + Filename string + Size int64 +} + +func NewInotifyFileWatcher(filename string) *InotifyFileWatcher { + fw := &InotifyFileWatcher{filepath.Clean(filename), 0} + return fw +} + +func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error { + err := WatchCreate(fw.Filename) + if err != nil { + return err + } + defer RemoveWatchCreate(fw.Filename) + + // Do a real check now as the file might have been created before + // calling `WatchFlags` above. + if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) { + // file exists, or stat returned an error. + return err + } + + events := Events(fw.Filename) + + for { + select { + case evt, ok := <-events: + if !ok { + return fmt.Errorf("inotify watcher has been closed") + } else if filepath.Clean(evt.Name) == fw.Filename { + return nil + } + case <-t.Dying(): + return tomb.ErrDying + } + } + panic("unreachable") +} + +func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { + err := Watch(fw.Filename) + if err != nil { + return nil, err + } + + changes := NewFileChanges() + fw.Size = pos + + go func() { + defer RemoveWatch(fw.Filename) + defer changes.Close() + + events := Events(fw.Filename) + + for { + prevSize := fw.Size + + var evt fsnotify.Event + var ok bool + + select { + case evt, ok = <-events: + if !ok { + return + } + case <-t.Dying(): + return + } + + switch { + case evt.Op&fsnotify.Remove == fsnotify.Remove: + fallthrough + + case evt.Op&fsnotify.Rename == fsnotify.Rename: + changes.NotifyDeleted() + return + + case evt.Op&fsnotify.Write == fsnotify.Write: + fi, err := os.Stat(fw.Filename) + if err != nil { + if os.IsNotExist(err) { + changes.NotifyDeleted() + return + } + // XXX: report this error back to the user + util.Fatal("Failed to stat file %v: %v", fw.Filename, err) + } + fw.Size = fi.Size() + + if prevSize > 0 && prevSize > fw.Size { + changes.NotifyTruncated() + } else { + changes.NotifyModified() + } + prevSize = fw.Size + } + } + }() + + return changes, nil +} diff --git a/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go b/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go new file mode 100644 index 000000000..f53f2c30d --- /dev/null +++ b/vendor/github.com/hpcloud/tail/watch/inotify_tracker.go @@ -0,0 +1,254 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "log" + "os" + "path/filepath" + "sync" + "syscall" + + "github.com/hpcloud/tail/util" + + "gopkg.in/fsnotify.v1" +) + +type InotifyTracker struct { + mux sync.Mutex + watcher *fsnotify.Watcher + chans map[string]chan fsnotify.Event + done map[string]chan bool + watchNums map[string]int + watch chan *watchInfo + remove chan *watchInfo + error chan error +} + +type watchInfo struct { + op fsnotify.Op + fname string +} + +func (this *watchInfo) isCreate() bool { + return this.op == fsnotify.Create +} + +var ( + // globally shared InotifyTracker; ensures only one fsnotify.Watcher is used + shared *InotifyTracker + + // these are used to ensure the shared InotifyTracker is run exactly once + once = sync.Once{} + goRun = func() { + shared = &InotifyTracker{ + mux: sync.Mutex{}, + chans: make(map[string]chan fsnotify.Event), + done: make(map[string]chan bool), + watchNums: make(map[string]int), + watch: make(chan *watchInfo), + remove: make(chan *watchInfo), + error: make(chan error), + } + go shared.run() + } + + logger = log.New(os.Stderr, "", log.LstdFlags) +) + +// Watch signals the run goroutine to begin watching the input filename +func Watch(fname string) error { + return watch(&watchInfo{ + fname: fname, + }) +} + +// Watch create signals the run goroutine to begin watching the input filename +// if call the WatchCreate function, don't call the Cleanup, call the RemoveWatchCreate +func WatchCreate(fname string) error { + return watch(&watchInfo{ + op: fsnotify.Create, + fname: fname, + }) +} + +func watch(winfo *watchInfo) error { + // start running the shared InotifyTracker if not already running + once.Do(goRun) + + winfo.fname = filepath.Clean(winfo.fname) + shared.watch <- winfo + return <-shared.error +} + +// RemoveWatch signals the run goroutine to remove the watch for the input filename +func RemoveWatch(fname string) { + remove(&watchInfo{ + fname: fname, + }) +} + +// RemoveWatch create signals the run goroutine to remove the watch for the input filename +func RemoveWatchCreate(fname string) { + remove(&watchInfo{ + op: fsnotify.Create, + fname: fname, + }) +} + +func remove(winfo *watchInfo) { + // start running the shared InotifyTracker if not already running + once.Do(goRun) + + winfo.fname = filepath.Clean(winfo.fname) + shared.mux.Lock() + done := shared.done[winfo.fname] + if done != nil { + delete(shared.done, winfo.fname) + close(done) + } + shared.mux.Unlock() + + shared.remove <- winfo +} + +// Events returns a channel to which FileEvents corresponding to the input filename +// will be sent. This channel will be closed when removeWatch is called on this +// filename. +func Events(fname string) chan fsnotify.Event { + shared.mux.Lock() + defer shared.mux.Unlock() + + return shared.chans[fname] +} + +// Cleanup removes the watch for the input filename if necessary. +func Cleanup(fname string) { + RemoveWatch(fname) +} + +// watchFlags calls fsnotify.WatchFlags for the input filename and flags, creating +// a new Watcher if the previous Watcher was closed. +func (shared *InotifyTracker) addWatch(winfo *watchInfo) error { + shared.mux.Lock() + defer shared.mux.Unlock() + + if shared.chans[winfo.fname] == nil { + shared.chans[winfo.fname] = make(chan fsnotify.Event) + shared.done[winfo.fname] = make(chan bool) + } + + fname := winfo.fname + if winfo.isCreate() { + // Watch for new files to be created in the parent directory. + fname = filepath.Dir(fname) + } + + // already in inotify watch + if shared.watchNums[fname] > 0 { + shared.watchNums[fname]++ + if winfo.isCreate() { + shared.watchNums[winfo.fname]++ + } + return nil + } + + err := shared.watcher.Add(fname) + if err == nil { + shared.watchNums[fname]++ + if winfo.isCreate() { + shared.watchNums[winfo.fname]++ + } + } + return err +} + +// removeWatch calls fsnotify.RemoveWatch for the input filename and closes the +// corresponding events channel. +func (shared *InotifyTracker) removeWatch(winfo *watchInfo) { + shared.mux.Lock() + defer shared.mux.Unlock() + + ch := shared.chans[winfo.fname] + if ch == nil { + return + } + + fname := winfo.fname + if winfo.isCreate() { + // Watch for new files to be created in the parent directory. + fname = filepath.Dir(fname) + } + + shared.watchNums[fname]-- + if shared.watchNums[fname] == 0 { + delete(shared.watchNums, fname) + // TODO: handle error + shared.watcher.Remove(fname) + } + + delete(shared.chans, winfo.fname) + close(ch) + + if !winfo.isCreate() { + return + } + + shared.watchNums[winfo.fname]-- + if shared.watchNums[winfo.fname] == 0 { + delete(shared.watchNums, winfo.fname) + } +} + +// sendEvent sends the input event to the appropriate Tail. +func (shared *InotifyTracker) sendEvent(event fsnotify.Event) { + name := filepath.Clean(event.Name) + + shared.mux.Lock() + ch := shared.chans[name] + done := shared.done[name] + shared.mux.Unlock() + + if ch != nil && done != nil { + select { + case ch <- event: + case <-done: + } + } +} + +// run starts the goroutine in which the shared struct reads events from its +// Watcher's Event channel and sends the events to the appropriate Tail. +func (shared *InotifyTracker) run() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + util.Fatal("failed to create Watcher") + } + shared.watcher = watcher + + for { + select { + case winfo := <-shared.watch: + shared.error <- shared.addWatch(winfo) + + case winfo := <-shared.remove: + shared.removeWatch(winfo) + + case event, open := <-shared.watcher.Events: + if !open { + return + } + shared.sendEvent(event) + + case err, open := <-shared.watcher.Errors: + if !open { + return + } else if err != nil { + sysErr, ok := err.(*os.SyscallError) + if !ok || sysErr.Err != syscall.EINTR { + logger.Printf("Error in Watcher Error channel: %s", err) + } + } + } + } +} diff --git a/vendor/github.com/hpcloud/tail/watch/polling.go b/vendor/github.com/hpcloud/tail/watch/polling.go new file mode 100644 index 000000000..33b8b4db1 --- /dev/null +++ b/vendor/github.com/hpcloud/tail/watch/polling.go @@ -0,0 +1,119 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import ( + "os" + "runtime" + "time" + + "github.com/hpcloud/tail/util" + "gopkg.in/tomb.v1" +) + +// PollingFileWatcher polls the file for changes. +type PollingFileWatcher struct { + Filename string + Size int64 +} + +func NewPollingFileWatcher(filename string) *PollingFileWatcher { + fw := &PollingFileWatcher{filename, 0} + return fw +} + +var POLL_DURATION time.Duration + +func (fw *PollingFileWatcher) BlockUntilExists(t *tomb.Tomb) error { + for { + if _, err := os.Stat(fw.Filename); err == nil { + return nil + } else if !os.IsNotExist(err) { + return err + } + select { + case <-time.After(POLL_DURATION): + continue + case <-t.Dying(): + return tomb.ErrDying + } + } + panic("unreachable") +} + +func (fw *PollingFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) { + origFi, err := os.Stat(fw.Filename) + if err != nil { + return nil, err + } + + changes := NewFileChanges() + var prevModTime time.Time + + // XXX: use tomb.Tomb to cleanly manage these goroutines. replace + // the fatal (below) with tomb's Kill. + + fw.Size = pos + + go func() { + defer changes.Close() + + prevSize := fw.Size + for { + select { + case <-t.Dying(): + return + default: + } + + time.Sleep(POLL_DURATION) + fi, err := os.Stat(fw.Filename) + if err != nil { + // Windows cannot delete a file if a handle is still open (tail keeps one open) + // so it gives access denied to anything trying to read it until all handles are released. + if os.IsNotExist(err) || (runtime.GOOS == "windows" && os.IsPermission(err)) { + // File does not exist (has been deleted). + changes.NotifyDeleted() + return + } + + // XXX: report this error back to the user + util.Fatal("Failed to stat file %v: %v", fw.Filename, err) + } + + // File got moved/renamed? + if !os.SameFile(origFi, fi) { + changes.NotifyDeleted() + return + } + + // File got truncated? + fw.Size = fi.Size() + if prevSize > 0 && prevSize > fw.Size { + changes.NotifyTruncated() + prevSize = fw.Size + continue + } + // File got bigger? + if prevSize > 0 && prevSize < fw.Size { + changes.NotifyModified() + prevSize = fw.Size + continue + } + prevSize = fw.Size + + // File was appended to (changed)? + modTime := fi.ModTime() + if modTime != prevModTime { + prevModTime = modTime + changes.NotifyModified() + } + } + }() + + return changes, nil +} + +func init() { + POLL_DURATION = 250 * time.Millisecond +} diff --git a/vendor/github.com/hpcloud/tail/watch/watch.go b/vendor/github.com/hpcloud/tail/watch/watch.go new file mode 100644 index 000000000..05baea10f --- /dev/null +++ b/vendor/github.com/hpcloud/tail/watch/watch.go @@ -0,0 +1,19 @@ +// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. + +package watch + +import "gopkg.in/tomb.v1" + +// FileWatcher monitors file-level events. +type FileWatcher interface { + // BlockUntilExists blocks until the file comes into existence. + BlockUntilExists(*tomb.Tomb) error + + // ChangeEvents reports on changes to a file, be it modification, + // deletion, renames or truncations. Returned FileChanges group of + // channels will be closed, thus become unusable, after a deletion + // or truncation event. + // In order to properly report truncations, ChangeEvents requires + // the caller to pass their current offset in the file. + ChangeEvents(*tomb.Tomb, int64) (*FileChanges, error) +} diff --git a/vendor/github.com/hpcloud/tail/winfile/winfile.go b/vendor/github.com/hpcloud/tail/winfile/winfile.go new file mode 100644 index 000000000..aa7e7bc5d --- /dev/null +++ b/vendor/github.com/hpcloud/tail/winfile/winfile.go @@ -0,0 +1,92 @@ +// +build windows + +package winfile + +import ( + "os" + "syscall" + "unsafe" +) + +// issue also described here +//https://codereview.appspot.com/8203043/ + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L218 +func Open(path string, mode int, perm uint32) (fd syscall.Handle, err error) { + if len(path) == 0 { + return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return syscall.InvalidHandle, err + } + var access uint32 + switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) { + case syscall.O_RDONLY: + access = syscall.GENERIC_READ + case syscall.O_WRONLY: + access = syscall.GENERIC_WRITE + case syscall.O_RDWR: + access = syscall.GENERIC_READ | syscall.GENERIC_WRITE + } + if mode&syscall.O_CREAT != 0 { + access |= syscall.GENERIC_WRITE + } + if mode&syscall.O_APPEND != 0 { + access &^= syscall.GENERIC_WRITE + access |= syscall.FILE_APPEND_DATA + } + sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE) + var sa *syscall.SecurityAttributes + if mode&syscall.O_CLOEXEC == 0 { + sa = makeInheritSa() + } + var createmode uint32 + switch { + case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL): + createmode = syscall.CREATE_NEW + case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC): + createmode = syscall.CREATE_ALWAYS + case mode&syscall.O_CREAT == syscall.O_CREAT: + createmode = syscall.OPEN_ALWAYS + case mode&syscall.O_TRUNC == syscall.O_TRUNC: + createmode = syscall.TRUNCATE_EXISTING + default: + createmode = syscall.OPEN_EXISTING + } + h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0) + return h, e +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L211 +func makeInheritSa() *syscall.SecurityAttributes { + var sa syscall.SecurityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + sa.InheritHandle = 1 + return &sa +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_windows.go#L133 +func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { + r, e := Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) + if e != nil { + return nil, e + } + return os.NewFile(uintptr(r), name), nil +} + +// https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_posix.go#L61 +func syscallMode(i os.FileMode) (o uint32) { + o |= uint32(i.Perm()) + if i&os.ModeSetuid != 0 { + o |= syscall.S_ISUID + } + if i&os.ModeSetgid != 0 { + o |= syscall.S_ISGID + } + if i&os.ModeSticky != 0 { + o |= syscall.S_ISVTX + } + // No mapping for Go's ModeTemporary (plan9 only). + return +} diff --git a/vendor/github.com/jmespath/go-jmespath/.gitignore b/vendor/github.com/jmespath/go-jmespath/.gitignore new file mode 100644 index 000000000..531fcc11c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/.gitignore @@ -0,0 +1,4 @@ +jpgo +jmespath-fuzz.zip +cpu.out +go-jmespath.test diff --git a/vendor/github.com/jmespath/go-jmespath/.travis.yml b/vendor/github.com/jmespath/go-jmespath/.travis.yml new file mode 100644 index 000000000..1f9807757 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/.travis.yml @@ -0,0 +1,9 @@ +language: go + +sudo: false + +go: + - 1.4 + +install: go get -v -t ./... +script: make test diff --git a/vendor/github.com/jmespath/go-jmespath/LICENSE b/vendor/github.com/jmespath/go-jmespath/LICENSE new file mode 100644 index 000000000..b03310a91 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/LICENSE @@ -0,0 +1,13 @@ +Copyright 2015 James Saryerwinnie + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/jmespath/go-jmespath/Makefile b/vendor/github.com/jmespath/go-jmespath/Makefile new file mode 100644 index 000000000..ad17bf001 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/Makefile @@ -0,0 +1,44 @@ + +CMD = jpgo + +help: + @echo "Please use \`make ' where is one of" + @echo " test to run all the tests" + @echo " build to build the library and jp executable" + @echo " generate to run codegen" + + +generate: + go generate ./... + +build: + rm -f $(CMD) + go build ./... + rm -f cmd/$(CMD)/$(CMD) && cd cmd/$(CMD)/ && go build ./... + mv cmd/$(CMD)/$(CMD) . + +test: + go test -v ./... + +check: + go vet ./... + @echo "golint ./..." + @lint=`golint ./...`; \ + lint=`echo "$$lint" | grep -v "astnodetype_string.go" | grep -v "toktype_string.go"`; \ + echo "$$lint"; \ + if [ "$$lint" != "" ]; then exit 1; fi + +htmlc: + go test -coverprofile="/tmp/jpcov" && go tool cover -html="/tmp/jpcov" && unlink /tmp/jpcov + +buildfuzz: + go-fuzz-build github.com/jmespath/go-jmespath/fuzz + +fuzz: buildfuzz + go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/corpus + +bench: + go test -bench . -cpuprofile cpu.out + +pprof-cpu: + go tool pprof ./go-jmespath.test ./cpu.out diff --git a/vendor/github.com/jmespath/go-jmespath/README.md b/vendor/github.com/jmespath/go-jmespath/README.md new file mode 100644 index 000000000..187ef676d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/README.md @@ -0,0 +1,7 @@ +# go-jmespath - A JMESPath implementation in Go + +[![Build Status](https://img.shields.io/travis/jmespath/go-jmespath.svg)](https://travis-ci.org/jmespath/go-jmespath) + + + +See http://jmespath.org for more info. diff --git a/vendor/github.com/jmespath/go-jmespath/api.go b/vendor/github.com/jmespath/go-jmespath/api.go new file mode 100644 index 000000000..9cfa988bc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/api.go @@ -0,0 +1,49 @@ +package jmespath + +import "strconv" + +// JmesPath is the epresentation of a compiled JMES path query. A JmesPath is +// safe for concurrent use by multiple goroutines. +type JMESPath struct { + ast ASTNode + intr *treeInterpreter +} + +// Compile parses a JMESPath expression and returns, if successful, a JMESPath +// object that can be used to match against data. +func Compile(expression string) (*JMESPath, error) { + parser := NewParser() + ast, err := parser.Parse(expression) + if err != nil { + return nil, err + } + jmespath := &JMESPath{ast: ast, intr: newInterpreter()} + return jmespath, nil +} + +// MustCompile is like Compile but panics if the expression cannot be parsed. +// It simplifies safe initialization of global variables holding compiled +// JMESPaths. +func MustCompile(expression string) *JMESPath { + jmespath, err := Compile(expression) + if err != nil { + panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error()) + } + return jmespath +} + +// Search evaluates a JMESPath expression against input data and returns the result. +func (jp *JMESPath) Search(data interface{}) (interface{}, error) { + return jp.intr.Execute(jp.ast, data) +} + +// Search evaluates a JMESPath expression against input data and returns the result. +func Search(expression string, data interface{}) (interface{}, error) { + intr := newInterpreter() + parser := NewParser() + ast, err := parser.Parse(expression) + if err != nil { + return nil, err + } + return intr.Execute(ast, data) +} diff --git a/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go new file mode 100644 index 000000000..1cd2d239c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type astNodeType; DO NOT EDIT + +package jmespath + +import "fmt" + +const _astNodeType_name = "ASTEmptyASTComparatorASTCurrentNodeASTExpRefASTFunctionExpressionASTFieldASTFilterProjectionASTFlattenASTIdentityASTIndexASTIndexExpressionASTKeyValPairASTLiteralASTMultiSelectHashASTMultiSelectListASTOrExpressionASTAndExpressionASTNotExpressionASTPipeASTProjectionASTSubexpressionASTSliceASTValueProjection" + +var _astNodeType_index = [...]uint16{0, 8, 21, 35, 44, 65, 73, 92, 102, 113, 121, 139, 152, 162, 180, 198, 213, 229, 245, 252, 265, 281, 289, 307} + +func (i astNodeType) String() string { + if i < 0 || i >= astNodeType(len(_astNodeType_index)-1) { + return fmt.Sprintf("astNodeType(%d)", i) + } + return _astNodeType_name[_astNodeType_index[i]:_astNodeType_index[i+1]] +} diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/basic.json b/vendor/github.com/jmespath/go-jmespath/compliance/basic.json new file mode 100644 index 000000000..d550e9695 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/basic.json @@ -0,0 +1,96 @@ +[{ + "given": + {"foo": {"bar": {"baz": "correct"}}}, + "cases": [ + { + "expression": "foo", + "result": {"bar": {"baz": "correct"}} + }, + { + "expression": "foo.bar", + "result": {"baz": "correct"} + }, + { + "expression": "foo.bar.baz", + "result": "correct" + }, + { + "expression": "foo\n.\nbar\n.baz", + "result": "correct" + }, + { + "expression": "foo.bar.baz.bad", + "result": null + }, + { + "expression": "foo.bar.bad", + "result": null + }, + { + "expression": "foo.bad", + "result": null + }, + { + "expression": "bad", + "result": null + }, + { + "expression": "bad.morebad.morebad", + "result": null + } + ] +}, +{ + "given": + {"foo": {"bar": ["one", "two", "three"]}}, + "cases": [ + { + "expression": "foo", + "result": {"bar": ["one", "two", "three"]} + }, + { + "expression": "foo.bar", + "result": ["one", "two", "three"] + } + ] +}, +{ + "given": ["one", "two", "three"], + "cases": [ + { + "expression": "one", + "result": null + }, + { + "expression": "two", + "result": null + }, + { + "expression": "three", + "result": null + }, + { + "expression": "one.two", + "result": null + } + ] +}, +{ + "given": + {"foo": {"1": ["one", "two", "three"], "-1": "bar"}}, + "cases": [ + { + "expression": "foo.\"1\"", + "result": ["one", "two", "three"] + }, + { + "expression": "foo.\"1\"[0]", + "result": "one" + }, + { + "expression": "foo.\"-1\"", + "result": "bar" + } + ] +} +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/boolean.json b/vendor/github.com/jmespath/go-jmespath/compliance/boolean.json new file mode 100644 index 000000000..e3fa196b1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/boolean.json @@ -0,0 +1,257 @@ +[ + { + "given": { + "outer": { + "foo": "foo", + "bar": "bar", + "baz": "baz" + } + }, + "cases": [ + { + "expression": "outer.foo || outer.bar", + "result": "foo" + }, + { + "expression": "outer.foo||outer.bar", + "result": "foo" + }, + { + "expression": "outer.bar || outer.baz", + "result": "bar" + }, + { + "expression": "outer.bar||outer.baz", + "result": "bar" + }, + { + "expression": "outer.bad || outer.foo", + "result": "foo" + }, + { + "expression": "outer.bad||outer.foo", + "result": "foo" + }, + { + "expression": "outer.foo || outer.bad", + "result": "foo" + }, + { + "expression": "outer.foo||outer.bad", + "result": "foo" + }, + { + "expression": "outer.bad || outer.alsobad", + "result": null + }, + { + "expression": "outer.bad||outer.alsobad", + "result": null + } + ] + }, + { + "given": { + "outer": { + "foo": "foo", + "bool": false, + "empty_list": [], + "empty_string": "" + } + }, + "cases": [ + { + "expression": "outer.empty_string || outer.foo", + "result": "foo" + }, + { + "expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo", + "result": "foo" + } + ] + }, + { + "given": { + "True": true, + "False": false, + "Number": 5, + "EmptyList": [], + "Zero": 0 + }, + "cases": [ + { + "expression": "True && False", + "result": false + }, + { + "expression": "False && True", + "result": false + }, + { + "expression": "True && True", + "result": true + }, + { + "expression": "False && False", + "result": false + }, + { + "expression": "True && Number", + "result": 5 + }, + { + "expression": "Number && True", + "result": true + }, + { + "expression": "Number && False", + "result": false + }, + { + "expression": "Number && EmptyList", + "result": [] + }, + { + "expression": "Number && True", + "result": true + }, + { + "expression": "EmptyList && True", + "result": [] + }, + { + "expression": "EmptyList && False", + "result": [] + }, + { + "expression": "True || False", + "result": true + }, + { + "expression": "True || True", + "result": true + }, + { + "expression": "False || True", + "result": true + }, + { + "expression": "False || False", + "result": false + }, + { + "expression": "Number || EmptyList", + "result": 5 + }, + { + "expression": "Number || True", + "result": 5 + }, + { + "expression": "Number || True && False", + "result": 5 + }, + { + "expression": "(Number || True) && False", + "result": false + }, + { + "expression": "Number || (True && False)", + "result": 5 + }, + { + "expression": "!True", + "result": false + }, + { + "expression": "!False", + "result": true + }, + { + "expression": "!Number", + "result": false + }, + { + "expression": "!EmptyList", + "result": true + }, + { + "expression": "True && !False", + "result": true + }, + { + "expression": "True && !EmptyList", + "result": true + }, + { + "expression": "!False && !EmptyList", + "result": true + }, + { + "expression": "!(True && False)", + "result": true + }, + { + "expression": "!Zero", + "result": false + }, + { + "expression": "!!Zero", + "result": true + } + ] + }, + { + "given": { + "one": 1, + "two": 2, + "three": 3 + }, + "cases": [ + { + "expression": "one < two", + "result": true + }, + { + "expression": "one <= two", + "result": true + }, + { + "expression": "one == one", + "result": true + }, + { + "expression": "one == two", + "result": false + }, + { + "expression": "one > two", + "result": false + }, + { + "expression": "one >= two", + "result": false + }, + { + "expression": "one != two", + "result": true + }, + { + "expression": "one < two && three > one", + "result": true + }, + { + "expression": "one < two || three > one", + "result": true + }, + { + "expression": "one < two || three < one", + "result": true + }, + { + "expression": "two < one || three < one", + "result": false + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/current.json b/vendor/github.com/jmespath/go-jmespath/compliance/current.json new file mode 100644 index 000000000..0c26248d0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/current.json @@ -0,0 +1,25 @@ +[ + { + "given": { + "foo": [{"name": "a"}, {"name": "b"}], + "bar": {"baz": "qux"} + }, + "cases": [ + { + "expression": "@", + "result": { + "foo": [{"name": "a"}, {"name": "b"}], + "bar": {"baz": "qux"} + } + }, + { + "expression": "@.bar", + "result": {"baz": "qux"} + }, + { + "expression": "@.foo[0]", + "result": {"name": "a"} + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/escape.json b/vendor/github.com/jmespath/go-jmespath/compliance/escape.json new file mode 100644 index 000000000..4a62d951a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/escape.json @@ -0,0 +1,46 @@ +[{ + "given": { + "foo.bar": "dot", + "foo bar": "space", + "foo\nbar": "newline", + "foo\"bar": "doublequote", + "c:\\\\windows\\path": "windows", + "/unix/path": "unix", + "\"\"\"": "threequotes", + "bar": {"baz": "qux"} + }, + "cases": [ + { + "expression": "\"foo.bar\"", + "result": "dot" + }, + { + "expression": "\"foo bar\"", + "result": "space" + }, + { + "expression": "\"foo\\nbar\"", + "result": "newline" + }, + { + "expression": "\"foo\\\"bar\"", + "result": "doublequote" + }, + { + "expression": "\"c:\\\\\\\\windows\\\\path\"", + "result": "windows" + }, + { + "expression": "\"/unix/path\"", + "result": "unix" + }, + { + "expression": "\"\\\"\\\"\\\"\"", + "result": "threequotes" + }, + { + "expression": "\"bar\".\"baz\"", + "result": "qux" + } + ] +}] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/filters.json b/vendor/github.com/jmespath/go-jmespath/compliance/filters.json new file mode 100644 index 000000000..5b9f52b11 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/filters.json @@ -0,0 +1,468 @@ +[ + { + "given": {"foo": [{"name": "a"}, {"name": "b"}]}, + "cases": [ + { + "comment": "Matching a literal", + "expression": "foo[?name == 'a']", + "result": [{"name": "a"}] + } + ] + }, + { + "given": {"foo": [0, 1], "bar": [2, 3]}, + "cases": [ + { + "comment": "Matching a literal", + "expression": "*[?[0] == `0`]", + "result": [[], []] + } + ] + }, + { + "given": {"foo": [{"first": "foo", "last": "bar"}, + {"first": "foo", "last": "foo"}, + {"first": "foo", "last": "baz"}]}, + "cases": [ + { + "comment": "Matching an expression", + "expression": "foo[?first == last]", + "result": [{"first": "foo", "last": "foo"}] + }, + { + "comment": "Verify projection created from filter", + "expression": "foo[?first == last].first", + "result": ["foo"] + } + ] + }, + { + "given": {"foo": [{"age": 20}, + {"age": 25}, + {"age": 30}]}, + "cases": [ + { + "comment": "Greater than with a number", + "expression": "foo[?age > `25`]", + "result": [{"age": 30}] + }, + { + "expression": "foo[?age >= `25`]", + "result": [{"age": 25}, {"age": 30}] + }, + { + "comment": "Greater than with a number", + "expression": "foo[?age > `30`]", + "result": [] + }, + { + "comment": "Greater than with a number", + "expression": "foo[?age < `25`]", + "result": [{"age": 20}] + }, + { + "comment": "Greater than with a number", + "expression": "foo[?age <= `25`]", + "result": [{"age": 20}, {"age": 25}] + }, + { + "comment": "Greater than with a number", + "expression": "foo[?age < `20`]", + "result": [] + }, + { + "expression": "foo[?age == `20`]", + "result": [{"age": 20}] + }, + { + "expression": "foo[?age != `20`]", + "result": [{"age": 25}, {"age": 30}] + } + ] + }, + { + "given": {"foo": [{"top": {"name": "a"}}, + {"top": {"name": "b"}}]}, + "cases": [ + { + "comment": "Filter with subexpression", + "expression": "foo[?top.name == 'a']", + "result": [{"top": {"name": "a"}}] + } + ] + }, + { + "given": {"foo": [{"top": {"first": "foo", "last": "bar"}}, + {"top": {"first": "foo", "last": "foo"}}, + {"top": {"first": "foo", "last": "baz"}}]}, + "cases": [ + { + "comment": "Matching an expression", + "expression": "foo[?top.first == top.last]", + "result": [{"top": {"first": "foo", "last": "foo"}}] + }, + { + "comment": "Matching a JSON array", + "expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]", + "result": [{"top": {"first": "foo", "last": "bar"}}] + } + ] + }, + { + "given": {"foo": [ + {"key": true}, + {"key": false}, + {"key": 0}, + {"key": 1}, + {"key": [0]}, + {"key": {"bar": [0]}}, + {"key": null}, + {"key": [1]}, + {"key": {"a":2}} + ]}, + "cases": [ + { + "expression": "foo[?key == `true`]", + "result": [{"key": true}] + }, + { + "expression": "foo[?key == `false`]", + "result": [{"key": false}] + }, + { + "expression": "foo[?key == `0`]", + "result": [{"key": 0}] + }, + { + "expression": "foo[?key == `1`]", + "result": [{"key": 1}] + }, + { + "expression": "foo[?key == `[0]`]", + "result": [{"key": [0]}] + }, + { + "expression": "foo[?key == `{\"bar\": [0]}`]", + "result": [{"key": {"bar": [0]}}] + }, + { + "expression": "foo[?key == `null`]", + "result": [{"key": null}] + }, + { + "expression": "foo[?key == `[1]`]", + "result": [{"key": [1]}] + }, + { + "expression": "foo[?key == `{\"a\":2}`]", + "result": [{"key": {"a":2}}] + }, + { + "expression": "foo[?`true` == key]", + "result": [{"key": true}] + }, + { + "expression": "foo[?`false` == key]", + "result": [{"key": false}] + }, + { + "expression": "foo[?`0` == key]", + "result": [{"key": 0}] + }, + { + "expression": "foo[?`1` == key]", + "result": [{"key": 1}] + }, + { + "expression": "foo[?`[0]` == key]", + "result": [{"key": [0]}] + }, + { + "expression": "foo[?`{\"bar\": [0]}` == key]", + "result": [{"key": {"bar": [0]}}] + }, + { + "expression": "foo[?`null` == key]", + "result": [{"key": null}] + }, + { + "expression": "foo[?`[1]` == key]", + "result": [{"key": [1]}] + }, + { + "expression": "foo[?`{\"a\":2}` == key]", + "result": [{"key": {"a":2}}] + }, + { + "expression": "foo[?key != `true`]", + "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `false`]", + "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `0`]", + "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `1`]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `null`]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `[1]`]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}] + }, + { + "expression": "foo[?key != `{\"a\":2}`]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}] + }, + { + "expression": "foo[?`true` != key]", + "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`false` != key]", + "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`0` != key]", + "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`1` != key]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`null` != key]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`[1]` != key]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}] + }, + { + "expression": "foo[?`{\"a\":2}` != key]", + "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]}, + {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}] + } + ] + }, + { + "given": {"reservations": [ + {"instances": [ + {"foo": 1, "bar": 2}, {"foo": 1, "bar": 3}, + {"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]}, + "cases": [ + { + "expression": "reservations[].instances[?bar==`1`]", + "result": [[{"foo": 2, "bar": 1}]] + }, + { + "expression": "reservations[*].instances[?bar==`1`]", + "result": [[{"foo": 2, "bar": 1}]] + }, + { + "expression": "reservations[].instances[?bar==`1`][]", + "result": [{"foo": 2, "bar": 1}] + } + ] + }, + { + "given": { + "baz": "other", + "foo": [ + {"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2} + ] + }, + "cases": [ + { + "expression": "foo[?bar==`1`].bar[0]", + "result": [] + } + ] + }, + { + "given": { + "foo": [ + {"a": 1, "b": {"c": "x"}}, + {"a": 1, "b": {"c": "y"}}, + {"a": 1, "b": {"c": "z"}}, + {"a": 2, "b": {"c": "z"}}, + {"a": 1, "baz": 2} + ] + }, + "cases": [ + { + "expression": "foo[?a==`1`].b.c", + "result": ["x", "y", "z"] + } + ] + }, + { + "given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]}, + "cases": [ + { + "comment": "Filter with or expression", + "expression": "foo[?name == 'a' || name == 'b']", + "result": [{"name": "a"}, {"name": "b"}] + }, + { + "expression": "foo[?name == 'a' || name == 'e']", + "result": [{"name": "a"}] + }, + { + "expression": "foo[?name == 'a' || name == 'b' || name == 'c']", + "result": [{"name": "a"}, {"name": "b"}, {"name": "c"}] + } + ] + }, + { + "given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]}, + "cases": [ + { + "comment": "Filter with and expression", + "expression": "foo[?a == `1` && b == `2`]", + "result": [{"a": 1, "b": 2}] + }, + { + "expression": "foo[?a == `1` && b == `4`]", + "result": [] + } + ] + }, + { + "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]}, + "cases": [ + { + "comment": "Filter with Or and And expressions", + "expression": "foo[?c == `3` || a == `1` && b == `4`]", + "result": [{"a": 1, "b": 2, "c": 3}] + }, + { + "expression": "foo[?b == `2` || a == `3` && b == `4`]", + "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}] + }, + { + "expression": "foo[?a == `3` && b == `4` || b == `2`]", + "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}] + }, + { + "expression": "foo[?(a == `3` && b == `4`) || b == `2`]", + "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}] + }, + { + "expression": "foo[?((a == `3` && b == `4`)) || b == `2`]", + "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}] + }, + { + "expression": "foo[?a == `3` && (b == `4` || b == `2`)]", + "result": [{"a": 3, "b": 4}] + }, + { + "expression": "foo[?a == `3` && ((b == `4` || b == `2`))]", + "result": [{"a": 3, "b": 4}] + } + ] + }, + { + "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]}, + "cases": [ + { + "comment": "Verify precedence of or/and expressions", + "expression": "foo[?a == `1` || b ==`2` && c == `5`]", + "result": [{"a": 1, "b": 2, "c": 3}] + }, + { + "comment": "Parentheses can alter precedence", + "expression": "foo[?(a == `1` || b ==`2`) && c == `5`]", + "result": [] + }, + { + "comment": "Not expressions combined with and/or", + "expression": "foo[?!(a == `1` || b ==`2`)]", + "result": [{"a": 3, "b": 4}] + } + ] + }, + { + "given": { + "foo": [ + {"key": true}, + {"key": false}, + {"key": []}, + {"key": {}}, + {"key": [0]}, + {"key": {"a": "b"}}, + {"key": 0}, + {"key": 1}, + {"key": null}, + {"notkey": true} + ] + }, + "cases": [ + { + "comment": "Unary filter expression", + "expression": "foo[?key]", + "result": [ + {"key": true}, {"key": [0]}, {"key": {"a": "b"}}, + {"key": 0}, {"key": 1} + ] + }, + { + "comment": "Unary not filter expression", + "expression": "foo[?!key]", + "result": [ + {"key": false}, {"key": []}, {"key": {}}, + {"key": null}, {"notkey": true} + ] + }, + { + "comment": "Equality with null RHS", + "expression": "foo[?key == `null`]", + "result": [ + {"key": null}, {"notkey": true} + ] + } + ] + }, + { + "given": { + "foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + "cases": [ + { + "comment": "Using @ in a filter expression", + "expression": "foo[?@ < `5`]", + "result": [0, 1, 2, 3, 4] + }, + { + "comment": "Using @ in a filter expression", + "expression": "foo[?`5` > @]", + "result": [0, 1, 2, 3, 4] + }, + { + "comment": "Using @ in a filter expression", + "expression": "foo[?@ == @]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/functions.json b/vendor/github.com/jmespath/go-jmespath/compliance/functions.json new file mode 100644 index 000000000..8b8db363a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/functions.json @@ -0,0 +1,825 @@ +[{ + "given": + { + "foo": -1, + "zero": 0, + "numbers": [-1, 3, 4, 5], + "array": [-1, 3, 4, 5, "a", "100"], + "strings": ["a", "b", "c"], + "decimals": [1.01, 1.2, -1.5], + "str": "Str", + "false": false, + "empty_list": [], + "empty_hash": {}, + "objects": {"foo": "bar", "bar": "baz"}, + "null_key": null + }, + "cases": [ + { + "expression": "abs(foo)", + "result": 1 + }, + { + "expression": "abs(foo)", + "result": 1 + }, + { + "expression": "abs(str)", + "error": "invalid-type" + }, + { + "expression": "abs(array[1])", + "result": 3 + }, + { + "expression": "abs(array[1])", + "result": 3 + }, + { + "expression": "abs(`false`)", + "error": "invalid-type" + }, + { + "expression": "abs(`-24`)", + "result": 24 + }, + { + "expression": "abs(`-24`)", + "result": 24 + }, + { + "expression": "abs(`1`, `2`)", + "error": "invalid-arity" + }, + { + "expression": "abs()", + "error": "invalid-arity" + }, + { + "expression": "unknown_function(`1`, `2`)", + "error": "unknown-function" + }, + { + "expression": "avg(numbers)", + "result": 2.75 + }, + { + "expression": "avg(array)", + "error": "invalid-type" + }, + { + "expression": "avg('abc')", + "error": "invalid-type" + }, + { + "expression": "avg(foo)", + "error": "invalid-type" + }, + { + "expression": "avg(@)", + "error": "invalid-type" + }, + { + "expression": "avg(strings)", + "error": "invalid-type" + }, + { + "expression": "ceil(`1.2`)", + "result": 2 + }, + { + "expression": "ceil(decimals[0])", + "result": 2 + }, + { + "expression": "ceil(decimals[1])", + "result": 2 + }, + { + "expression": "ceil(decimals[2])", + "result": -1 + }, + { + "expression": "ceil('string')", + "error": "invalid-type" + }, + { + "expression": "contains('abc', 'a')", + "result": true + }, + { + "expression": "contains('abc', 'd')", + "result": false + }, + { + "expression": "contains(`false`, 'd')", + "error": "invalid-type" + }, + { + "expression": "contains(strings, 'a')", + "result": true + }, + { + "expression": "contains(decimals, `1.2`)", + "result": true + }, + { + "expression": "contains(decimals, `false`)", + "result": false + }, + { + "expression": "ends_with(str, 'r')", + "result": true + }, + { + "expression": "ends_with(str, 'tr')", + "result": true + }, + { + "expression": "ends_with(str, 'Str')", + "result": true + }, + { + "expression": "ends_with(str, 'SStr')", + "result": false + }, + { + "expression": "ends_with(str, 'foo')", + "result": false + }, + { + "expression": "ends_with(str, `0`)", + "error": "invalid-type" + }, + { + "expression": "floor(`1.2`)", + "result": 1 + }, + { + "expression": "floor('string')", + "error": "invalid-type" + }, + { + "expression": "floor(decimals[0])", + "result": 1 + }, + { + "expression": "floor(foo)", + "result": -1 + }, + { + "expression": "floor(str)", + "error": "invalid-type" + }, + { + "expression": "length('abc')", + "result": 3 + }, + { + "expression": "length('✓foo')", + "result": 4 + }, + { + "expression": "length('')", + "result": 0 + }, + { + "expression": "length(@)", + "result": 12 + }, + { + "expression": "length(strings[0])", + "result": 1 + }, + { + "expression": "length(str)", + "result": 3 + }, + { + "expression": "length(array)", + "result": 6 + }, + { + "expression": "length(objects)", + "result": 2 + }, + { + "expression": "length(`false`)", + "error": "invalid-type" + }, + { + "expression": "length(foo)", + "error": "invalid-type" + }, + { + "expression": "length(strings[0])", + "result": 1 + }, + { + "expression": "max(numbers)", + "result": 5 + }, + { + "expression": "max(decimals)", + "result": 1.2 + }, + { + "expression": "max(strings)", + "result": "c" + }, + { + "expression": "max(abc)", + "error": "invalid-type" + }, + { + "expression": "max(array)", + "error": "invalid-type" + }, + { + "expression": "max(decimals)", + "result": 1.2 + }, + { + "expression": "max(empty_list)", + "result": null + }, + { + "expression": "merge(`{}`)", + "result": {} + }, + { + "expression": "merge(`{}`, `{}`)", + "result": {} + }, + { + "expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)", + "result": {"a": 1, "b": 2} + }, + { + "expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)", + "result": {"a": 2} + }, + { + "expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)", + "result": {"a": 2, "b": 2, "c": 3, "d": 4} + }, + { + "expression": "min(numbers)", + "result": -1 + }, + { + "expression": "min(decimals)", + "result": -1.5 + }, + { + "expression": "min(abc)", + "error": "invalid-type" + }, + { + "expression": "min(array)", + "error": "invalid-type" + }, + { + "expression": "min(empty_list)", + "result": null + }, + { + "expression": "min(decimals)", + "result": -1.5 + }, + { + "expression": "min(strings)", + "result": "a" + }, + { + "expression": "type('abc')", + "result": "string" + }, + { + "expression": "type(`1.0`)", + "result": "number" + }, + { + "expression": "type(`2`)", + "result": "number" + }, + { + "expression": "type(`true`)", + "result": "boolean" + }, + { + "expression": "type(`false`)", + "result": "boolean" + }, + { + "expression": "type(`null`)", + "result": "null" + }, + { + "expression": "type(`[0]`)", + "result": "array" + }, + { + "expression": "type(`{\"a\": \"b\"}`)", + "result": "object" + }, + { + "expression": "type(@)", + "result": "object" + }, + { + "expression": "sort(keys(objects))", + "result": ["bar", "foo"] + }, + { + "expression": "keys(foo)", + "error": "invalid-type" + }, + { + "expression": "keys(strings)", + "error": "invalid-type" + }, + { + "expression": "keys(`false`)", + "error": "invalid-type" + }, + { + "expression": "sort(values(objects))", + "result": ["bar", "baz"] + }, + { + "expression": "keys(empty_hash)", + "result": [] + }, + { + "expression": "values(foo)", + "error": "invalid-type" + }, + { + "expression": "join(', ', strings)", + "result": "a, b, c" + }, + { + "expression": "join(', ', strings)", + "result": "a, b, c" + }, + { + "expression": "join(',', `[\"a\", \"b\"]`)", + "result": "a,b" + }, + { + "expression": "join(',', `[\"a\", 0]`)", + "error": "invalid-type" + }, + { + "expression": "join(', ', str)", + "error": "invalid-type" + }, + { + "expression": "join('|', strings)", + "result": "a|b|c" + }, + { + "expression": "join(`2`, strings)", + "error": "invalid-type" + }, + { + "expression": "join('|', decimals)", + "error": "invalid-type" + }, + { + "expression": "join('|', decimals[].to_string(@))", + "result": "1.01|1.2|-1.5" + }, + { + "expression": "join('|', empty_list)", + "result": "" + }, + { + "expression": "reverse(numbers)", + "result": [5, 4, 3, -1] + }, + { + "expression": "reverse(array)", + "result": ["100", "a", 5, 4, 3, -1] + }, + { + "expression": "reverse(`[]`)", + "result": [] + }, + { + "expression": "reverse('')", + "result": "" + }, + { + "expression": "reverse('hello world')", + "result": "dlrow olleh" + }, + { + "expression": "starts_with(str, 'S')", + "result": true + }, + { + "expression": "starts_with(str, 'St')", + "result": true + }, + { + "expression": "starts_with(str, 'Str')", + "result": true + }, + { + "expression": "starts_with(str, 'String')", + "result": false + }, + { + "expression": "starts_with(str, `0`)", + "error": "invalid-type" + }, + { + "expression": "sum(numbers)", + "result": 11 + }, + { + "expression": "sum(decimals)", + "result": 0.71 + }, + { + "expression": "sum(array)", + "error": "invalid-type" + }, + { + "expression": "sum(array[].to_number(@))", + "result": 111 + }, + { + "expression": "sum(`[]`)", + "result": 0 + }, + { + "expression": "to_array('foo')", + "result": ["foo"] + }, + { + "expression": "to_array(`0`)", + "result": [0] + }, + { + "expression": "to_array(objects)", + "result": [{"foo": "bar", "bar": "baz"}] + }, + { + "expression": "to_array(`[1, 2, 3]`)", + "result": [1, 2, 3] + }, + { + "expression": "to_array(false)", + "result": [false] + }, + { + "expression": "to_string('foo')", + "result": "foo" + }, + { + "expression": "to_string(`1.2`)", + "result": "1.2" + }, + { + "expression": "to_string(`[0, 1]`)", + "result": "[0,1]" + }, + { + "expression": "to_number('1.0')", + "result": 1.0 + }, + { + "expression": "to_number('1.1')", + "result": 1.1 + }, + { + "expression": "to_number('4')", + "result": 4 + }, + { + "expression": "to_number('notanumber')", + "result": null + }, + { + "expression": "to_number(`false`)", + "result": null + }, + { + "expression": "to_number(`null`)", + "result": null + }, + { + "expression": "to_number(`[0]`)", + "result": null + }, + { + "expression": "to_number(`{\"foo\": 0}`)", + "result": null + }, + { + "expression": "\"to_string\"(`1.0`)", + "error": "syntax" + }, + { + "expression": "sort(numbers)", + "result": [-1, 3, 4, 5] + }, + { + "expression": "sort(strings)", + "result": ["a", "b", "c"] + }, + { + "expression": "sort(decimals)", + "result": [-1.5, 1.01, 1.2] + }, + { + "expression": "sort(array)", + "error": "invalid-type" + }, + { + "expression": "sort(abc)", + "error": "invalid-type" + }, + { + "expression": "sort(empty_list)", + "result": [] + }, + { + "expression": "sort(@)", + "error": "invalid-type" + }, + { + "expression": "not_null(unknown_key, str)", + "result": "Str" + }, + { + "expression": "not_null(unknown_key, foo.bar, empty_list, str)", + "result": [] + }, + { + "expression": "not_null(unknown_key, null_key, empty_list, str)", + "result": [] + }, + { + "expression": "not_null(all, expressions, are_null)", + "result": null + }, + { + "expression": "not_null()", + "error": "invalid-arity" + }, + { + "description": "function projection on single arg function", + "expression": "numbers[].to_string(@)", + "result": ["-1", "3", "4", "5"] + }, + { + "description": "function projection on single arg function", + "expression": "array[].to_number(@)", + "result": [-1, 3, 4, 5, 100] + } + ] +}, { + "given": + { + "foo": [ + {"b": "b", "a": "a"}, + {"c": "c", "b": "b"}, + {"d": "d", "c": "c"}, + {"e": "e", "d": "d"}, + {"f": "f", "e": "e"} + ] + }, + "cases": [ + { + "description": "function projection on variadic function", + "expression": "foo[].not_null(f, e, d, c, b, a)", + "result": ["b", "c", "d", "e", "f"] + } + ] +}, { + "given": + { + "people": [ + {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"}, + {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"}, + {"age": 30, "age_str": "30", "bool": true, "name": "c"}, + {"age": 50, "age_str": "50", "bool": false, "name": "d"}, + {"age": 10, "age_str": "10", "bool": true, "name": 3} + ] + }, + "cases": [ + { + "description": "sort by field expression", + "expression": "sort_by(people, &age)", + "result": [ + {"age": 10, "age_str": "10", "bool": true, "name": 3}, + {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"}, + {"age": 30, "age_str": "30", "bool": true, "name": "c"}, + {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"}, + {"age": 50, "age_str": "50", "bool": false, "name": "d"} + ] + }, + { + "expression": "sort_by(people, &age_str)", + "result": [ + {"age": 10, "age_str": "10", "bool": true, "name": 3}, + {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"}, + {"age": 30, "age_str": "30", "bool": true, "name": "c"}, + {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"}, + {"age": 50, "age_str": "50", "bool": false, "name": "d"} + ] + }, + { + "description": "sort by function expression", + "expression": "sort_by(people, &to_number(age_str))", + "result": [ + {"age": 10, "age_str": "10", "bool": true, "name": 3}, + {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"}, + {"age": 30, "age_str": "30", "bool": true, "name": "c"}, + {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"}, + {"age": 50, "age_str": "50", "bool": false, "name": "d"} + ] + }, + { + "description": "function projection on sort_by function", + "expression": "sort_by(people, &age)[].name", + "result": [3, "a", "c", "b", "d"] + }, + { + "expression": "sort_by(people, &extra)", + "error": "invalid-type" + }, + { + "expression": "sort_by(people, &bool)", + "error": "invalid-type" + }, + { + "expression": "sort_by(people, &name)", + "error": "invalid-type" + }, + { + "expression": "sort_by(people, name)", + "error": "invalid-type" + }, + { + "expression": "sort_by(people, &age)[].extra", + "result": ["foo", "bar"] + }, + { + "expression": "sort_by(`[]`, &age)", + "result": [] + }, + { + "expression": "max_by(people, &age)", + "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"} + }, + { + "expression": "max_by(people, &age_str)", + "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"} + }, + { + "expression": "max_by(people, &bool)", + "error": "invalid-type" + }, + { + "expression": "max_by(people, &extra)", + "error": "invalid-type" + }, + { + "expression": "max_by(people, &to_number(age_str))", + "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"} + }, + { + "expression": "min_by(people, &age)", + "result": {"age": 10, "age_str": "10", "bool": true, "name": 3} + }, + { + "expression": "min_by(people, &age_str)", + "result": {"age": 10, "age_str": "10", "bool": true, "name": 3} + }, + { + "expression": "min_by(people, &bool)", + "error": "invalid-type" + }, + { + "expression": "min_by(people, &extra)", + "error": "invalid-type" + }, + { + "expression": "min_by(people, &to_number(age_str))", + "result": {"age": 10, "age_str": "10", "bool": true, "name": 3} + } + ] +}, { + "given": + { + "people": [ + {"age": 10, "order": "1"}, + {"age": 10, "order": "2"}, + {"age": 10, "order": "3"}, + {"age": 10, "order": "4"}, + {"age": 10, "order": "5"}, + {"age": 10, "order": "6"}, + {"age": 10, "order": "7"}, + {"age": 10, "order": "8"}, + {"age": 10, "order": "9"}, + {"age": 10, "order": "10"}, + {"age": 10, "order": "11"} + ] + }, + "cases": [ + { + "description": "stable sort order", + "expression": "sort_by(people, &age)", + "result": [ + {"age": 10, "order": "1"}, + {"age": 10, "order": "2"}, + {"age": 10, "order": "3"}, + {"age": 10, "order": "4"}, + {"age": 10, "order": "5"}, + {"age": 10, "order": "6"}, + {"age": 10, "order": "7"}, + {"age": 10, "order": "8"}, + {"age": 10, "order": "9"}, + {"age": 10, "order": "10"}, + {"age": 10, "order": "11"} + ] + } + ] +}, { + "given": + { + "people": [ + {"a": 10, "b": 1, "c": "z"}, + {"a": 10, "b": 2, "c": null}, + {"a": 10, "b": 3}, + {"a": 10, "b": 4, "c": "z"}, + {"a": 10, "b": 5, "c": null}, + {"a": 10, "b": 6}, + {"a": 10, "b": 7, "c": "z"}, + {"a": 10, "b": 8, "c": null}, + {"a": 10, "b": 9} + ], + "empty": [] + }, + "cases": [ + { + "expression": "map(&a, people)", + "result": [10, 10, 10, 10, 10, 10, 10, 10, 10] + }, + { + "expression": "map(&c, people)", + "result": ["z", null, null, "z", null, null, "z", null, null] + }, + { + "expression": "map(&a, badkey)", + "error": "invalid-type" + }, + { + "expression": "map(&foo, empty)", + "result": [] + } + ] +}, { + "given": { + "array": [ + { + "foo": {"bar": "yes1"} + }, + { + "foo": {"bar": "yes2"} + }, + { + "foo1": {"bar": "no"} + } + ]}, + "cases": [ + { + "expression": "map(&foo.bar, array)", + "result": ["yes1", "yes2", null] + }, + { + "expression": "map(&foo1.bar, array)", + "result": [null, null, "no"] + }, + { + "expression": "map(&foo.bar.baz, array)", + "result": [null, null, null] + } + ] +}, { + "given": { + "array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]] + }, + "cases": [ + { + "expression": "map(&[], array)", + "result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]] + } + ] +} +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json b/vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json new file mode 100644 index 000000000..7998a41ac --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json @@ -0,0 +1,1377 @@ +[ + { + "given": { + "__L": true + }, + "cases": [ + { + "expression": "__L", + "result": true + } + ] + }, + { + "given": { + "!\r": true + }, + "cases": [ + { + "expression": "\"!\\r\"", + "result": true + } + ] + }, + { + "given": { + "Y_1623": true + }, + "cases": [ + { + "expression": "Y_1623", + "result": true + } + ] + }, + { + "given": { + "x": true + }, + "cases": [ + { + "expression": "x", + "result": true + } + ] + }, + { + "given": { + "\tF\uCebb": true + }, + "cases": [ + { + "expression": "\"\\tF\\uCebb\"", + "result": true + } + ] + }, + { + "given": { + " \t": true + }, + "cases": [ + { + "expression": "\" \\t\"", + "result": true + } + ] + }, + { + "given": { + " ": true + }, + "cases": [ + { + "expression": "\" \"", + "result": true + } + ] + }, + { + "given": { + "v2": true + }, + "cases": [ + { + "expression": "v2", + "result": true + } + ] + }, + { + "given": { + "\t": true + }, + "cases": [ + { + "expression": "\"\\t\"", + "result": true + } + ] + }, + { + "given": { + "_X": true + }, + "cases": [ + { + "expression": "_X", + "result": true + } + ] + }, + { + "given": { + "\t4\ud9da\udd15": true + }, + "cases": [ + { + "expression": "\"\\t4\\ud9da\\udd15\"", + "result": true + } + ] + }, + { + "given": { + "v24_W": true + }, + "cases": [ + { + "expression": "v24_W", + "result": true + } + ] + }, + { + "given": { + "H": true + }, + "cases": [ + { + "expression": "\"H\"", + "result": true + } + ] + }, + { + "given": { + "\f": true + }, + "cases": [ + { + "expression": "\"\\f\"", + "result": true + } + ] + }, + { + "given": { + "E4": true + }, + "cases": [ + { + "expression": "\"E4\"", + "result": true + } + ] + }, + { + "given": { + "!": true + }, + "cases": [ + { + "expression": "\"!\"", + "result": true + } + ] + }, + { + "given": { + "tM": true + }, + "cases": [ + { + "expression": "tM", + "result": true + } + ] + }, + { + "given": { + " [": true + }, + "cases": [ + { + "expression": "\" [\"", + "result": true + } + ] + }, + { + "given": { + "R!": true + }, + "cases": [ + { + "expression": "\"R!\"", + "result": true + } + ] + }, + { + "given": { + "_6W": true + }, + "cases": [ + { + "expression": "_6W", + "result": true + } + ] + }, + { + "given": { + "\uaBA1\r": true + }, + "cases": [ + { + "expression": "\"\\uaBA1\\r\"", + "result": true + } + ] + }, + { + "given": { + "tL7": true + }, + "cases": [ + { + "expression": "tL7", + "result": true + } + ] + }, + { + "given": { + "<": true + }, + "cases": [ + { + "expression": "\">\"", + "result": true + } + ] + }, + { + "given": { + "hvu": true + }, + "cases": [ + { + "expression": "hvu", + "result": true + } + ] + }, + { + "given": { + "; !": true + }, + "cases": [ + { + "expression": "\"; !\"", + "result": true + } + ] + }, + { + "given": { + "hU": true + }, + "cases": [ + { + "expression": "hU", + "result": true + } + ] + }, + { + "given": { + "!I\n\/": true + }, + "cases": [ + { + "expression": "\"!I\\n\\/\"", + "result": true + } + ] + }, + { + "given": { + "\uEEbF": true + }, + "cases": [ + { + "expression": "\"\\uEEbF\"", + "result": true + } + ] + }, + { + "given": { + "U)\t": true + }, + "cases": [ + { + "expression": "\"U)\\t\"", + "result": true + } + ] + }, + { + "given": { + "fa0_9": true + }, + "cases": [ + { + "expression": "fa0_9", + "result": true + } + ] + }, + { + "given": { + "/": true + }, + "cases": [ + { + "expression": "\"/\"", + "result": true + } + ] + }, + { + "given": { + "Gy": true + }, + "cases": [ + { + "expression": "Gy", + "result": true + } + ] + }, + { + "given": { + "\b": true + }, + "cases": [ + { + "expression": "\"\\b\"", + "result": true + } + ] + }, + { + "given": { + "<": true + }, + "cases": [ + { + "expression": "\"<\"", + "result": true + } + ] + }, + { + "given": { + "\t": true + }, + "cases": [ + { + "expression": "\"\\t\"", + "result": true + } + ] + }, + { + "given": { + "\t&\\\r": true + }, + "cases": [ + { + "expression": "\"\\t&\\\\\\r\"", + "result": true + } + ] + }, + { + "given": { + "#": true + }, + "cases": [ + { + "expression": "\"#\"", + "result": true + } + ] + }, + { + "given": { + "B__": true + }, + "cases": [ + { + "expression": "B__", + "result": true + } + ] + }, + { + "given": { + "\nS \n": true + }, + "cases": [ + { + "expression": "\"\\nS \\n\"", + "result": true + } + ] + }, + { + "given": { + "Bp": true + }, + "cases": [ + { + "expression": "Bp", + "result": true + } + ] + }, + { + "given": { + ",\t;": true + }, + "cases": [ + { + "expression": "\",\\t;\"", + "result": true + } + ] + }, + { + "given": { + "B_q": true + }, + "cases": [ + { + "expression": "B_q", + "result": true + } + ] + }, + { + "given": { + "\/+\t\n\b!Z": true + }, + "cases": [ + { + "expression": "\"\\/+\\t\\n\\b!Z\"", + "result": true + } + ] + }, + { + "given": { + "\udadd\udfc7\\ueFAc": true + }, + "cases": [ + { + "expression": "\"\udadd\udfc7\\\\ueFAc\"", + "result": true + } + ] + }, + { + "given": { + ":\f": true + }, + "cases": [ + { + "expression": "\":\\f\"", + "result": true + } + ] + }, + { + "given": { + "\/": true + }, + "cases": [ + { + "expression": "\"\\/\"", + "result": true + } + ] + }, + { + "given": { + "_BW_6Hg_Gl": true + }, + "cases": [ + { + "expression": "_BW_6Hg_Gl", + "result": true + } + ] + }, + { + "given": { + "\udbcf\udc02": true + }, + "cases": [ + { + "expression": "\"\udbcf\udc02\"", + "result": true + } + ] + }, + { + "given": { + "zs1DC": true + }, + "cases": [ + { + "expression": "zs1DC", + "result": true + } + ] + }, + { + "given": { + "__434": true + }, + "cases": [ + { + "expression": "__434", + "result": true + } + ] + }, + { + "given": { + "\udb94\udd41": true + }, + "cases": [ + { + "expression": "\"\udb94\udd41\"", + "result": true + } + ] + }, + { + "given": { + "Z_5": true + }, + "cases": [ + { + "expression": "Z_5", + "result": true + } + ] + }, + { + "given": { + "z_M_": true + }, + "cases": [ + { + "expression": "z_M_", + "result": true + } + ] + }, + { + "given": { + "YU_2": true + }, + "cases": [ + { + "expression": "YU_2", + "result": true + } + ] + }, + { + "given": { + "_0": true + }, + "cases": [ + { + "expression": "_0", + "result": true + } + ] + }, + { + "given": { + "\b+": true + }, + "cases": [ + { + "expression": "\"\\b+\"", + "result": true + } + ] + }, + { + "given": { + "\"": true + }, + "cases": [ + { + "expression": "\"\\\"\"", + "result": true + } + ] + }, + { + "given": { + "D7": true + }, + "cases": [ + { + "expression": "D7", + "result": true + } + ] + }, + { + "given": { + "_62L": true + }, + "cases": [ + { + "expression": "_62L", + "result": true + } + ] + }, + { + "given": { + "\tK\t": true + }, + "cases": [ + { + "expression": "\"\\tK\\t\"", + "result": true + } + ] + }, + { + "given": { + "\n\\\f": true + }, + "cases": [ + { + "expression": "\"\\n\\\\\\f\"", + "result": true + } + ] + }, + { + "given": { + "I_": true + }, + "cases": [ + { + "expression": "I_", + "result": true + } + ] + }, + { + "given": { + "W_a0_": true + }, + "cases": [ + { + "expression": "W_a0_", + "result": true + } + ] + }, + { + "given": { + "BQ": true + }, + "cases": [ + { + "expression": "BQ", + "result": true + } + ] + }, + { + "given": { + "\tX$\uABBb": true + }, + "cases": [ + { + "expression": "\"\\tX$\\uABBb\"", + "result": true + } + ] + }, + { + "given": { + "Z9": true + }, + "cases": [ + { + "expression": "Z9", + "result": true + } + ] + }, + { + "given": { + "\b%\"\uda38\udd0f": true + }, + "cases": [ + { + "expression": "\"\\b%\\\"\uda38\udd0f\"", + "result": true + } + ] + }, + { + "given": { + "_F": true + }, + "cases": [ + { + "expression": "_F", + "result": true + } + ] + }, + { + "given": { + "!,": true + }, + "cases": [ + { + "expression": "\"!,\"", + "result": true + } + ] + }, + { + "given": { + "\"!": true + }, + "cases": [ + { + "expression": "\"\\\"!\"", + "result": true + } + ] + }, + { + "given": { + "Hh": true + }, + "cases": [ + { + "expression": "Hh", + "result": true + } + ] + }, + { + "given": { + "&": true + }, + "cases": [ + { + "expression": "\"&\"", + "result": true + } + ] + }, + { + "given": { + "9\r\\R": true + }, + "cases": [ + { + "expression": "\"9\\r\\\\R\"", + "result": true + } + ] + }, + { + "given": { + "M_k": true + }, + "cases": [ + { + "expression": "M_k", + "result": true + } + ] + }, + { + "given": { + "!\b\n\udb06\ude52\"\"": true + }, + "cases": [ + { + "expression": "\"!\\b\\n\udb06\ude52\\\"\\\"\"", + "result": true + } + ] + }, + { + "given": { + "6": true + }, + "cases": [ + { + "expression": "\"6\"", + "result": true + } + ] + }, + { + "given": { + "_7": true + }, + "cases": [ + { + "expression": "_7", + "result": true + } + ] + }, + { + "given": { + "0": true + }, + "cases": [ + { + "expression": "\"0\"", + "result": true + } + ] + }, + { + "given": { + "\\8\\": true + }, + "cases": [ + { + "expression": "\"\\\\8\\\\\"", + "result": true + } + ] + }, + { + "given": { + "b7eo": true + }, + "cases": [ + { + "expression": "b7eo", + "result": true + } + ] + }, + { + "given": { + "xIUo9": true + }, + "cases": [ + { + "expression": "xIUo9", + "result": true + } + ] + }, + { + "given": { + "5": true + }, + "cases": [ + { + "expression": "\"5\"", + "result": true + } + ] + }, + { + "given": { + "?": true + }, + "cases": [ + { + "expression": "\"?\"", + "result": true + } + ] + }, + { + "given": { + "sU": true + }, + "cases": [ + { + "expression": "sU", + "result": true + } + ] + }, + { + "given": { + "VH2&H\\\/": true + }, + "cases": [ + { + "expression": "\"VH2&H\\\\\\/\"", + "result": true + } + ] + }, + { + "given": { + "_C": true + }, + "cases": [ + { + "expression": "_C", + "result": true + } + ] + }, + { + "given": { + "_": true + }, + "cases": [ + { + "expression": "_", + "result": true + } + ] + }, + { + "given": { + "<\t": true + }, + "cases": [ + { + "expression": "\"<\\t\"", + "result": true + } + ] + }, + { + "given": { + "\uD834\uDD1E": true + }, + "cases": [ + { + "expression": "\"\\uD834\\uDD1E\"", + "result": true + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/indices.json b/vendor/github.com/jmespath/go-jmespath/compliance/indices.json new file mode 100644 index 000000000..aa03b35dd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/indices.json @@ -0,0 +1,346 @@ +[{ + "given": + {"foo": {"bar": ["zero", "one", "two"]}}, + "cases": [ + { + "expression": "foo.bar[0]", + "result": "zero" + }, + { + "expression": "foo.bar[1]", + "result": "one" + }, + { + "expression": "foo.bar[2]", + "result": "two" + }, + { + "expression": "foo.bar[3]", + "result": null + }, + { + "expression": "foo.bar[-1]", + "result": "two" + }, + { + "expression": "foo.bar[-2]", + "result": "one" + }, + { + "expression": "foo.bar[-3]", + "result": "zero" + }, + { + "expression": "foo.bar[-4]", + "result": null + } + ] +}, +{ + "given": + {"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]}, + "cases": [ + { + "expression": "foo.bar", + "result": null + }, + { + "expression": "foo[0].bar", + "result": "one" + }, + { + "expression": "foo[1].bar", + "result": "two" + }, + { + "expression": "foo[2].bar", + "result": "three" + }, + { + "expression": "foo[3].notbar", + "result": "four" + }, + { + "expression": "foo[3].bar", + "result": null + }, + { + "expression": "foo[0]", + "result": {"bar": "one"} + }, + { + "expression": "foo[1]", + "result": {"bar": "two"} + }, + { + "expression": "foo[2]", + "result": {"bar": "three"} + }, + { + "expression": "foo[3]", + "result": {"notbar": "four"} + }, + { + "expression": "foo[4]", + "result": null + } + ] +}, +{ + "given": [ + "one", "two", "three" + ], + "cases": [ + { + "expression": "[0]", + "result": "one" + }, + { + "expression": "[1]", + "result": "two" + }, + { + "expression": "[2]", + "result": "three" + }, + { + "expression": "[-1]", + "result": "three" + }, + { + "expression": "[-2]", + "result": "two" + }, + { + "expression": "[-3]", + "result": "one" + } + ] +}, +{ + "given": {"reservations": [ + {"instances": [{"foo": 1}, {"foo": 2}]} + ]}, + "cases": [ + { + "expression": "reservations[].instances[].foo", + "result": [1, 2] + }, + { + "expression": "reservations[].instances[].bar", + "result": [] + }, + { + "expression": "reservations[].notinstances[].foo", + "result": [] + }, + { + "expression": "reservations[].notinstances[].foo", + "result": [] + } + ] +}, +{ + "given": {"reservations": [{ + "instances": [ + {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}, + {"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]}, + {"foo": "bar"}, + {"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]}, + {"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]}, + {"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]}, + {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]} + ], + "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]} + }, { + "instances": [ + {"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}, + {"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]}, + {"c": "bar"}, + {"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]}, + {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]} + ], + "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]} + } + ]}, + "cases": [ + { + "expression": "reservations[].instances[].foo[].bar", + "result": [1, 2, 4, 5, 6, 8] + }, + { + "expression": "reservations[].instances[].foo[].baz", + "result": [] + }, + { + "expression": "reservations[].instances[].notfoo[].bar", + "result": [20, 21, 22, 23, 24, 25] + }, + { + "expression": "reservations[].instances[].notfoo[].notbar", + "result": [[7], [7]] + }, + { + "expression": "reservations[].notinstances[].foo", + "result": [] + }, + { + "expression": "reservations[].instances[].foo[].notbar", + "result": [3, [7]] + }, + { + "expression": "reservations[].instances[].bar[].baz", + "result": [[1], [2], [3], [4]] + }, + { + "expression": "reservations[].instances[].baz[].baz", + "result": [[1, 2], [], [], [3, 4]] + }, + { + "expression": "reservations[].instances[].qux[].baz", + "result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []] + }, + { + "expression": "reservations[].instances[].qux[].baz[]", + "result": [1, 2, 3, 4, 1, 2, 3, 4] + } + ] +}, +{ + "given": { + "foo": [ + [["one", "two"], ["three", "four"]], + [["five", "six"], ["seven", "eight"]], + [["nine"], ["ten"]] + ] + }, + "cases": [ + { + "expression": "foo[]", + "result": [["one", "two"], ["three", "four"], ["five", "six"], + ["seven", "eight"], ["nine"], ["ten"]] + }, + { + "expression": "foo[][0]", + "result": ["one", "three", "five", "seven", "nine", "ten"] + }, + { + "expression": "foo[][1]", + "result": ["two", "four", "six", "eight"] + }, + { + "expression": "foo[][0][0]", + "result": [] + }, + { + "expression": "foo[][2][2]", + "result": [] + }, + { + "expression": "foo[][0][0][100]", + "result": [] + } + ] +}, +{ + "given": { + "foo": [{ + "bar": [ + { + "qux": 2, + "baz": 1 + }, + { + "qux": 4, + "baz": 3 + } + ] + }, + { + "bar": [ + { + "qux": 6, + "baz": 5 + }, + { + "qux": 8, + "baz": 7 + } + ] + } + ] + }, + "cases": [ + { + "expression": "foo", + "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]}, + {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}] + }, + { + "expression": "foo[]", + "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]}, + {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}] + }, + { + "expression": "foo[].bar", + "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}], + [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]] + }, + { + "expression": "foo[].bar[]", + "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}, + {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}] + }, + { + "expression": "foo[].bar[].baz", + "result": [1, 3, 5, 7] + } + ] +}, +{ + "given": { + "string": "string", + "hash": {"foo": "bar", "bar": "baz"}, + "number": 23, + "nullvalue": null + }, + "cases": [ + { + "expression": "string[]", + "result": null + }, + { + "expression": "hash[]", + "result": null + }, + { + "expression": "number[]", + "result": null + }, + { + "expression": "nullvalue[]", + "result": null + }, + { + "expression": "string[].foo", + "result": null + }, + { + "expression": "hash[].foo", + "result": null + }, + { + "expression": "number[].foo", + "result": null + }, + { + "expression": "nullvalue[].foo", + "result": null + }, + { + "expression": "nullvalue[].foo[].bar", + "result": null + } + ] +} +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/literal.json b/vendor/github.com/jmespath/go-jmespath/compliance/literal.json new file mode 100644 index 000000000..c6706b971 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/literal.json @@ -0,0 +1,185 @@ +[ + { + "given": { + "foo": [{"name": "a"}, {"name": "b"}], + "bar": {"baz": "qux"} + }, + "cases": [ + { + "expression": "`\"foo\"`", + "result": "foo" + }, + { + "comment": "Interpret escaped unicode.", + "expression": "`\"\\u03a6\"`", + "result": "Φ" + }, + { + "expression": "`\"✓\"`", + "result": "✓" + }, + { + "expression": "`[1, 2, 3]`", + "result": [1, 2, 3] + }, + { + "expression": "`{\"a\": \"b\"}`", + "result": {"a": "b"} + }, + { + "expression": "`true`", + "result": true + }, + { + "expression": "`false`", + "result": false + }, + { + "expression": "`null`", + "result": null + }, + { + "expression": "`0`", + "result": 0 + }, + { + "expression": "`1`", + "result": 1 + }, + { + "expression": "`2`", + "result": 2 + }, + { + "expression": "`3`", + "result": 3 + }, + { + "expression": "`4`", + "result": 4 + }, + { + "expression": "`5`", + "result": 5 + }, + { + "expression": "`6`", + "result": 6 + }, + { + "expression": "`7`", + "result": 7 + }, + { + "expression": "`8`", + "result": 8 + }, + { + "expression": "`9`", + "result": 9 + }, + { + "comment": "Escaping a backtick in quotes", + "expression": "`\"foo\\`bar\"`", + "result": "foo`bar" + }, + { + "comment": "Double quote in literal", + "expression": "`\"foo\\\"bar\"`", + "result": "foo\"bar" + }, + { + "expression": "`\"1\\`\"`", + "result": "1`" + }, + { + "comment": "Multiple literal expressions with escapes", + "expression": "`\"\\\\\"`.{a:`\"b\"`}", + "result": {"a": "b"} + }, + { + "comment": "literal . identifier", + "expression": "`{\"a\": \"b\"}`.a", + "result": "b" + }, + { + "comment": "literal . identifier . identifier", + "expression": "`{\"a\": {\"b\": \"c\"}}`.a.b", + "result": "c" + }, + { + "comment": "literal . identifier bracket-expr", + "expression": "`[0, 1, 2]`[1]", + "result": 1 + } + ] + }, + { + "comment": "Literals", + "given": {"type": "object"}, + "cases": [ + { + "comment": "Literal with leading whitespace", + "expression": "` {\"foo\": true}`", + "result": {"foo": true} + }, + { + "comment": "Literal with trailing whitespace", + "expression": "`{\"foo\": true} `", + "result": {"foo": true} + }, + { + "comment": "Literal on RHS of subexpr not allowed", + "expression": "foo.`\"bar\"`", + "error": "syntax" + } + ] + }, + { + "comment": "Raw String Literals", + "given": {}, + "cases": [ + { + "expression": "'foo'", + "result": "foo" + }, + { + "expression": "' foo '", + "result": " foo " + }, + { + "expression": "'0'", + "result": "0" + }, + { + "expression": "'newline\n'", + "result": "newline\n" + }, + { + "expression": "'\n'", + "result": "\n" + }, + { + "expression": "'✓'", + "result": "✓" + }, + { + "expression": "'ð„ž'", + "result": "ð„ž" + }, + { + "expression": "' [foo] '", + "result": " [foo] " + }, + { + "expression": "'[foo]'", + "result": "[foo]" + }, + { + "comment": "Do not interpret escaped unicode.", + "expression": "'\\u03a6'", + "result": "\\u03a6" + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json b/vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json new file mode 100644 index 000000000..8f2a481ed --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json @@ -0,0 +1,393 @@ +[{ + "given": { + "foo": { + "bar": "bar", + "baz": "baz", + "qux": "qux", + "nested": { + "one": { + "a": "first", + "b": "second", + "c": "third" + }, + "two": { + "a": "first", + "b": "second", + "c": "third" + }, + "three": { + "a": "first", + "b": "second", + "c": {"inner": "third"} + } + } + }, + "bar": 1, + "baz": 2, + "qux\"": 3 + }, + "cases": [ + { + "expression": "foo.{bar: bar}", + "result": {"bar": "bar"} + }, + { + "expression": "foo.{\"bar\": bar}", + "result": {"bar": "bar"} + }, + { + "expression": "foo.{\"foo.bar\": bar}", + "result": {"foo.bar": "bar"} + }, + { + "expression": "foo.{bar: bar, baz: baz}", + "result": {"bar": "bar", "baz": "baz"} + }, + { + "expression": "foo.{\"bar\": bar, \"baz\": baz}", + "result": {"bar": "bar", "baz": "baz"} + }, + { + "expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}", + "result": {"baz": 2, "qux\"": 3} + }, + { + "expression": "foo.{bar:bar,baz:baz}", + "result": {"bar": "bar", "baz": "baz"} + }, + { + "expression": "foo.{bar: bar,qux: qux}", + "result": {"bar": "bar", "qux": "qux"} + }, + { + "expression": "foo.{bar: bar, noexist: noexist}", + "result": {"bar": "bar", "noexist": null} + }, + { + "expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}", + "result": {"noexist": null, "alsonoexist": null} + }, + { + "expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}", + "result": null + }, + { + "expression": "foo.nested.*.{a: a,b: b}", + "result": [{"a": "first", "b": "second"}, + {"a": "first", "b": "second"}, + {"a": "first", "b": "second"}] + }, + { + "expression": "foo.nested.three.{a: a, cinner: c.inner}", + "result": {"a": "first", "cinner": "third"} + }, + { + "expression": "foo.nested.three.{a: a, c: c.inner.bad.key}", + "result": {"a": "first", "c": null} + }, + { + "expression": "foo.{a: nested.one.a, b: nested.two.b}", + "result": {"a": "first", "b": "second"} + }, + { + "expression": "{bar: bar, baz: baz}", + "result": {"bar": 1, "baz": 2} + }, + { + "expression": "{bar: bar}", + "result": {"bar": 1} + }, + { + "expression": "{otherkey: bar}", + "result": {"otherkey": 1} + }, + { + "expression": "{no: no, exist: exist}", + "result": {"no": null, "exist": null} + }, + { + "expression": "foo.[bar]", + "result": ["bar"] + }, + { + "expression": "foo.[bar,baz]", + "result": ["bar", "baz"] + }, + { + "expression": "foo.[bar,qux]", + "result": ["bar", "qux"] + }, + { + "expression": "foo.[bar,noexist]", + "result": ["bar", null] + }, + { + "expression": "foo.[noexist,alsonoexist]", + "result": [null, null] + } + ] +}, { + "given": { + "foo": {"bar": 1, "baz": [2, 3, 4]} + }, + "cases": [ + { + "expression": "foo.{bar:bar,baz:baz}", + "result": {"bar": 1, "baz": [2, 3, 4]} + }, + { + "expression": "foo.[bar,baz[0]]", + "result": [1, 2] + }, + { + "expression": "foo.[bar,baz[1]]", + "result": [1, 3] + }, + { + "expression": "foo.[bar,baz[2]]", + "result": [1, 4] + }, + { + "expression": "foo.[bar,baz[3]]", + "result": [1, null] + }, + { + "expression": "foo.[bar[0],baz[3]]", + "result": [null, null] + } + ] +}, { + "given": { + "foo": {"bar": 1, "baz": 2} + }, + "cases": [ + { + "expression": "foo.{bar: bar, baz: baz}", + "result": {"bar": 1, "baz": 2} + }, + { + "expression": "foo.[bar,baz]", + "result": [1, 2] + } + ] +}, { + "given": { + "foo": { + "bar": {"baz": [{"common": "first", "one": 1}, + {"common": "second", "two": 2}]}, + "ignoreme": 1, + "includeme": true + } + }, + "cases": [ + { + "expression": "foo.{bar: bar.baz[1],includeme: includeme}", + "result": {"bar": {"common": "second", "two": 2}, "includeme": true} + }, + { + "expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}", + "result": {"bar.baz.two": 2, "includeme": true} + }, + { + "expression": "foo.[includeme, bar.baz[*].common]", + "result": [true, ["first", "second"]] + }, + { + "expression": "foo.[includeme, bar.baz[*].none]", + "result": [true, []] + }, + { + "expression": "foo.[includeme, bar.baz[].common]", + "result": [true, ["first", "second"]] + } + ] +}, { + "given": { + "reservations": [{ + "instances": [ + {"id": "id1", + "name": "first"}, + {"id": "id2", + "name": "second"} + ]}, { + "instances": [ + {"id": "id3", + "name": "third"}, + {"id": "id4", + "name": "fourth"} + ]} + ]}, + "cases": [ + { + "expression": "reservations[*].instances[*].{id: id, name: name}", + "result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}], + [{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]] + }, + { + "expression": "reservations[].instances[].{id: id, name: name}", + "result": [{"id": "id1", "name": "first"}, + {"id": "id2", "name": "second"}, + {"id": "id3", "name": "third"}, + {"id": "id4", "name": "fourth"}] + }, + { + "expression": "reservations[].instances[].[id, name]", + "result": [["id1", "first"], + ["id2", "second"], + ["id3", "third"], + ["id4", "fourth"]] + } + ] +}, +{ + "given": { + "foo": [{ + "bar": [ + { + "qux": 2, + "baz": 1 + }, + { + "qux": 4, + "baz": 3 + } + ] + }, + { + "bar": [ + { + "qux": 6, + "baz": 5 + }, + { + "qux": 8, + "baz": 7 + } + ] + } + ] + }, + "cases": [ + { + "expression": "foo", + "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]}, + {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}] + }, + { + "expression": "foo[]", + "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]}, + {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}] + }, + { + "expression": "foo[].bar", + "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}], + [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]] + }, + { + "expression": "foo[].bar[]", + "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}, + {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}] + }, + { + "expression": "foo[].bar[].[baz, qux]", + "result": [[1, 2], [3, 4], [5, 6], [7, 8]] + }, + { + "expression": "foo[].bar[].[baz]", + "result": [[1], [3], [5], [7]] + }, + { + "expression": "foo[].bar[].[baz, qux][]", + "result": [1, 2, 3, 4, 5, 6, 7, 8] + } + ] +}, +{ + "given": { + "foo": { + "baz": [ + { + "bar": "abc" + }, { + "bar": "def" + } + ], + "qux": ["zero"] + } + }, + "cases": [ + { + "expression": "foo.[baz[*].bar, qux[0]]", + "result": [["abc", "def"], "zero"] + } + ] +}, +{ + "given": { + "foo": { + "baz": [ + { + "bar": "a", + "bam": "b", + "boo": "c" + }, { + "bar": "d", + "bam": "e", + "boo": "f" + } + ], + "qux": ["zero"] + } + }, + "cases": [ + { + "expression": "foo.[baz[*].[bar, boo], qux[0]]", + "result": [[["a", "c" ], ["d", "f" ]], "zero"] + } + ] +}, +{ + "given": { + "foo": { + "baz": [ + { + "bar": "a", + "bam": "b", + "boo": "c" + }, { + "bar": "d", + "bam": "e", + "boo": "f" + } + ], + "qux": ["zero"] + } + }, + "cases": [ + { + "expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]", + "result": [["a", "d"], "zero"] + } + ] +}, +{ + "given": {"type": "object"}, + "cases": [ + { + "comment": "Nested multiselect", + "expression": "[[*],*]", + "result": [null, ["object"]] + } + ] +}, +{ + "given": [], + "cases": [ + { + "comment": "Nested multiselect", + "expression": "[[*]]", + "result": [[]] + } + ] +} +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json b/vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json new file mode 100644 index 000000000..2127cf441 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json @@ -0,0 +1,59 @@ +[{ + "given": + {"outer": {"foo": "foo", "bar": "bar", "baz": "baz"}}, + "cases": [ + { + "expression": "outer.foo || outer.bar", + "result": "foo" + }, + { + "expression": "outer.foo||outer.bar", + "result": "foo" + }, + { + "expression": "outer.bar || outer.baz", + "result": "bar" + }, + { + "expression": "outer.bar||outer.baz", + "result": "bar" + }, + { + "expression": "outer.bad || outer.foo", + "result": "foo" + }, + { + "expression": "outer.bad||outer.foo", + "result": "foo" + }, + { + "expression": "outer.foo || outer.bad", + "result": "foo" + }, + { + "expression": "outer.foo||outer.bad", + "result": "foo" + }, + { + "expression": "outer.bad || outer.alsobad", + "result": null + }, + { + "expression": "outer.bad||outer.alsobad", + "result": null + } + ] +}, { + "given": + {"outer": {"foo": "foo", "bool": false, "empty_list": [], "empty_string": ""}}, + "cases": [ + { + "expression": "outer.empty_string || outer.foo", + "result": "foo" + }, + { + "expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo", + "result": "foo" + } + ] +}] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/pipe.json b/vendor/github.com/jmespath/go-jmespath/compliance/pipe.json new file mode 100644 index 000000000..b10c0a496 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/pipe.json @@ -0,0 +1,131 @@ +[{ + "given": { + "foo": { + "bar": { + "baz": "subkey" + }, + "other": { + "baz": "subkey" + }, + "other2": { + "baz": "subkey" + }, + "other3": { + "notbaz": ["a", "b", "c"] + }, + "other4": { + "notbaz": ["a", "b", "c"] + } + } + }, + "cases": [ + { + "expression": "foo.*.baz | [0]", + "result": "subkey" + }, + { + "expression": "foo.*.baz | [1]", + "result": "subkey" + }, + { + "expression": "foo.*.baz | [2]", + "result": "subkey" + }, + { + "expression": "foo.bar.* | [0]", + "result": "subkey" + }, + { + "expression": "foo.*.notbaz | [*]", + "result": [["a", "b", "c"], ["a", "b", "c"]] + }, + { + "expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz", + "result": ["subkey", "subkey"] + } + ] +}, { + "given": { + "foo": { + "bar": { + "baz": "one" + }, + "other": { + "baz": "two" + }, + "other2": { + "baz": "three" + }, + "other3": { + "notbaz": ["a", "b", "c"] + }, + "other4": { + "notbaz": ["d", "e", "f"] + } + } + }, + "cases": [ + { + "expression": "foo | bar", + "result": {"baz": "one"} + }, + { + "expression": "foo | bar | baz", + "result": "one" + }, + { + "expression": "foo|bar| baz", + "result": "one" + }, + { + "expression": "not_there | [0]", + "result": null + }, + { + "expression": "not_there | [0]", + "result": null + }, + { + "expression": "[foo.bar, foo.other] | [0]", + "result": {"baz": "one"} + }, + { + "expression": "{\"a\": foo.bar, \"b\": foo.other} | a", + "result": {"baz": "one"} + }, + { + "expression": "{\"a\": foo.bar, \"b\": foo.other} | b", + "result": {"baz": "two"} + }, + { + "expression": "foo.bam || foo.bar | baz", + "result": "one" + }, + { + "expression": "foo | not_there || bar", + "result": {"baz": "one"} + } + ] +}, { + "given": { + "foo": [{ + "bar": [{ + "baz": "one" + }, { + "baz": "two" + }] + }, { + "bar": [{ + "baz": "three" + }, { + "baz": "four" + }] + }] + }, + "cases": [ + { + "expression": "foo[*].bar[*] | [0][0]", + "result": {"baz": "one"} + } + ] +}] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/slice.json b/vendor/github.com/jmespath/go-jmespath/compliance/slice.json new file mode 100644 index 000000000..359477278 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/slice.json @@ -0,0 +1,187 @@ +[{ + "given": { + "foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + "bar": { + "baz": 1 + } + }, + "cases": [ + { + "expression": "bar[0:10]", + "result": null + }, + { + "expression": "foo[0:10:1]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[0:10]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[0:10:]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[0::1]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[0::]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[0:]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[:10:1]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[::1]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[:10:]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[::]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[:]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[1:9]", + "result": [1, 2, 3, 4, 5, 6, 7, 8] + }, + { + "expression": "foo[0:10:2]", + "result": [0, 2, 4, 6, 8] + }, + { + "expression": "foo[5:]", + "result": [5, 6, 7, 8, 9] + }, + { + "expression": "foo[5::2]", + "result": [5, 7, 9] + }, + { + "expression": "foo[::2]", + "result": [0, 2, 4, 6, 8] + }, + { + "expression": "foo[::-1]", + "result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + "expression": "foo[1::2]", + "result": [1, 3, 5, 7, 9] + }, + { + "expression": "foo[10:0:-1]", + "result": [9, 8, 7, 6, 5, 4, 3, 2, 1] + }, + { + "expression": "foo[10:5:-1]", + "result": [9, 8, 7, 6] + }, + { + "expression": "foo[8:2:-2]", + "result": [8, 6, 4] + }, + { + "expression": "foo[0:20]", + "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + }, + { + "expression": "foo[10:-20:-1]", + "result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + "expression": "foo[10:-20]", + "result": [] + }, + { + "expression": "foo[-4:-1]", + "result": [6, 7, 8] + }, + { + "expression": "foo[:-5:-1]", + "result": [9, 8, 7, 6] + }, + { + "expression": "foo[8:2:0]", + "error": "invalid-value" + }, + { + "expression": "foo[8:2:0:1]", + "error": "syntax" + }, + { + "expression": "foo[8:2&]", + "error": "syntax" + }, + { + "expression": "foo[2:a:3]", + "error": "syntax" + } + ] +}, { + "given": { + "foo": [{"a": 1}, {"a": 2}, {"a": 3}], + "bar": [{"a": {"b": 1}}, {"a": {"b": 2}}, + {"a": {"b": 3}}], + "baz": 50 + }, + "cases": [ + { + "expression": "foo[:2].a", + "result": [1, 2] + }, + { + "expression": "foo[:2].b", + "result": [] + }, + { + "expression": "foo[:2].a.b", + "result": [] + }, + { + "expression": "bar[::-1].a.b", + "result": [3, 2, 1] + }, + { + "expression": "bar[:2].a.b", + "result": [1, 2] + }, + { + "expression": "baz[:2].a", + "result": null + } + ] +}, { + "given": [{"a": 1}, {"a": 2}, {"a": 3}], + "cases": [ + { + "expression": "[:]", + "result": [{"a": 1}, {"a": 2}, {"a": 3}] + }, + { + "expression": "[:2].a", + "result": [1, 2] + }, + { + "expression": "[::-1].a", + "result": [3, 2, 1] + }, + { + "expression": "[:2].b", + "result": [] + } + ] +}] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/syntax.json b/vendor/github.com/jmespath/go-jmespath/compliance/syntax.json new file mode 100644 index 000000000..003c29458 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/syntax.json @@ -0,0 +1,616 @@ +[{ + "comment": "Dot syntax", + "given": {"type": "object"}, + "cases": [ + { + "expression": "foo.bar", + "result": null + }, + { + "expression": "foo.1", + "error": "syntax" + }, + { + "expression": "foo.-11", + "error": "syntax" + }, + { + "expression": "foo", + "result": null + }, + { + "expression": "foo.", + "error": "syntax" + }, + { + "expression": "foo.", + "error": "syntax" + }, + { + "expression": ".foo", + "error": "syntax" + }, + { + "expression": "foo..bar", + "error": "syntax" + }, + { + "expression": "foo.bar.", + "error": "syntax" + }, + { + "expression": "foo[.]", + "error": "syntax" + } + ] +}, + { + "comment": "Simple token errors", + "given": {"type": "object"}, + "cases": [ + { + "expression": ".", + "error": "syntax" + }, + { + "expression": ":", + "error": "syntax" + }, + { + "expression": ",", + "error": "syntax" + }, + { + "expression": "]", + "error": "syntax" + }, + { + "expression": "[", + "error": "syntax" + }, + { + "expression": "}", + "error": "syntax" + }, + { + "expression": "{", + "error": "syntax" + }, + { + "expression": ")", + "error": "syntax" + }, + { + "expression": "(", + "error": "syntax" + }, + { + "expression": "((&", + "error": "syntax" + }, + { + "expression": "a[", + "error": "syntax" + }, + { + "expression": "a]", + "error": "syntax" + }, + { + "expression": "a][", + "error": "syntax" + }, + { + "expression": "!", + "error": "syntax" + } + ] + }, + { + "comment": "Boolean syntax errors", + "given": {"type": "object"}, + "cases": [ + { + "expression": "![!(!", + "error": "syntax" + } + ] + }, + { + "comment": "Wildcard syntax", + "given": {"type": "object"}, + "cases": [ + { + "expression": "*", + "result": ["object"] + }, + { + "expression": "*.*", + "result": [] + }, + { + "expression": "*.foo", + "result": [] + }, + { + "expression": "*[0]", + "result": [] + }, + { + "expression": ".*", + "error": "syntax" + }, + { + "expression": "*foo", + "error": "syntax" + }, + { + "expression": "*0", + "error": "syntax" + }, + { + "expression": "foo[*]bar", + "error": "syntax" + }, + { + "expression": "foo[*]*", + "error": "syntax" + } + ] + }, + { + "comment": "Flatten syntax", + "given": {"type": "object"}, + "cases": [ + { + "expression": "[]", + "result": null + } + ] + }, + { + "comment": "Simple bracket syntax", + "given": {"type": "object"}, + "cases": [ + { + "expression": "[0]", + "result": null + }, + { + "expression": "[*]", + "result": null + }, + { + "expression": "*.[0]", + "error": "syntax" + }, + { + "expression": "*.[\"0\"]", + "result": [[null]] + }, + { + "expression": "[*].bar", + "result": null + }, + { + "expression": "[*][0]", + "result": null + }, + { + "expression": "foo[#]", + "error": "syntax" + } + ] + }, + { + "comment": "Multi-select list syntax", + "given": {"type": "object"}, + "cases": [ + { + "expression": "foo[0]", + "result": null + }, + { + "comment": "Valid multi-select of a list", + "expression": "foo[0, 1]", + "error": "syntax" + }, + { + "expression": "foo.[0]", + "error": "syntax" + }, + { + "expression": "foo.[*]", + "result": null + }, + { + "comment": "Multi-select of a list with trailing comma", + "expression": "foo[0, ]", + "error": "syntax" + }, + { + "comment": "Multi-select of a list with trailing comma and no close", + "expression": "foo[0,", + "error": "syntax" + }, + { + "comment": "Multi-select of a list with trailing comma and no close", + "expression": "foo.[a", + "error": "syntax" + }, + { + "comment": "Multi-select of a list with extra comma", + "expression": "foo[0,, 1]", + "error": "syntax" + }, + { + "comment": "Multi-select of a list using an identifier index", + "expression": "foo[abc]", + "error": "syntax" + }, + { + "comment": "Multi-select of a list using identifier indices", + "expression": "foo[abc, def]", + "error": "syntax" + }, + { + "comment": "Multi-select of a list using an identifier index", + "expression": "foo[abc, 1]", + "error": "syntax" + }, + { + "comment": "Multi-select of a list using an identifier index with trailing comma", + "expression": "foo[abc, ]", + "error": "syntax" + }, + { + "comment": "Valid multi-select of a hash using an identifier index", + "expression": "foo.[abc]", + "result": null + }, + { + "comment": "Valid multi-select of a hash", + "expression": "foo.[abc, def]", + "result": null + }, + { + "comment": "Multi-select of a hash using a numeric index", + "expression": "foo.[abc, 1]", + "error": "syntax" + }, + { + "comment": "Multi-select of a hash with a trailing comma", + "expression": "foo.[abc, ]", + "error": "syntax" + }, + { + "comment": "Multi-select of a hash with extra commas", + "expression": "foo.[abc,, def]", + "error": "syntax" + }, + { + "comment": "Multi-select of a hash using number indices", + "expression": "foo.[0, 1]", + "error": "syntax" + } + ] + }, + { + "comment": "Multi-select hash syntax", + "given": {"type": "object"}, + "cases": [ + { + "comment": "No key or value", + "expression": "a{}", + "error": "syntax" + }, + { + "comment": "No closing token", + "expression": "a{", + "error": "syntax" + }, + { + "comment": "Not a key value pair", + "expression": "a{foo}", + "error": "syntax" + }, + { + "comment": "Missing value and closing character", + "expression": "a{foo:", + "error": "syntax" + }, + { + "comment": "Missing closing character", + "expression": "a{foo: 0", + "error": "syntax" + }, + { + "comment": "Missing value", + "expression": "a{foo:}", + "error": "syntax" + }, + { + "comment": "Trailing comma and no closing character", + "expression": "a{foo: 0, ", + "error": "syntax" + }, + { + "comment": "Missing value with trailing comma", + "expression": "a{foo: ,}", + "error": "syntax" + }, + { + "comment": "Accessing Array using an identifier", + "expression": "a{foo: bar}", + "error": "syntax" + }, + { + "expression": "a{foo: 0}", + "error": "syntax" + }, + { + "comment": "Missing key-value pair", + "expression": "a.{}", + "error": "syntax" + }, + { + "comment": "Not a key-value pair", + "expression": "a.{foo}", + "error": "syntax" + }, + { + "comment": "Missing value", + "expression": "a.{foo:}", + "error": "syntax" + }, + { + "comment": "Missing value with trailing comma", + "expression": "a.{foo: ,}", + "error": "syntax" + }, + { + "comment": "Valid multi-select hash extraction", + "expression": "a.{foo: bar}", + "result": null + }, + { + "comment": "Valid multi-select hash extraction", + "expression": "a.{foo: bar, baz: bam}", + "result": null + }, + { + "comment": "Trailing comma", + "expression": "a.{foo: bar, }", + "error": "syntax" + }, + { + "comment": "Missing key in second key-value pair", + "expression": "a.{foo: bar, baz}", + "error": "syntax" + }, + { + "comment": "Missing value in second key-value pair", + "expression": "a.{foo: bar, baz:}", + "error": "syntax" + }, + { + "comment": "Trailing comma", + "expression": "a.{foo: bar, baz: bam, }", + "error": "syntax" + }, + { + "comment": "Nested multi select", + "expression": "{\"\\\\\":{\" \":*}}", + "result": {"\\": {" ": ["object"]}} + } + ] + }, + { + "comment": "Or expressions", + "given": {"type": "object"}, + "cases": [ + { + "expression": "foo || bar", + "result": null + }, + { + "expression": "foo ||", + "error": "syntax" + }, + { + "expression": "foo.|| bar", + "error": "syntax" + }, + { + "expression": " || foo", + "error": "syntax" + }, + { + "expression": "foo || || foo", + "error": "syntax" + }, + { + "expression": "foo.[a || b]", + "result": null + }, + { + "expression": "foo.[a ||]", + "error": "syntax" + }, + { + "expression": "\"foo", + "error": "syntax" + } + ] + }, + { + "comment": "Filter expressions", + "given": {"type": "object"}, + "cases": [ + { + "expression": "foo[?bar==`\"baz\"`]", + "result": null + }, + { + "expression": "foo[? bar == `\"baz\"` ]", + "result": null + }, + { + "expression": "foo[ ?bar==`\"baz\"`]", + "error": "syntax" + }, + { + "expression": "foo[?bar==]", + "error": "syntax" + }, + { + "expression": "foo[?==]", + "error": "syntax" + }, + { + "expression": "foo[?==bar]", + "error": "syntax" + }, + { + "expression": "foo[?bar==baz?]", + "error": "syntax" + }, + { + "expression": "foo[?a.b.c==d.e.f]", + "result": null + }, + { + "expression": "foo[?bar==`[0, 1, 2]`]", + "result": null + }, + { + "expression": "foo[?bar==`[\"a\", \"b\", \"c\"]`]", + "result": null + }, + { + "comment": "Literal char not escaped", + "expression": "foo[?bar==`[\"foo`bar\"]`]", + "error": "syntax" + }, + { + "comment": "Literal char escaped", + "expression": "foo[?bar==`[\"foo\\`bar\"]`]", + "result": null + }, + { + "comment": "Unknown comparator", + "expression": "foo[?bar<>baz]", + "error": "syntax" + }, + { + "comment": "Unknown comparator", + "expression": "foo[?bar^baz]", + "error": "syntax" + }, + { + "expression": "foo[bar==baz]", + "error": "syntax" + }, + { + "comment": "Quoted identifier in filter expression no spaces", + "expression": "[?\"\\\\\">`\"foo\"`]", + "result": null + }, + { + "comment": "Quoted identifier in filter expression with spaces", + "expression": "[?\"\\\\\" > `\"foo\"`]", + "result": null + } + ] + }, + { + "comment": "Filter expression errors", + "given": {"type": "object"}, + "cases": [ + { + "expression": "bar.`\"anything\"`", + "error": "syntax" + }, + { + "expression": "bar.baz.noexists.`\"literal\"`", + "error": "syntax" + }, + { + "comment": "Literal wildcard projection", + "expression": "foo[*].`\"literal\"`", + "error": "syntax" + }, + { + "expression": "foo[*].name.`\"literal\"`", + "error": "syntax" + }, + { + "expression": "foo[].name.`\"literal\"`", + "error": "syntax" + }, + { + "expression": "foo[].name.`\"literal\"`.`\"subliteral\"`", + "error": "syntax" + }, + { + "comment": "Projecting a literal onto an empty list", + "expression": "foo[*].name.noexist.`\"literal\"`", + "error": "syntax" + }, + { + "expression": "foo[].name.noexist.`\"literal\"`", + "error": "syntax" + }, + { + "expression": "twolen[*].`\"foo\"`", + "error": "syntax" + }, + { + "comment": "Two level projection of a literal", + "expression": "twolen[*].threelen[*].`\"bar\"`", + "error": "syntax" + }, + { + "comment": "Two level flattened projection of a literal", + "expression": "twolen[].threelen[].`\"bar\"`", + "error": "syntax" + } + ] + }, + { + "comment": "Identifiers", + "given": {"type": "object"}, + "cases": [ + { + "expression": "foo", + "result": null + }, + { + "expression": "\"foo\"", + "result": null + }, + { + "expression": "\"\\\\\"", + "result": null + } + ] + }, + { + "comment": "Combined syntax", + "given": [], + "cases": [ + { + "expression": "*||*|*|*", + "result": null + }, + { + "expression": "*[]||[*]", + "result": [] + }, + { + "expression": "[*.*]", + "result": [null] + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/unicode.json b/vendor/github.com/jmespath/go-jmespath/compliance/unicode.json new file mode 100644 index 000000000..6b07b0b6d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/unicode.json @@ -0,0 +1,38 @@ +[ + { + "given": {"foo": [{"✓": "✓"}, {"✓": "✗"}]}, + "cases": [ + { + "expression": "foo[].\"✓\"", + "result": ["✓", "✗"] + } + ] + }, + { + "given": {"☯": true}, + "cases": [ + { + "expression": "\"☯\"", + "result": true + } + ] + }, + { + "given": {"♪♫•*¨*•.¸¸â¤Â¸Â¸.•*¨*•♫♪": true}, + "cases": [ + { + "expression": "\"♪♫•*¨*•.¸¸â¤Â¸Â¸.•*¨*•♫♪\"", + "result": true + } + ] + }, + { + "given": {"☃": true}, + "cases": [ + { + "expression": "\"☃\"", + "result": true + } + ] + } +] diff --git a/vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json b/vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json new file mode 100644 index 000000000..3bcec3028 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json @@ -0,0 +1,460 @@ +[{ + "given": { + "foo": { + "bar": { + "baz": "val" + }, + "other": { + "baz": "val" + }, + "other2": { + "baz": "val" + }, + "other3": { + "notbaz": ["a", "b", "c"] + }, + "other4": { + "notbaz": ["a", "b", "c"] + }, + "other5": { + "other": { + "a": 1, + "b": 1, + "c": 1 + } + } + } + }, + "cases": [ + { + "expression": "foo.*.baz", + "result": ["val", "val", "val"] + }, + { + "expression": "foo.bar.*", + "result": ["val"] + }, + { + "expression": "foo.*.notbaz", + "result": [["a", "b", "c"], ["a", "b", "c"]] + }, + { + "expression": "foo.*.notbaz[0]", + "result": ["a", "a"] + }, + { + "expression": "foo.*.notbaz[-1]", + "result": ["c", "c"] + } + ] +}, { + "given": { + "foo": { + "first-1": { + "second-1": "val" + }, + "first-2": { + "second-1": "val" + }, + "first-3": { + "second-1": "val" + } + } + }, + "cases": [ + { + "expression": "foo.*", + "result": [{"second-1": "val"}, {"second-1": "val"}, + {"second-1": "val"}] + }, + { + "expression": "foo.*.*", + "result": [["val"], ["val"], ["val"]] + }, + { + "expression": "foo.*.*.*", + "result": [[], [], []] + }, + { + "expression": "foo.*.*.*.*", + "result": [[], [], []] + } + ] +}, { + "given": { + "foo": { + "bar": "one" + }, + "other": { + "bar": "one" + }, + "nomatch": { + "notbar": "three" + } + }, + "cases": [ + { + "expression": "*.bar", + "result": ["one", "one"] + } + ] +}, { + "given": { + "top1": { + "sub1": {"foo": "one"} + }, + "top2": { + "sub1": {"foo": "one"} + } + }, + "cases": [ + { + "expression": "*", + "result": [{"sub1": {"foo": "one"}}, + {"sub1": {"foo": "one"}}] + }, + { + "expression": "*.sub1", + "result": [{"foo": "one"}, + {"foo": "one"}] + }, + { + "expression": "*.*", + "result": [[{"foo": "one"}], + [{"foo": "one"}]] + }, + { + "expression": "*.*.foo[]", + "result": ["one", "one"] + }, + { + "expression": "*.sub1.foo", + "result": ["one", "one"] + } + ] +}, +{ + "given": + {"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]}, + "cases": [ + { + "expression": "foo[*].bar", + "result": ["one", "two", "three"] + }, + { + "expression": "foo[*].notbar", + "result": ["four"] + } + ] +}, +{ + "given": + [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}], + "cases": [ + { + "expression": "[*]", + "result": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}] + }, + { + "expression": "[*].bar", + "result": ["one", "two", "three"] + }, + { + "expression": "[*].notbar", + "result": ["four"] + } + ] +}, +{ + "given": { + "foo": { + "bar": [ + {"baz": ["one", "two", "three"]}, + {"baz": ["four", "five", "six"]}, + {"baz": ["seven", "eight", "nine"]} + ] + } + }, + "cases": [ + { + "expression": "foo.bar[*].baz", + "result": [["one", "two", "three"], ["four", "five", "six"], ["seven", "eight", "nine"]] + }, + { + "expression": "foo.bar[*].baz[0]", + "result": ["one", "four", "seven"] + }, + { + "expression": "foo.bar[*].baz[1]", + "result": ["two", "five", "eight"] + }, + { + "expression": "foo.bar[*].baz[2]", + "result": ["three", "six", "nine"] + }, + { + "expression": "foo.bar[*].baz[3]", + "result": [] + } + ] +}, +{ + "given": { + "foo": { + "bar": [["one", "two"], ["three", "four"]] + } + }, + "cases": [ + { + "expression": "foo.bar[*]", + "result": [["one", "two"], ["three", "four"]] + }, + { + "expression": "foo.bar[0]", + "result": ["one", "two"] + }, + { + "expression": "foo.bar[0][0]", + "result": "one" + }, + { + "expression": "foo.bar[0][0][0]", + "result": null + }, + { + "expression": "foo.bar[0][0][0][0]", + "result": null + }, + { + "expression": "foo[0][0]", + "result": null + } + ] +}, +{ + "given": { + "foo": [ + {"bar": [{"kind": "basic"}, {"kind": "intermediate"}]}, + {"bar": [{"kind": "advanced"}, {"kind": "expert"}]}, + {"bar": "string"} + ] + + }, + "cases": [ + { + "expression": "foo[*].bar[*].kind", + "result": [["basic", "intermediate"], ["advanced", "expert"]] + }, + { + "expression": "foo[*].bar[0].kind", + "result": ["basic", "advanced"] + } + ] +}, +{ + "given": { + "foo": [ + {"bar": {"kind": "basic"}}, + {"bar": {"kind": "intermediate"}}, + {"bar": {"kind": "advanced"}}, + {"bar": {"kind": "expert"}}, + {"bar": "string"} + ] + }, + "cases": [ + { + "expression": "foo[*].bar.kind", + "result": ["basic", "intermediate", "advanced", "expert"] + } + ] +}, +{ + "given": { + "foo": [{"bar": ["one", "two"]}, {"bar": ["three", "four"]}, {"bar": ["five"]}] + }, + "cases": [ + { + "expression": "foo[*].bar[0]", + "result": ["one", "three", "five"] + }, + { + "expression": "foo[*].bar[1]", + "result": ["two", "four"] + }, + { + "expression": "foo[*].bar[2]", + "result": [] + } + ] +}, +{ + "given": { + "foo": [{"bar": []}, {"bar": []}, {"bar": []}] + }, + "cases": [ + { + "expression": "foo[*].bar[0]", + "result": [] + } + ] +}, +{ + "given": { + "foo": [["one", "two"], ["three", "four"], ["five"]] + }, + "cases": [ + { + "expression": "foo[*][0]", + "result": ["one", "three", "five"] + }, + { + "expression": "foo[*][1]", + "result": ["two", "four"] + } + ] +}, +{ + "given": { + "foo": [ + [ + ["one", "two"], ["three", "four"] + ], [ + ["five", "six"], ["seven", "eight"] + ], [ + ["nine"], ["ten"] + ] + ] + }, + "cases": [ + { + "expression": "foo[*][0]", + "result": [["one", "two"], ["five", "six"], ["nine"]] + }, + { + "expression": "foo[*][1]", + "result": [["three", "four"], ["seven", "eight"], ["ten"]] + }, + { + "expression": "foo[*][0][0]", + "result": ["one", "five", "nine"] + }, + { + "expression": "foo[*][1][0]", + "result": ["three", "seven", "ten"] + }, + { + "expression": "foo[*][0][1]", + "result": ["two", "six"] + }, + { + "expression": "foo[*][1][1]", + "result": ["four", "eight"] + }, + { + "expression": "foo[*][2]", + "result": [] + }, + { + "expression": "foo[*][2][2]", + "result": [] + }, + { + "expression": "bar[*]", + "result": null + }, + { + "expression": "bar[*].baz[*]", + "result": null + } + ] +}, +{ + "given": { + "string": "string", + "hash": {"foo": "bar", "bar": "baz"}, + "number": 23, + "nullvalue": null + }, + "cases": [ + { + "expression": "string[*]", + "result": null + }, + { + "expression": "hash[*]", + "result": null + }, + { + "expression": "number[*]", + "result": null + }, + { + "expression": "nullvalue[*]", + "result": null + }, + { + "expression": "string[*].foo", + "result": null + }, + { + "expression": "hash[*].foo", + "result": null + }, + { + "expression": "number[*].foo", + "result": null + }, + { + "expression": "nullvalue[*].foo", + "result": null + }, + { + "expression": "nullvalue[*].foo[*].bar", + "result": null + } + ] +}, +{ + "given": { + "string": "string", + "hash": {"foo": "val", "bar": "val"}, + "number": 23, + "array": [1, 2, 3], + "nullvalue": null + }, + "cases": [ + { + "expression": "string.*", + "result": null + }, + { + "expression": "hash.*", + "result": ["val", "val"] + }, + { + "expression": "number.*", + "result": null + }, + { + "expression": "array.*", + "result": null + }, + { + "expression": "nullvalue.*", + "result": null + } + ] +}, +{ + "given": { + "a": [0, 1, 2], + "b": [0, 1, 2] + }, + "cases": [ + { + "expression": "*[0]", + "result": [0, 0] + } + ] +} +] diff --git a/vendor/github.com/jmespath/go-jmespath/functions.go b/vendor/github.com/jmespath/go-jmespath/functions.go new file mode 100644 index 000000000..8a3f2ef0d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/functions.go @@ -0,0 +1,840 @@ +package jmespath + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "sort" + "strconv" + "strings" + "unicode/utf8" +) + +type jpFunction func(arguments []interface{}) (interface{}, error) + +type jpType string + +const ( + jpUnknown jpType = "unknown" + jpNumber jpType = "number" + jpString jpType = "string" + jpArray jpType = "array" + jpObject jpType = "object" + jpArrayNumber jpType = "array[number]" + jpArrayString jpType = "array[string]" + jpExpref jpType = "expref" + jpAny jpType = "any" +) + +type functionEntry struct { + name string + arguments []argSpec + handler jpFunction + hasExpRef bool +} + +type argSpec struct { + types []jpType + variadic bool +} + +type byExprString struct { + intr *treeInterpreter + node ASTNode + items []interface{} + hasError bool +} + +func (a *byExprString) Len() int { + return len(a.items) +} +func (a *byExprString) Swap(i, j int) { + a.items[i], a.items[j] = a.items[j], a.items[i] +} +func (a *byExprString) Less(i, j int) bool { + first, err := a.intr.Execute(a.node, a.items[i]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + ith, ok := first.(string) + if !ok { + a.hasError = true + return true + } + second, err := a.intr.Execute(a.node, a.items[j]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + jth, ok := second.(string) + if !ok { + a.hasError = true + return true + } + return ith < jth +} + +type byExprFloat struct { + intr *treeInterpreter + node ASTNode + items []interface{} + hasError bool +} + +func (a *byExprFloat) Len() int { + return len(a.items) +} +func (a *byExprFloat) Swap(i, j int) { + a.items[i], a.items[j] = a.items[j], a.items[i] +} +func (a *byExprFloat) Less(i, j int) bool { + first, err := a.intr.Execute(a.node, a.items[i]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + ith, ok := first.(float64) + if !ok { + a.hasError = true + return true + } + second, err := a.intr.Execute(a.node, a.items[j]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + jth, ok := second.(float64) + if !ok { + a.hasError = true + return true + } + return ith < jth +} + +type functionCaller struct { + functionTable map[string]functionEntry +} + +func newFunctionCaller() *functionCaller { + caller := &functionCaller{} + caller.functionTable = map[string]functionEntry{ + "length": functionEntry{ + name: "length", + arguments: []argSpec{ + argSpec{types: []jpType{jpString, jpArray, jpObject}}, + }, + handler: jpfLength, + }, + "starts_with": functionEntry{ + name: "starts_with", + arguments: []argSpec{ + argSpec{types: []jpType{jpString}}, + argSpec{types: []jpType{jpString}}, + }, + handler: jpfStartsWith, + }, + "abs": functionEntry{ + name: "abs", + arguments: []argSpec{ + argSpec{types: []jpType{jpNumber}}, + }, + handler: jpfAbs, + }, + "avg": functionEntry{ + name: "avg", + arguments: []argSpec{ + argSpec{types: []jpType{jpArrayNumber}}, + }, + handler: jpfAvg, + }, + "ceil": functionEntry{ + name: "ceil", + arguments: []argSpec{ + argSpec{types: []jpType{jpNumber}}, + }, + handler: jpfCeil, + }, + "contains": functionEntry{ + name: "contains", + arguments: []argSpec{ + argSpec{types: []jpType{jpArray, jpString}}, + argSpec{types: []jpType{jpAny}}, + }, + handler: jpfContains, + }, + "ends_with": functionEntry{ + name: "ends_with", + arguments: []argSpec{ + argSpec{types: []jpType{jpString}}, + argSpec{types: []jpType{jpString}}, + }, + handler: jpfEndsWith, + }, + "floor": functionEntry{ + name: "floor", + arguments: []argSpec{ + argSpec{types: []jpType{jpNumber}}, + }, + handler: jpfFloor, + }, + "map": functionEntry{ + name: "amp", + arguments: []argSpec{ + argSpec{types: []jpType{jpExpref}}, + argSpec{types: []jpType{jpArray}}, + }, + handler: jpfMap, + hasExpRef: true, + }, + "max": functionEntry{ + name: "max", + arguments: []argSpec{ + argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, + }, + handler: jpfMax, + }, + "merge": functionEntry{ + name: "merge", + arguments: []argSpec{ + argSpec{types: []jpType{jpObject}, variadic: true}, + }, + handler: jpfMerge, + }, + "max_by": functionEntry{ + name: "max_by", + arguments: []argSpec{ + argSpec{types: []jpType{jpArray}}, + argSpec{types: []jpType{jpExpref}}, + }, + handler: jpfMaxBy, + hasExpRef: true, + }, + "sum": functionEntry{ + name: "sum", + arguments: []argSpec{ + argSpec{types: []jpType{jpArrayNumber}}, + }, + handler: jpfSum, + }, + "min": functionEntry{ + name: "min", + arguments: []argSpec{ + argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, + }, + handler: jpfMin, + }, + "min_by": functionEntry{ + name: "min_by", + arguments: []argSpec{ + argSpec{types: []jpType{jpArray}}, + argSpec{types: []jpType{jpExpref}}, + }, + handler: jpfMinBy, + hasExpRef: true, + }, + "type": functionEntry{ + name: "type", + arguments: []argSpec{ + argSpec{types: []jpType{jpAny}}, + }, + handler: jpfType, + }, + "keys": functionEntry{ + name: "keys", + arguments: []argSpec{ + argSpec{types: []jpType{jpObject}}, + }, + handler: jpfKeys, + }, + "values": functionEntry{ + name: "values", + arguments: []argSpec{ + argSpec{types: []jpType{jpObject}}, + }, + handler: jpfValues, + }, + "sort": functionEntry{ + name: "sort", + arguments: []argSpec{ + argSpec{types: []jpType{jpArrayString, jpArrayNumber}}, + }, + handler: jpfSort, + }, + "sort_by": functionEntry{ + name: "sort_by", + arguments: []argSpec{ + argSpec{types: []jpType{jpArray}}, + argSpec{types: []jpType{jpExpref}}, + }, + handler: jpfSortBy, + hasExpRef: true, + }, + "join": functionEntry{ + name: "join", + arguments: []argSpec{ + argSpec{types: []jpType{jpString}}, + argSpec{types: []jpType{jpArrayString}}, + }, + handler: jpfJoin, + }, + "reverse": functionEntry{ + name: "reverse", + arguments: []argSpec{ + argSpec{types: []jpType{jpArray, jpString}}, + }, + handler: jpfReverse, + }, + "to_array": functionEntry{ + name: "to_array", + arguments: []argSpec{ + argSpec{types: []jpType{jpAny}}, + }, + handler: jpfToArray, + }, + "to_string": functionEntry{ + name: "to_string", + arguments: []argSpec{ + argSpec{types: []jpType{jpAny}}, + }, + handler: jpfToString, + }, + "to_number": functionEntry{ + name: "to_number", + arguments: []argSpec{ + argSpec{types: []jpType{jpAny}}, + }, + handler: jpfToNumber, + }, + "not_null": functionEntry{ + name: "not_null", + arguments: []argSpec{ + argSpec{types: []jpType{jpAny}, variadic: true}, + }, + handler: jpfNotNull, + }, + } + return caller +} + +func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) { + if len(e.arguments) == 0 { + return arguments, nil + } + if !e.arguments[len(e.arguments)-1].variadic { + if len(e.arguments) != len(arguments) { + return nil, errors.New("incorrect number of args") + } + for i, spec := range e.arguments { + userArg := arguments[i] + err := spec.typeCheck(userArg) + if err != nil { + return nil, err + } + } + return arguments, nil + } + if len(arguments) < len(e.arguments) { + return nil, errors.New("Invalid arity.") + } + return arguments, nil +} + +func (a *argSpec) typeCheck(arg interface{}) error { + for _, t := range a.types { + switch t { + case jpNumber: + if _, ok := arg.(float64); ok { + return nil + } + case jpString: + if _, ok := arg.(string); ok { + return nil + } + case jpArray: + if _, ok := arg.([]interface{}); ok { + return nil + } + case jpObject: + if _, ok := arg.(map[string]interface{}); ok { + return nil + } + case jpArrayNumber: + if _, ok := toArrayNum(arg); ok { + return nil + } + case jpArrayString: + if _, ok := toArrayStr(arg); ok { + return nil + } + case jpAny: + return nil + case jpExpref: + if _, ok := arg.(expRef); ok { + return nil + } + } + } + return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types) +} + +func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) { + entry, ok := f.functionTable[name] + if !ok { + return nil, errors.New("unknown function: " + name) + } + resolvedArgs, err := entry.resolveArgs(arguments) + if err != nil { + return nil, err + } + if entry.hasExpRef { + var extra []interface{} + extra = append(extra, intr) + resolvedArgs = append(extra, resolvedArgs...) + } + return entry.handler(resolvedArgs) +} + +func jpfAbs(arguments []interface{}) (interface{}, error) { + num := arguments[0].(float64) + return math.Abs(num), nil +} + +func jpfLength(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if c, ok := arg.(string); ok { + return float64(utf8.RuneCountInString(c)), nil + } else if c, ok := arg.([]interface{}); ok { + return float64(len(c)), nil + } else if c, ok := arg.(map[string]interface{}); ok { + return float64(len(c)), nil + } + return nil, errors.New("could not compute length()") +} + +func jpfStartsWith(arguments []interface{}) (interface{}, error) { + search := arguments[0].(string) + prefix := arguments[1].(string) + return strings.HasPrefix(search, prefix), nil +} + +func jpfAvg(arguments []interface{}) (interface{}, error) { + // We've already type checked the value so we can safely use + // type assertions. + args := arguments[0].([]interface{}) + length := float64(len(args)) + numerator := 0.0 + for _, n := range args { + numerator += n.(float64) + } + return numerator / length, nil +} +func jpfCeil(arguments []interface{}) (interface{}, error) { + val := arguments[0].(float64) + return math.Ceil(val), nil +} +func jpfContains(arguments []interface{}) (interface{}, error) { + search := arguments[0] + el := arguments[1] + if searchStr, ok := search.(string); ok { + if elStr, ok := el.(string); ok { + return strings.Index(searchStr, elStr) != -1, nil + } + return false, nil + } + // Otherwise this is a generic contains for []interface{} + general := search.([]interface{}) + for _, item := range general { + if item == el { + return true, nil + } + } + return false, nil +} +func jpfEndsWith(arguments []interface{}) (interface{}, error) { + search := arguments[0].(string) + suffix := arguments[1].(string) + return strings.HasSuffix(search, suffix), nil +} +func jpfFloor(arguments []interface{}) (interface{}, error) { + val := arguments[0].(float64) + return math.Floor(val), nil +} +func jpfMap(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + exp := arguments[1].(expRef) + node := exp.ref + arr := arguments[2].([]interface{}) + mapped := make([]interface{}, 0, len(arr)) + for _, value := range arr { + current, err := intr.Execute(node, value) + if err != nil { + return nil, err + } + mapped = append(mapped, current) + } + return mapped, nil +} +func jpfMax(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item > best { + best = item + } + } + return best, nil + } + // Otherwise we're dealing with a max() of strings. + items, _ := toArrayStr(arguments[0]) + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item > best { + best = item + } + } + return best, nil +} +func jpfMerge(arguments []interface{}) (interface{}, error) { + final := make(map[string]interface{}) + for _, m := range arguments { + mapped := m.(map[string]interface{}) + for key, value := range mapped { + final[key] = value + } + } + return final, nil +} +func jpfMaxBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return nil, nil + } else if len(arr) == 1 { + return arr[0], nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + switch t := start.(type) { + case float64: + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(float64) + if !ok { + return nil, errors.New("invalid type, must be number") + } + if current > bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + case string: + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(string) + if !ok { + return nil, errors.New("invalid type, must be string") + } + if current > bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + default: + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfSum(arguments []interface{}) (interface{}, error) { + items, _ := toArrayNum(arguments[0]) + sum := 0.0 + for _, item := range items { + sum += item + } + return sum, nil +} + +func jpfMin(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item < best { + best = item + } + } + return best, nil + } + items, _ := toArrayStr(arguments[0]) + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item < best { + best = item + } + } + return best, nil +} + +func jpfMinBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return nil, nil + } else if len(arr) == 1 { + return arr[0], nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + if t, ok := start.(float64); ok { + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(float64) + if !ok { + return nil, errors.New("invalid type, must be number") + } + if current < bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + } else if t, ok := start.(string); ok { + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(string) + if !ok { + return nil, errors.New("invalid type, must be string") + } + if current < bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + } else { + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfType(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if _, ok := arg.(float64); ok { + return "number", nil + } + if _, ok := arg.(string); ok { + return "string", nil + } + if _, ok := arg.([]interface{}); ok { + return "array", nil + } + if _, ok := arg.(map[string]interface{}); ok { + return "object", nil + } + if arg == nil { + return "null", nil + } + if arg == true || arg == false { + return "boolean", nil + } + return nil, errors.New("unknown type") +} +func jpfKeys(arguments []interface{}) (interface{}, error) { + arg := arguments[0].(map[string]interface{}) + collected := make([]interface{}, 0, len(arg)) + for key := range arg { + collected = append(collected, key) + } + return collected, nil +} +func jpfValues(arguments []interface{}) (interface{}, error) { + arg := arguments[0].(map[string]interface{}) + collected := make([]interface{}, 0, len(arg)) + for _, value := range arg { + collected = append(collected, value) + } + return collected, nil +} +func jpfSort(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + d := sort.Float64Slice(items) + sort.Stable(d) + final := make([]interface{}, len(d)) + for i, val := range d { + final[i] = val + } + return final, nil + } + // Otherwise we're dealing with sort()'ing strings. + items, _ := toArrayStr(arguments[0]) + d := sort.StringSlice(items) + sort.Stable(d) + final := make([]interface{}, len(d)) + for i, val := range d { + final[i] = val + } + return final, nil +} +func jpfSortBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return arr, nil + } else if len(arr) == 1 { + return arr, nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + if _, ok := start.(float64); ok { + sortable := &byExprFloat{intr, node, arr, false} + sort.Stable(sortable) + if sortable.hasError { + return nil, errors.New("error in sort_by comparison") + } + return arr, nil + } else if _, ok := start.(string); ok { + sortable := &byExprString{intr, node, arr, false} + sort.Stable(sortable) + if sortable.hasError { + return nil, errors.New("error in sort_by comparison") + } + return arr, nil + } else { + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfJoin(arguments []interface{}) (interface{}, error) { + sep := arguments[0].(string) + // We can't just do arguments[1].([]string), we have to + // manually convert each item to a string. + arrayStr := []string{} + for _, item := range arguments[1].([]interface{}) { + arrayStr = append(arrayStr, item.(string)) + } + return strings.Join(arrayStr, sep), nil +} +func jpfReverse(arguments []interface{}) (interface{}, error) { + if s, ok := arguments[0].(string); ok { + r := []rune(s) + for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { + r[i], r[j] = r[j], r[i] + } + return string(r), nil + } + items := arguments[0].([]interface{}) + length := len(items) + reversed := make([]interface{}, length) + for i, item := range items { + reversed[length-(i+1)] = item + } + return reversed, nil +} +func jpfToArray(arguments []interface{}) (interface{}, error) { + if _, ok := arguments[0].([]interface{}); ok { + return arguments[0], nil + } + return arguments[:1:1], nil +} +func jpfToString(arguments []interface{}) (interface{}, error) { + if v, ok := arguments[0].(string); ok { + return v, nil + } + result, err := json.Marshal(arguments[0]) + if err != nil { + return nil, err + } + return string(result), nil +} +func jpfToNumber(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if v, ok := arg.(float64); ok { + return v, nil + } + if v, ok := arg.(string); ok { + conv, err := strconv.ParseFloat(v, 64) + if err != nil { + return nil, nil + } + return conv, nil + } + if _, ok := arg.([]interface{}); ok { + return nil, nil + } + if _, ok := arg.(map[string]interface{}); ok { + return nil, nil + } + if arg == nil { + return nil, nil + } + if arg == true || arg == false { + return nil, nil + } + return nil, errors.New("unknown type") +} +func jpfNotNull(arguments []interface{}) (interface{}, error) { + for _, arg := range arguments { + if arg != nil { + return arg, nil + } + } + return nil, nil +} diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10 new file mode 100644 index 000000000..4d5f9756e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10 @@ -0,0 +1 @@ +foo.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100 new file mode 100644 index 000000000..bc4f6a3f4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100 @@ -0,0 +1 @@ +ends_with(str, 'SStr') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101 new file mode 100644 index 000000000..81bf07a7a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101 @@ -0,0 +1 @@ +ends_with(str, 'foo') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102 new file mode 100644 index 000000000..3225de913 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102 @@ -0,0 +1 @@ +floor(`1.2`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103 new file mode 100644 index 000000000..8cac95958 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103 @@ -0,0 +1 @@ +floor(decimals[0]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104 new file mode 100644 index 000000000..bd76f47e2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104 @@ -0,0 +1 @@ +floor(foo) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105 new file mode 100644 index 000000000..c719add3d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105 @@ -0,0 +1 @@ +length('abc') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106 new file mode 100644 index 000000000..ff12f04f1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106 @@ -0,0 +1 @@ +length('') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107 new file mode 100644 index 000000000..0eccba1d3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107 @@ -0,0 +1 @@ +length(@) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108 new file mode 100644 index 000000000..ab14b0fa8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108 @@ -0,0 +1 @@ +length(strings[0]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109 new file mode 100644 index 000000000..f1514bb74 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109 @@ -0,0 +1 @@ +length(str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110 new file mode 100644 index 000000000..09276059a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110 @@ -0,0 +1 @@ +length(array) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112 new file mode 100644 index 000000000..ab14b0fa8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112 @@ -0,0 +1 @@ +length(strings[0]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115 new file mode 100644 index 000000000..bfb41ae98 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115 @@ -0,0 +1 @@ +max(strings) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118 new file mode 100644 index 000000000..915ec172a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118 @@ -0,0 +1 @@ +merge(`{}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119 new file mode 100644 index 000000000..5b74e9b59 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119 @@ -0,0 +1 @@ +merge(`{}`, `{}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12 new file mode 100644 index 000000000..64c5e5885 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12 @@ -0,0 +1 @@ +two \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120 new file mode 100644 index 000000000..f34dcd8fa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120 @@ -0,0 +1 @@ +merge(`{"a": 1}`, `{"b": 2}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121 new file mode 100644 index 000000000..e335dc96f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121 @@ -0,0 +1 @@ +merge(`{"a": 1}`, `{"a": 2}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122 new file mode 100644 index 000000000..aac28fffe --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122 @@ -0,0 +1 @@ +merge(`{"a": 1, "b": 2}`, `{"a": 2, "c": 3}`, `{"d": 4}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123 new file mode 100644 index 000000000..1c6fd6719 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123 @@ -0,0 +1 @@ +min(numbers) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126 new file mode 100644 index 000000000..93e68db77 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126 @@ -0,0 +1 @@ +min(decimals) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128 new file mode 100644 index 000000000..554601ea4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128 @@ -0,0 +1 @@ +type('abc') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129 new file mode 100644 index 000000000..1ab2d9834 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129 @@ -0,0 +1 @@ +type(`1.0`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13 new file mode 100644 index 000000000..1d19714ff --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13 @@ -0,0 +1 @@ +three \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130 new file mode 100644 index 000000000..3cee2f56f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130 @@ -0,0 +1 @@ +type(`2`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131 new file mode 100644 index 000000000..4821f9aef --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131 @@ -0,0 +1 @@ +type(`true`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132 new file mode 100644 index 000000000..40b6913a6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132 @@ -0,0 +1 @@ +type(`false`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133 new file mode 100644 index 000000000..c711252be --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133 @@ -0,0 +1 @@ +type(`null`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134 new file mode 100644 index 000000000..ec5d07e95 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134 @@ -0,0 +1 @@ +type(`[0]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135 new file mode 100644 index 000000000..2080401e1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135 @@ -0,0 +1 @@ +type(`{"a": "b"}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136 new file mode 100644 index 000000000..c5ee2ba5c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136 @@ -0,0 +1 @@ +type(@) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137 new file mode 100644 index 000000000..1814ca17b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137 @@ -0,0 +1 @@ +keys(objects) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138 new file mode 100644 index 000000000..e03cdb0d6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138 @@ -0,0 +1 @@ +values(objects) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139 new file mode 100644 index 000000000..7fea8d2ce --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139 @@ -0,0 +1 @@ +keys(empty_hash) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14 new file mode 100644 index 000000000..a17c92f59 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14 @@ -0,0 +1 @@ +one.two \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140 new file mode 100644 index 000000000..4f1d882a4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140 @@ -0,0 +1 @@ +join(', ', strings) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141 new file mode 100644 index 000000000..4f1d882a4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141 @@ -0,0 +1 @@ +join(', ', strings) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142 new file mode 100644 index 000000000..19ec1fe09 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142 @@ -0,0 +1 @@ +join(',', `["a", "b"]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143 new file mode 100644 index 000000000..761c68a6b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143 @@ -0,0 +1 @@ +join('|', strings) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144 new file mode 100644 index 000000000..a0dd68eaa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144 @@ -0,0 +1 @@ +join('|', decimals[].to_string(@)) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145 new file mode 100644 index 000000000..a4190b2ba --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145 @@ -0,0 +1 @@ +join('|', empty_list) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146 new file mode 100644 index 000000000..f5033c302 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146 @@ -0,0 +1 @@ +reverse(numbers) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147 new file mode 100644 index 000000000..822f054d5 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147 @@ -0,0 +1 @@ +reverse(array) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148 new file mode 100644 index 000000000..a584adcc0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148 @@ -0,0 +1 @@ +reverse(`[]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149 new file mode 100644 index 000000000..fb4cc5dc4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149 @@ -0,0 +1 @@ +reverse('') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15 new file mode 100644 index 000000000..693f95496 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15 @@ -0,0 +1 @@ +foo."1" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150 new file mode 100644 index 000000000..aa260fabc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150 @@ -0,0 +1 @@ +reverse('hello world') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151 new file mode 100644 index 000000000..d8c58826a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151 @@ -0,0 +1 @@ +starts_with(str, 'S') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152 new file mode 100644 index 000000000..32e16b7bb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152 @@ -0,0 +1 @@ +starts_with(str, 'St') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153 new file mode 100644 index 000000000..5f575ae7f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153 @@ -0,0 +1 @@ +starts_with(str, 'Str') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155 new file mode 100644 index 000000000..f31551c62 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155 @@ -0,0 +1 @@ +sum(numbers) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156 new file mode 100644 index 000000000..18b90446c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156 @@ -0,0 +1 @@ +sum(decimals) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157 new file mode 100644 index 000000000..def4d0bc1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157 @@ -0,0 +1 @@ +sum(array[].to_number(@)) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158 new file mode 100644 index 000000000..48e4a7707 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158 @@ -0,0 +1 @@ +sum(`[]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-159 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-159 new file mode 100644 index 000000000..9fb939a0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-159 @@ -0,0 +1 @@ +to_array('foo') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-16 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-16 new file mode 100644 index 000000000..86155ed75 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-16 @@ -0,0 +1 @@ +foo."1"[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-160 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-160 new file mode 100644 index 000000000..74ba7cc67 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-160 @@ -0,0 +1 @@ +to_array(`0`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-161 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-161 new file mode 100644 index 000000000..57f8b983f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-161 @@ -0,0 +1 @@ +to_array(objects) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-162 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-162 new file mode 100644 index 000000000..d17c7345f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-162 @@ -0,0 +1 @@ +to_array(`[1, 2, 3]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-163 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-163 new file mode 100644 index 000000000..15f70f783 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-163 @@ -0,0 +1 @@ +to_array(false) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-164 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-164 new file mode 100644 index 000000000..9b227529b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-164 @@ -0,0 +1 @@ +to_string('foo') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-165 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-165 new file mode 100644 index 000000000..489a42935 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-165 @@ -0,0 +1 @@ +to_string(`1.2`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-166 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-166 new file mode 100644 index 000000000..d17106a00 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-166 @@ -0,0 +1 @@ +to_string(`[0, 1]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-167 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-167 new file mode 100644 index 000000000..4f4ae9e68 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-167 @@ -0,0 +1 @@ +to_number('1.0') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-168 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-168 new file mode 100644 index 000000000..ce932e2e6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-168 @@ -0,0 +1 @@ +to_number('1.1') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-169 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-169 new file mode 100644 index 000000000..e246fa4db --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-169 @@ -0,0 +1 @@ +to_number('4') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-17 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-17 new file mode 100644 index 000000000..de0b4c39d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-17 @@ -0,0 +1 @@ +foo."-1" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-170 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-170 new file mode 100644 index 000000000..f8c264747 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-170 @@ -0,0 +1 @@ +to_number('notanumber') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-171 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-171 new file mode 100644 index 000000000..7d423b1cd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-171 @@ -0,0 +1 @@ +to_number(`false`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-172 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-172 new file mode 100644 index 000000000..503716b68 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-172 @@ -0,0 +1 @@ +to_number(`null`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-173 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-173 new file mode 100644 index 000000000..7f61dfa15 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-173 @@ -0,0 +1 @@ +to_number(`[0]`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-174 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-174 new file mode 100644 index 000000000..ee72a8c01 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-174 @@ -0,0 +1 @@ +to_number(`{"foo": 0}`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-175 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-175 new file mode 100644 index 000000000..8d8f1f759 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-175 @@ -0,0 +1 @@ +sort(numbers) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-178 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-178 new file mode 100644 index 000000000..8cb54ba47 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-178 @@ -0,0 +1 @@ +sort(empty_list) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-179 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-179 new file mode 100644 index 000000000..cf2c9b1db --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-179 @@ -0,0 +1 @@ +not_null(unknown_key, str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-18 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-18 new file mode 100644 index 000000000..b516b2c48 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-18 @@ -0,0 +1 @@ +@ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-180 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-180 new file mode 100644 index 000000000..e047d4866 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-180 @@ -0,0 +1 @@ +not_null(unknown_key, foo.bar, empty_list, str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-181 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-181 new file mode 100644 index 000000000..c4cc87b9c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-181 @@ -0,0 +1 @@ +not_null(unknown_key, null_key, empty_list, str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-182 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-182 new file mode 100644 index 000000000..2c7fa0a9c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-182 @@ -0,0 +1 @@ +not_null(all, expressions, are_null) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-183 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-183 new file mode 100644 index 000000000..eb096e61c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-183 @@ -0,0 +1 @@ +numbers[].to_string(@) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-184 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-184 new file mode 100644 index 000000000..4958abaec --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-184 @@ -0,0 +1 @@ +array[].to_number(@) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-185 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-185 new file mode 100644 index 000000000..102708472 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-185 @@ -0,0 +1 @@ +foo[].not_null(f, e, d, c, b, a) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-186 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-186 new file mode 100644 index 000000000..83cb91612 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-186 @@ -0,0 +1 @@ +sort_by(people, &age) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-187 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-187 new file mode 100644 index 000000000..a494d6c4b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-187 @@ -0,0 +1 @@ +sort_by(people, &to_number(age_str)) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-188 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-188 new file mode 100644 index 000000000..2294fc54d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-188 @@ -0,0 +1 @@ +sort_by(people, &age)[].name \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-189 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-189 new file mode 100644 index 000000000..bb8c2b46d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-189 @@ -0,0 +1 @@ +sort_by(people, &age)[].extra \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-19 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-19 new file mode 100644 index 000000000..e3ed49ac6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-19 @@ -0,0 +1 @@ +@.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-190 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-190 new file mode 100644 index 000000000..3ab029034 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-190 @@ -0,0 +1 @@ +sort_by(`[]`, &age) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-191 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-191 new file mode 100644 index 000000000..97db56f7b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-191 @@ -0,0 +1 @@ +max_by(people, &age) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-192 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-192 new file mode 100644 index 000000000..a7e648de9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-192 @@ -0,0 +1 @@ +max_by(people, &age_str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-193 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-193 new file mode 100644 index 000000000..be4348d0c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-193 @@ -0,0 +1 @@ +max_by(people, &to_number(age_str)) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-194 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-194 new file mode 100644 index 000000000..a707283d4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-194 @@ -0,0 +1 @@ +min_by(people, &age) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-195 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-195 new file mode 100644 index 000000000..2cd6618d8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-195 @@ -0,0 +1 @@ +min_by(people, &age_str) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-196 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-196 new file mode 100644 index 000000000..833e68373 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-196 @@ -0,0 +1 @@ +min_by(people, &to_number(age_str)) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-198 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-198 new file mode 100644 index 000000000..706dbda89 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-198 @@ -0,0 +1 @@ +__L \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-199 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-199 new file mode 100644 index 000000000..ca593ca93 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-199 @@ -0,0 +1 @@ +"!\r" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-2 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-2 new file mode 100644 index 000000000..4d5f9756e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-2 @@ -0,0 +1 @@ +foo.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-20 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-20 new file mode 100644 index 000000000..f300ab917 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-20 @@ -0,0 +1 @@ +@.foo[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-200 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-200 new file mode 100644 index 000000000..9c9384354 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-200 @@ -0,0 +1 @@ +Y_1623 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-201 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-201 new file mode 100644 index 000000000..c1b0730e0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-201 @@ -0,0 +1 @@ +x \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-202 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-202 new file mode 100644 index 000000000..1552ec63a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-202 @@ -0,0 +1 @@ +"\tF\uCebb" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-203 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-203 new file mode 100644 index 000000000..047041273 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-203 @@ -0,0 +1 @@ +" \t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-204 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-204 new file mode 100644 index 000000000..efd782cc3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-204 @@ -0,0 +1 @@ +" " \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-205 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-205 new file mode 100644 index 000000000..8494ac270 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-205 @@ -0,0 +1 @@ +v2 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-206 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-206 new file mode 100644 index 000000000..c61f7f7eb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-206 @@ -0,0 +1 @@ +"\t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-207 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-207 new file mode 100644 index 000000000..f6055f189 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-207 @@ -0,0 +1 @@ +_X \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-208 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-208 new file mode 100644 index 000000000..4f58e0e7b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-208 @@ -0,0 +1 @@ +"\t4\ud9da\udd15" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-209 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-209 new file mode 100644 index 000000000..f536bfbf6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-209 @@ -0,0 +1 @@ +v24_W \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-21 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-21 new file mode 100644 index 000000000..ef47ff2c0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-21 @@ -0,0 +1 @@ +"foo.bar" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-210 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-210 new file mode 100644 index 000000000..69759281c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-210 @@ -0,0 +1 @@ +"H" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-211 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-211 new file mode 100644 index 000000000..c3e8b5927 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-211 @@ -0,0 +1 @@ +"\f" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-212 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-212 new file mode 100644 index 000000000..24ecc222c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-212 @@ -0,0 +1 @@ +"E4" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-213 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-213 new file mode 100644 index 000000000..5693009d2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-213 @@ -0,0 +1 @@ +"!" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-214 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-214 new file mode 100644 index 000000000..62dd220e7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-214 @@ -0,0 +1 @@ +tM \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-215 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-215 new file mode 100644 index 000000000..3c1e81f55 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-215 @@ -0,0 +1 @@ +" [" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-216 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-216 new file mode 100644 index 000000000..493daa673 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-216 @@ -0,0 +1 @@ +"R!" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-217 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-217 new file mode 100644 index 000000000..116b50ab3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-217 @@ -0,0 +1 @@ +_6W \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-218 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-218 new file mode 100644 index 000000000..0073fac45 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-218 @@ -0,0 +1 @@ +"\uaBA1\r" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-219 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-219 new file mode 100644 index 000000000..00d8fa37e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-219 @@ -0,0 +1 @@ +tL7 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-22 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-22 new file mode 100644 index 000000000..661ebcfa3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-22 @@ -0,0 +1 @@ +"foo bar" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-220 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-220 new file mode 100644 index 000000000..c14f16e02 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-220 @@ -0,0 +1 @@ +"<" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-257 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-257 new file mode 100644 index 000000000..8a2443e6e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-257 @@ -0,0 +1 @@ +hvu \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-258 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-258 new file mode 100644 index 000000000..c9ddacbb6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-258 @@ -0,0 +1 @@ +"; !" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-259 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-259 new file mode 100644 index 000000000..d0209c6df --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-259 @@ -0,0 +1 @@ +hU \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-26 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-26 new file mode 100644 index 000000000..82649bd24 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-26 @@ -0,0 +1 @@ +"/unix/path" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-260 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-260 new file mode 100644 index 000000000..c07242aa4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-260 @@ -0,0 +1 @@ +"!I\n\/" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-261 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-261 new file mode 100644 index 000000000..7aae4effc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-261 @@ -0,0 +1 @@ +"\uEEbF" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-262 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-262 new file mode 100644 index 000000000..c1574f35f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-262 @@ -0,0 +1 @@ +"U)\t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-263 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-263 new file mode 100644 index 000000000..5197e3a2b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-263 @@ -0,0 +1 @@ +fa0_9 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-264 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-264 new file mode 100644 index 000000000..320558b00 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-264 @@ -0,0 +1 @@ +"/" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-265 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-265 new file mode 100644 index 000000000..4a2cb0865 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-265 @@ -0,0 +1 @@ +Gy \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-266 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-266 new file mode 100644 index 000000000..9524c8381 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-266 @@ -0,0 +1 @@ +"\b" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-267 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-267 new file mode 100644 index 000000000..066b8d98b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-267 @@ -0,0 +1 @@ +"<" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-268 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-268 new file mode 100644 index 000000000..c61f7f7eb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-268 @@ -0,0 +1 @@ +"\t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-269 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-269 new file mode 100644 index 000000000..a582f62d2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-269 @@ -0,0 +1 @@ +"\t&\\\r" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-27 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-27 new file mode 100644 index 000000000..a1d50731c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-27 @@ -0,0 +1 @@ +"\"\"\"" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-270 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-270 new file mode 100644 index 000000000..e3c5eedeb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-270 @@ -0,0 +1 @@ +"#" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-271 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-271 new file mode 100644 index 000000000..e75309a52 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-271 @@ -0,0 +1 @@ +B__ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-272 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-272 new file mode 100644 index 000000000..027177272 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-272 @@ -0,0 +1 @@ +"\nS \n" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-273 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-273 new file mode 100644 index 000000000..99432276e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-273 @@ -0,0 +1 @@ +Bp \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-274 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-274 new file mode 100644 index 000000000..d4f8a788b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-274 @@ -0,0 +1 @@ +",\t;" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-275 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-275 new file mode 100644 index 000000000..56c384f75 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-275 @@ -0,0 +1 @@ +B_q \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-276 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-276 new file mode 100644 index 000000000..f093d2aa3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-276 @@ -0,0 +1 @@ +"\/+\t\n\b!Z" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-277 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-277 new file mode 100644 index 000000000..11e1229d9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-277 @@ -0,0 +1 @@ +"󇟇\\ueFAc" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-278 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-278 new file mode 100644 index 000000000..90dbfcfcd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-278 @@ -0,0 +1 @@ +":\f" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-279 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-279 new file mode 100644 index 000000000..b06b83025 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-279 @@ -0,0 +1 @@ +"\/" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-28 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-28 new file mode 100644 index 000000000..5f55d73af --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-28 @@ -0,0 +1 @@ +"bar"."baz" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-280 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-280 new file mode 100644 index 000000000..0e4bf7c11 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-280 @@ -0,0 +1 @@ +_BW_6Hg_Gl \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-281 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-281 new file mode 100644 index 000000000..81bb45f80 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-281 @@ -0,0 +1 @@ +"ôƒ°‚" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-282 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-282 new file mode 100644 index 000000000..d0b4de146 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-282 @@ -0,0 +1 @@ +zs1DC \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-283 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-283 new file mode 100644 index 000000000..68797580c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-283 @@ -0,0 +1 @@ +__434 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-284 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-284 new file mode 100644 index 000000000..e61be91c4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-284 @@ -0,0 +1 @@ +"óµ…" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-285 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-285 new file mode 100644 index 000000000..026cb9cbb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-285 @@ -0,0 +1 @@ +Z_5 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-286 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-286 new file mode 100644 index 000000000..ca9587d06 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-286 @@ -0,0 +1 @@ +z_M_ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-287 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-287 new file mode 100644 index 000000000..67f6d9c42 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-287 @@ -0,0 +1 @@ +YU_2 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-288 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-288 new file mode 100644 index 000000000..927ab653a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-288 @@ -0,0 +1 @@ +_0 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-289 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-289 new file mode 100644 index 000000000..39307ab93 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-289 @@ -0,0 +1 @@ +"\b+" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-29 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-29 new file mode 100644 index 000000000..8b0c5b41b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-29 @@ -0,0 +1 @@ +foo[?name == 'a'] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-290 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-290 new file mode 100644 index 000000000..a3ec2ed7a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-290 @@ -0,0 +1 @@ +"\"" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-291 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-291 new file mode 100644 index 000000000..26bf7e122 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-291 @@ -0,0 +1 @@ +D7 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-292 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-292 new file mode 100644 index 000000000..d595c9f43 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-292 @@ -0,0 +1 @@ +_62L \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-293 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-293 new file mode 100644 index 000000000..f68696949 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-293 @@ -0,0 +1 @@ +"\tK\t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-294 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-294 new file mode 100644 index 000000000..f3a9b7edb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-294 @@ -0,0 +1 @@ +"\n\\\f" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-295 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-295 new file mode 100644 index 000000000..455f00ffc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-295 @@ -0,0 +1 @@ +I_ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-296 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-296 new file mode 100644 index 000000000..ccd5968f9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-296 @@ -0,0 +1 @@ +W_a0_ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-297 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-297 new file mode 100644 index 000000000..ee55c16fc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-297 @@ -0,0 +1 @@ +BQ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-298 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-298 new file mode 100644 index 000000000..0d1a169a6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-298 @@ -0,0 +1 @@ +"\tX$\uABBb" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-299 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-299 new file mode 100644 index 000000000..0573cfd73 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-299 @@ -0,0 +1 @@ +Z9 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-3 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-3 new file mode 100644 index 000000000..f0fcbd8ea --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-3 @@ -0,0 +1 @@ +foo.bar.baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-30 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-30 new file mode 100644 index 000000000..4f8e6a17a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-30 @@ -0,0 +1 @@ +*[?[0] == `0`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-300 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-300 new file mode 100644 index 000000000..a0db02beb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-300 @@ -0,0 +1 @@ +"\b%\"òž„" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-301 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-301 new file mode 100644 index 000000000..56032f7a2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-301 @@ -0,0 +1 @@ +_F \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-302 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-302 new file mode 100644 index 000000000..4a8a3cff3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-302 @@ -0,0 +1 @@ +"!," \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-303 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-303 new file mode 100644 index 000000000..7c1efac00 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-303 @@ -0,0 +1 @@ +"\"!" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-304 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-304 new file mode 100644 index 000000000..a0f489d53 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-304 @@ -0,0 +1 @@ +Hh \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-305 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-305 new file mode 100644 index 000000000..c64e8d5ac --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-305 @@ -0,0 +1 @@ +"&" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-306 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-306 new file mode 100644 index 000000000..0567e992f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-306 @@ -0,0 +1 @@ +"9\r\\R" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-307 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-307 new file mode 100644 index 000000000..ce8245c5b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-307 @@ -0,0 +1 @@ +M_k \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-308 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-308 new file mode 100644 index 000000000..8f16a5ac0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-308 @@ -0,0 +1 @@ +"!\b\nó‘©’\"\"" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-309 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-309 new file mode 100644 index 000000000..504ff5ae3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-309 @@ -0,0 +1 @@ +"6" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-31 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-31 new file mode 100644 index 000000000..07fb57234 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-31 @@ -0,0 +1 @@ +foo[?first == last] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-310 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-310 new file mode 100644 index 000000000..533dd8e54 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-310 @@ -0,0 +1 @@ +_7 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-311 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-311 new file mode 100644 index 000000000..1e4a3a341 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-311 @@ -0,0 +1 @@ +"0" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-312 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-312 new file mode 100644 index 000000000..37961f6ca --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-312 @@ -0,0 +1 @@ +"\\8\\" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-313 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-313 new file mode 100644 index 000000000..23480cff1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-313 @@ -0,0 +1 @@ +b7eo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-314 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-314 new file mode 100644 index 000000000..e609f81a3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-314 @@ -0,0 +1 @@ +xIUo9 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-315 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-315 new file mode 100644 index 000000000..d89a25f0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-315 @@ -0,0 +1 @@ +"5" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-316 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-316 new file mode 100644 index 000000000..5adcf5e7d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-316 @@ -0,0 +1 @@ +"?" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-317 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-317 new file mode 100644 index 000000000..ace4a897d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-317 @@ -0,0 +1 @@ +sU \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-318 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-318 new file mode 100644 index 000000000..feffb7061 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-318 @@ -0,0 +1 @@ +"VH2&H\\\/" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-319 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-319 new file mode 100644 index 000000000..8223f1e51 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-319 @@ -0,0 +1 @@ +_C \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-32 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-32 new file mode 100644 index 000000000..7e85c4bdf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-32 @@ -0,0 +1 @@ +foo[?first == last].first \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-320 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-320 new file mode 100644 index 000000000..c9cdc63b0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-320 @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-321 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-321 new file mode 100644 index 000000000..c82f7982e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-321 @@ -0,0 +1 @@ +"<\t" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-322 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-322 new file mode 100644 index 000000000..dae65c515 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-322 @@ -0,0 +1 @@ +"\uD834\uDD1E" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-323 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-323 new file mode 100644 index 000000000..b6b369543 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-323 @@ -0,0 +1 @@ +foo.bar[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-324 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-324 new file mode 100644 index 000000000..bf06e678c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-324 @@ -0,0 +1 @@ +foo.bar[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-325 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-325 new file mode 100644 index 000000000..5d48e0205 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-325 @@ -0,0 +1 @@ +foo.bar[2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-326 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-326 new file mode 100644 index 000000000..de3af7230 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-326 @@ -0,0 +1 @@ +foo.bar[3] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-327 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-327 new file mode 100644 index 000000000..a1c333508 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-327 @@ -0,0 +1 @@ +foo.bar[-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-328 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-328 new file mode 100644 index 000000000..ad0fef91c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-328 @@ -0,0 +1 @@ +foo.bar[-2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-329 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-329 new file mode 100644 index 000000000..3e83c6f73 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-329 @@ -0,0 +1 @@ +foo.bar[-3] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-33 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-33 new file mode 100644 index 000000000..72fc0a53e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-33 @@ -0,0 +1 @@ +foo[?age > `25`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-330 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-330 new file mode 100644 index 000000000..433a737d6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-330 @@ -0,0 +1 @@ +foo.bar[-4] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-331 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-331 new file mode 100644 index 000000000..4d5f9756e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-331 @@ -0,0 +1 @@ +foo.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-332 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-332 new file mode 100644 index 000000000..5e0d9b717 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-332 @@ -0,0 +1 @@ +foo[0].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-333 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-333 new file mode 100644 index 000000000..3cd7e9460 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-333 @@ -0,0 +1 @@ +foo[1].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-334 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-334 new file mode 100644 index 000000000..74cb17655 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-334 @@ -0,0 +1 @@ +foo[2].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-335 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-335 new file mode 100644 index 000000000..3cf2007f7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-335 @@ -0,0 +1 @@ +foo[3].notbar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-336 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-336 new file mode 100644 index 000000000..9674d8803 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-336 @@ -0,0 +1 @@ +foo[3].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-337 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-337 new file mode 100644 index 000000000..9b0b2f818 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-337 @@ -0,0 +1 @@ +foo[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-338 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-338 new file mode 100644 index 000000000..83c639a18 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-338 @@ -0,0 +1 @@ +foo[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-339 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-339 new file mode 100644 index 000000000..3b76c9f64 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-339 @@ -0,0 +1 @@ +foo[2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-34 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-34 new file mode 100644 index 000000000..9a2b0184e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-34 @@ -0,0 +1 @@ +foo[?age >= `25`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-340 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-340 new file mode 100644 index 000000000..ff99e045d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-340 @@ -0,0 +1 @@ +foo[3] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-341 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-341 new file mode 100644 index 000000000..040ecb240 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-341 @@ -0,0 +1 @@ +foo[4] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-342 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-342 new file mode 100644 index 000000000..6e7ea636e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-342 @@ -0,0 +1 @@ +[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-343 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-343 new file mode 100644 index 000000000..bace2a0be --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-343 @@ -0,0 +1 @@ +[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-344 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-344 new file mode 100644 index 000000000..5d50c80c0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-344 @@ -0,0 +1 @@ +[2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-345 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-345 new file mode 100644 index 000000000..99d21a2a0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-345 @@ -0,0 +1 @@ +[-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-346 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-346 new file mode 100644 index 000000000..133a9c627 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-346 @@ -0,0 +1 @@ +[-2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-347 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-347 new file mode 100644 index 000000000..b7f78c5dc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-347 @@ -0,0 +1 @@ +[-3] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-348 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-348 new file mode 100644 index 000000000..bd9de815f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-348 @@ -0,0 +1 @@ +reservations[].instances[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-349 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-349 new file mode 100644 index 000000000..55e625735 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-349 @@ -0,0 +1 @@ +reservations[].instances[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-35 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-35 new file mode 100644 index 000000000..fa83f1da3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-35 @@ -0,0 +1 @@ +foo[?age > `30`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-350 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-350 new file mode 100644 index 000000000..1661747c0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-350 @@ -0,0 +1 @@ +reservations[].notinstances[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-351 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-351 new file mode 100644 index 000000000..1661747c0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-351 @@ -0,0 +1 @@ +reservations[].notinstances[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-352 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-352 new file mode 100644 index 000000000..3debc70f8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-352 @@ -0,0 +1 @@ +reservations[].instances[].foo[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-353 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-353 new file mode 100644 index 000000000..75af2fda0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-353 @@ -0,0 +1 @@ +reservations[].instances[].foo[].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-354 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-354 new file mode 100644 index 000000000..4a70cd8a0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-354 @@ -0,0 +1 @@ +reservations[].instances[].notfoo[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-355 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-355 new file mode 100644 index 000000000..987985b00 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-355 @@ -0,0 +1 @@ +reservations[].instances[].notfoo[].notbar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-356 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-356 new file mode 100644 index 000000000..1661747c0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-356 @@ -0,0 +1 @@ +reservations[].notinstances[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-357 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-357 new file mode 100644 index 000000000..634f937e5 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-357 @@ -0,0 +1 @@ +reservations[].instances[].foo[].notbar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-358 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-358 new file mode 100644 index 000000000..09cb7b8bb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-358 @@ -0,0 +1 @@ +reservations[].instances[].bar[].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-359 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-359 new file mode 100644 index 000000000..f5d9ac5b7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-359 @@ -0,0 +1 @@ +reservations[].instances[].baz[].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-36 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-36 new file mode 100644 index 000000000..463a2a542 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-36 @@ -0,0 +1 @@ +foo[?age < `25`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-360 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-360 new file mode 100644 index 000000000..d1016d6e7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-360 @@ -0,0 +1 @@ +reservations[].instances[].qux[].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-361 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-361 new file mode 100644 index 000000000..ef54cf52d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-361 @@ -0,0 +1 @@ +reservations[].instances[].qux[].baz[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-362 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-362 new file mode 100644 index 000000000..bea506ff2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-362 @@ -0,0 +1 @@ +foo[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-363 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-363 new file mode 100644 index 000000000..20dd081e0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-363 @@ -0,0 +1 @@ +foo[][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-364 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-364 new file mode 100644 index 000000000..4803734b0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-364 @@ -0,0 +1 @@ +foo[][1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-365 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-365 new file mode 100644 index 000000000..1be565985 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-365 @@ -0,0 +1 @@ +foo[][0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-366 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-366 new file mode 100644 index 000000000..d2cf6da59 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-366 @@ -0,0 +1 @@ +foo[][2][2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-367 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-367 new file mode 100644 index 000000000..c609ca64b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-367 @@ -0,0 +1 @@ +foo[][0][0][100] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-368 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-368 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-368 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-369 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-369 new file mode 100644 index 000000000..bea506ff2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-369 @@ -0,0 +1 @@ +foo[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-37 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-37 new file mode 100644 index 000000000..10ed5d3f6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-37 @@ -0,0 +1 @@ +foo[?age <= `25`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-370 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-370 new file mode 100644 index 000000000..13f2c4a0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-370 @@ -0,0 +1 @@ +foo[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-371 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-371 new file mode 100644 index 000000000..edf3d9277 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-371 @@ -0,0 +1 @@ +foo[].bar[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-372 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-372 new file mode 100644 index 000000000..2a3b993af --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-372 @@ -0,0 +1 @@ +foo[].bar[].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-373 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-373 new file mode 100644 index 000000000..d5ca878a1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-373 @@ -0,0 +1 @@ +string[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-374 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-374 new file mode 100644 index 000000000..fcd255f5d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-374 @@ -0,0 +1 @@ +hash[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-375 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-375 new file mode 100644 index 000000000..2d53bd7cd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-375 @@ -0,0 +1 @@ +number[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-376 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-376 new file mode 100644 index 000000000..cb10d2497 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-376 @@ -0,0 +1 @@ +nullvalue[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-377 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-377 new file mode 100644 index 000000000..f6c79ca84 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-377 @@ -0,0 +1 @@ +string[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-378 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-378 new file mode 100644 index 000000000..09bf36e8a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-378 @@ -0,0 +1 @@ +hash[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-379 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-379 new file mode 100644 index 000000000..4c3578189 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-379 @@ -0,0 +1 @@ +number[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-38 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-38 new file mode 100644 index 000000000..16a4c36ac --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-38 @@ -0,0 +1 @@ +foo[?age < `20`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-380 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-380 new file mode 100644 index 000000000..2dd8ae218 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-380 @@ -0,0 +1 @@ +nullvalue[].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-381 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-381 new file mode 100644 index 000000000..dfed81603 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-381 @@ -0,0 +1 @@ +nullvalue[].foo[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-382 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-382 new file mode 100644 index 000000000..d7628e646 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-382 @@ -0,0 +1 @@ +`"foo"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-383 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-383 new file mode 100644 index 000000000..49c5269b1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-383 @@ -0,0 +1 @@ +`"\u03a6"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-384 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-384 new file mode 100644 index 000000000..d5db721d0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-384 @@ -0,0 +1 @@ +`"✓"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-385 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-385 new file mode 100644 index 000000000..a2b6e4ec8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-385 @@ -0,0 +1 @@ +`[1, 2, 3]` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-386 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-386 new file mode 100644 index 000000000..f5801bdd6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-386 @@ -0,0 +1 @@ +`{"a": "b"}` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-387 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-387 new file mode 100644 index 000000000..f87db59a8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-387 @@ -0,0 +1 @@ +`true` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-388 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-388 new file mode 100644 index 000000000..3b20d905f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-388 @@ -0,0 +1 @@ +`false` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-389 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-389 new file mode 100644 index 000000000..70bcd29a7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-389 @@ -0,0 +1 @@ +`null` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-39 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-39 new file mode 100644 index 000000000..351054d3e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-39 @@ -0,0 +1 @@ +foo[?age == `20`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-390 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-390 new file mode 100644 index 000000000..0918d4155 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-390 @@ -0,0 +1 @@ +`0` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-391 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-391 new file mode 100644 index 000000000..ef70c4c11 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-391 @@ -0,0 +1 @@ +`1` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-392 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-392 new file mode 100644 index 000000000..b39a922f4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-392 @@ -0,0 +1 @@ +`2` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-393 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-393 new file mode 100644 index 000000000..7e65687db --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-393 @@ -0,0 +1 @@ +`3` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-394 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-394 new file mode 100644 index 000000000..770d1ece7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-394 @@ -0,0 +1 @@ +`4` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-395 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-395 new file mode 100644 index 000000000..a8b81985c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-395 @@ -0,0 +1 @@ +`5` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-396 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-396 new file mode 100644 index 000000000..7f0861065 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-396 @@ -0,0 +1 @@ +`6` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-397 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-397 new file mode 100644 index 000000000..495114d91 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-397 @@ -0,0 +1 @@ +`7` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-398 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-398 new file mode 100644 index 000000000..94f355c46 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-398 @@ -0,0 +1 @@ +`8` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-399 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-399 new file mode 100644 index 000000000..600d2aa3f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-399 @@ -0,0 +1 @@ +`9` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-4 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-4 new file mode 100644 index 000000000..314852235 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-4 @@ -0,0 +1 @@ +foo.bar.baz.bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-40 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-40 new file mode 100644 index 000000000..99d9258a6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-40 @@ -0,0 +1 @@ +foo[?age != `20`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-400 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-400 new file mode 100644 index 000000000..637015b5f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-400 @@ -0,0 +1 @@ +`"foo\`bar"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-401 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-401 new file mode 100644 index 000000000..6fa7557b8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-401 @@ -0,0 +1 @@ +`"foo\"bar"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-402 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-402 new file mode 100644 index 000000000..5aabeec34 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-402 @@ -0,0 +1 @@ +`"1\`"` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-403 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-403 new file mode 100644 index 000000000..8302ea198 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-403 @@ -0,0 +1 @@ +`"\\"`.{a:`"b"`} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-404 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-404 new file mode 100644 index 000000000..d88d014a9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-404 @@ -0,0 +1 @@ +`{"a": "b"}`.a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-405 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-405 new file mode 100644 index 000000000..47152dddb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-405 @@ -0,0 +1 @@ +`{"a": {"b": "c"}}`.a.b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-406 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-406 new file mode 100644 index 000000000..895d42938 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-406 @@ -0,0 +1 @@ +`[0, 1, 2]`[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-407 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-407 new file mode 100644 index 000000000..42500a368 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-407 @@ -0,0 +1 @@ +` {"foo": true}` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-408 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-408 new file mode 100644 index 000000000..08b944dad --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-408 @@ -0,0 +1 @@ +`{"foo": true} ` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-409 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-409 new file mode 100644 index 000000000..6de163f80 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-409 @@ -0,0 +1 @@ +'foo' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-41 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-41 new file mode 100644 index 000000000..5bc357d9f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-41 @@ -0,0 +1 @@ +foo[?top.name == 'a'] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-410 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-410 new file mode 100644 index 000000000..b84bbdb29 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-410 @@ -0,0 +1 @@ +' foo ' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-411 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-411 new file mode 100644 index 000000000..bf6a07ace --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-411 @@ -0,0 +1 @@ +'0' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-412 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-412 new file mode 100644 index 000000000..c742f5b0c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-412 @@ -0,0 +1,2 @@ +'newline +' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-413 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-413 new file mode 100644 index 000000000..04e9b3ade --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-413 @@ -0,0 +1,2 @@ +' +' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-414 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-414 new file mode 100644 index 000000000..ebdaf120d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-414 @@ -0,0 +1 @@ +'✓' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-415 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-415 new file mode 100644 index 000000000..d0ba5d7fa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-415 @@ -0,0 +1 @@ +'ð„ž' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-416 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-416 new file mode 100644 index 000000000..19c2e2ef4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-416 @@ -0,0 +1 @@ +' [foo] ' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-417 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-417 new file mode 100644 index 000000000..5faa483b1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-417 @@ -0,0 +1 @@ +'[foo]' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-418 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-418 new file mode 100644 index 000000000..e3c05c163 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-418 @@ -0,0 +1 @@ +'\u03a6' \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-419 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-419 new file mode 100644 index 000000000..7c13861ac --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-419 @@ -0,0 +1 @@ +foo.{bar: bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-42 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-42 new file mode 100644 index 000000000..d037a0a4d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-42 @@ -0,0 +1 @@ +foo[?top.first == top.last] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-420 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-420 new file mode 100644 index 000000000..f795c2552 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-420 @@ -0,0 +1 @@ +foo.{"bar": bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-421 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-421 new file mode 100644 index 000000000..772c45639 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-421 @@ -0,0 +1 @@ +foo.{"foo.bar": bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-422 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-422 new file mode 100644 index 000000000..8808e92bf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-422 @@ -0,0 +1 @@ +foo.{bar: bar, baz: baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-423 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-423 new file mode 100644 index 000000000..3f13757a1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-423 @@ -0,0 +1 @@ +foo.{"bar": bar, "baz": baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-424 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-424 new file mode 100644 index 000000000..23cd8903e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-424 @@ -0,0 +1 @@ +{"baz": baz, "qux\"": "qux\""} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-425 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-425 new file mode 100644 index 000000000..fabb6da4f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-425 @@ -0,0 +1 @@ +foo.{bar:bar,baz:baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-426 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-426 new file mode 100644 index 000000000..4c3f615b1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-426 @@ -0,0 +1 @@ +foo.{bar: bar,qux: qux} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-427 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-427 new file mode 100644 index 000000000..8bc46535a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-427 @@ -0,0 +1 @@ +foo.{bar: bar, noexist: noexist} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-428 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-428 new file mode 100644 index 000000000..2024b6f11 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-428 @@ -0,0 +1 @@ +foo.{noexist: noexist, alsonoexist: alsonoexist} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-429 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-429 new file mode 100644 index 000000000..b52191d10 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-429 @@ -0,0 +1 @@ +foo.badkey.{nokey: nokey, alsonokey: alsonokey} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-43 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-43 new file mode 100644 index 000000000..8534a5cae --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-43 @@ -0,0 +1 @@ +foo[?top == `{"first": "foo", "last": "bar"}`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-430 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-430 new file mode 100644 index 000000000..5cd310b6d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-430 @@ -0,0 +1 @@ +foo.nested.*.{a: a,b: b} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-431 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-431 new file mode 100644 index 000000000..0b24ef535 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-431 @@ -0,0 +1 @@ +foo.nested.three.{a: a, cinner: c.inner} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-432 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-432 new file mode 100644 index 000000000..473c1c351 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-432 @@ -0,0 +1 @@ +foo.nested.three.{a: a, c: c.inner.bad.key} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-433 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-433 new file mode 100644 index 000000000..44ba735ab --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-433 @@ -0,0 +1 @@ +foo.{a: nested.one.a, b: nested.two.b} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-434 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-434 new file mode 100644 index 000000000..f5f89b12b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-434 @@ -0,0 +1 @@ +{bar: bar, baz: baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-435 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-435 new file mode 100644 index 000000000..697764cb3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-435 @@ -0,0 +1 @@ +{bar: bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-436 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-436 new file mode 100644 index 000000000..20447fb10 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-436 @@ -0,0 +1 @@ +{otherkey: bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-437 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-437 new file mode 100644 index 000000000..310b9b1dd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-437 @@ -0,0 +1 @@ +{no: no, exist: exist} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-438 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-438 new file mode 100644 index 000000000..c79b2e240 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-438 @@ -0,0 +1 @@ +foo.[bar] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-439 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-439 new file mode 100644 index 000000000..ab498ef65 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-439 @@ -0,0 +1 @@ +foo.[bar,baz] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-44 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-44 new file mode 100644 index 000000000..71307c409 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-44 @@ -0,0 +1 @@ +foo[?key == `true`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-440 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-440 new file mode 100644 index 000000000..4b8f39a46 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-440 @@ -0,0 +1 @@ +foo.[bar,qux] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-441 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-441 new file mode 100644 index 000000000..b8f9020f8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-441 @@ -0,0 +1 @@ +foo.[bar,noexist] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-442 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-442 new file mode 100644 index 000000000..b7c7b3f65 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-442 @@ -0,0 +1 @@ +foo.[noexist,alsonoexist] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-443 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-443 new file mode 100644 index 000000000..fabb6da4f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-443 @@ -0,0 +1 @@ +foo.{bar:bar,baz:baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-444 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-444 new file mode 100644 index 000000000..c15c39f82 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-444 @@ -0,0 +1 @@ +foo.[bar,baz[0]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-445 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-445 new file mode 100644 index 000000000..9cebd8984 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-445 @@ -0,0 +1 @@ +foo.[bar,baz[1]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-446 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-446 new file mode 100644 index 000000000..c5bbfbf84 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-446 @@ -0,0 +1 @@ +foo.[bar,baz[2]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-447 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-447 new file mode 100644 index 000000000..d81cb2b90 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-447 @@ -0,0 +1 @@ +foo.[bar,baz[3]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-448 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-448 new file mode 100644 index 000000000..3a65aa7d6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-448 @@ -0,0 +1 @@ +foo.[bar[0],baz[3]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-449 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-449 new file mode 100644 index 000000000..8808e92bf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-449 @@ -0,0 +1 @@ +foo.{bar: bar, baz: baz} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-45 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-45 new file mode 100644 index 000000000..e142b22a2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-45 @@ -0,0 +1 @@ +foo[?key == `false`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-450 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-450 new file mode 100644 index 000000000..ab498ef65 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-450 @@ -0,0 +1 @@ +foo.[bar,baz] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-451 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-451 new file mode 100644 index 000000000..8e3d22dc5 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-451 @@ -0,0 +1 @@ +foo.{bar: bar.baz[1],includeme: includeme} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-452 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-452 new file mode 100644 index 000000000..398c7f8b0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-452 @@ -0,0 +1 @@ +foo.{"bar.baz.two": bar.baz[1].two, includeme: includeme} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-453 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-453 new file mode 100644 index 000000000..a17644487 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-453 @@ -0,0 +1 @@ +foo.[includeme, bar.baz[*].common] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-454 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-454 new file mode 100644 index 000000000..da5225ddc --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-454 @@ -0,0 +1 @@ +foo.[includeme, bar.baz[*].none] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-455 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-455 new file mode 100644 index 000000000..a8870b22b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-455 @@ -0,0 +1 @@ +foo.[includeme, bar.baz[].common] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-456 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-456 new file mode 100644 index 000000000..420b1a57c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-456 @@ -0,0 +1 @@ +reservations[*].instances[*].{id: id, name: name} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-457 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-457 new file mode 100644 index 000000000..0761ee16d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-457 @@ -0,0 +1 @@ +reservations[].instances[].{id: id, name: name} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-458 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-458 new file mode 100644 index 000000000..aa1191a48 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-458 @@ -0,0 +1 @@ +reservations[].instances[].[id, name] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-459 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-459 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-459 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-46 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-46 new file mode 100644 index 000000000..9a24a464e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-46 @@ -0,0 +1 @@ +foo[?key == `0`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-460 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-460 new file mode 100644 index 000000000..bea506ff2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-460 @@ -0,0 +1 @@ +foo[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-461 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-461 new file mode 100644 index 000000000..13f2c4a0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-461 @@ -0,0 +1 @@ +foo[].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-462 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-462 new file mode 100644 index 000000000..edf3d9277 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-462 @@ -0,0 +1 @@ +foo[].bar[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-463 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-463 new file mode 100644 index 000000000..d965466e9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-463 @@ -0,0 +1 @@ +foo[].bar[].[baz, qux] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-464 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-464 new file mode 100644 index 000000000..f1822a174 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-464 @@ -0,0 +1 @@ +foo[].bar[].[baz] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-465 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-465 new file mode 100644 index 000000000..c6f77b80c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-465 @@ -0,0 +1 @@ +foo[].bar[].[baz, qux][] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-466 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-466 new file mode 100644 index 000000000..db56262a4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-466 @@ -0,0 +1 @@ +foo.[baz[*].bar, qux[0]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-467 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-467 new file mode 100644 index 000000000..b901067d2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-467 @@ -0,0 +1 @@ +foo.[baz[*].[bar, boo], qux[0]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-468 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-468 new file mode 100644 index 000000000..738479fa6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-468 @@ -0,0 +1 @@ +foo.[baz[*].not_there || baz[*].bar, qux[0]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-469 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-469 new file mode 100644 index 000000000..6926996a7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-469 @@ -0,0 +1 @@ +[[*],*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-47 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-47 new file mode 100644 index 000000000..6d33cc72c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-47 @@ -0,0 +1 @@ +foo[?key == `1`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-470 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-470 new file mode 100644 index 000000000..736be0a31 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-470 @@ -0,0 +1 @@ +[[*]] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-471 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-471 new file mode 100644 index 000000000..29e1fb20a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-471 @@ -0,0 +1 @@ +outer.foo || outer.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-472 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-472 new file mode 100644 index 000000000..c0070ba78 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-472 @@ -0,0 +1 @@ +outer.foo||outer.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-473 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-473 new file mode 100644 index 000000000..661b0bec5 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-473 @@ -0,0 +1 @@ +outer.bar || outer.baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-474 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-474 new file mode 100644 index 000000000..296d5aeee --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-474 @@ -0,0 +1 @@ +outer.bar||outer.baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-475 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-475 new file mode 100644 index 000000000..ca140f8aa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-475 @@ -0,0 +1 @@ +outer.bad || outer.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-476 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-476 new file mode 100644 index 000000000..15d309242 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-476 @@ -0,0 +1 @@ +outer.bad||outer.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-477 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-477 new file mode 100644 index 000000000..56148d957 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-477 @@ -0,0 +1 @@ +outer.foo || outer.bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-478 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-478 new file mode 100644 index 000000000..6d3cf6d90 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-478 @@ -0,0 +1 @@ +outer.foo||outer.bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-479 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-479 new file mode 100644 index 000000000..100fa8339 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-479 @@ -0,0 +1 @@ +outer.bad || outer.alsobad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-48 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-48 new file mode 100644 index 000000000..de56fc042 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-48 @@ -0,0 +1 @@ +foo[?key == `[0]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-480 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-480 new file mode 100644 index 000000000..64490352b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-480 @@ -0,0 +1 @@ +outer.bad||outer.alsobad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-481 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-481 new file mode 100644 index 000000000..af901bde1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-481 @@ -0,0 +1 @@ +outer.empty_string || outer.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-482 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-482 new file mode 100644 index 000000000..36b63e462 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-482 @@ -0,0 +1 @@ +outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-483 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-483 new file mode 100644 index 000000000..aba584f99 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-483 @@ -0,0 +1 @@ +foo.*.baz | [0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-484 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-484 new file mode 100644 index 000000000..4234ac019 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-484 @@ -0,0 +1 @@ +foo.*.baz | [1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-485 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-485 new file mode 100644 index 000000000..12330d990 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-485 @@ -0,0 +1 @@ +foo.*.baz | [2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-486 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-486 new file mode 100644 index 000000000..1b2d93e19 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-486 @@ -0,0 +1 @@ +foo.bar.* | [0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-487 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-487 new file mode 100644 index 000000000..c371fc645 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-487 @@ -0,0 +1 @@ +foo.*.notbaz | [*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-488 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-488 new file mode 100644 index 000000000..3c835642e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-488 @@ -0,0 +1 @@ +foo | bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-489 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-489 new file mode 100644 index 000000000..decaa0421 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-489 @@ -0,0 +1 @@ +foo | bar | baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-49 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-49 new file mode 100644 index 000000000..49d9c63a3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-49 @@ -0,0 +1 @@ +foo[?key == `{"bar": [0]}`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-490 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-490 new file mode 100644 index 000000000..b91068037 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-490 @@ -0,0 +1 @@ +foo|bar| baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-491 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-491 new file mode 100644 index 000000000..11df74d8b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-491 @@ -0,0 +1 @@ +not_there | [0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-492 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-492 new file mode 100644 index 000000000..11df74d8b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-492 @@ -0,0 +1 @@ +not_there | [0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-493 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-493 new file mode 100644 index 000000000..37da9fc0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-493 @@ -0,0 +1 @@ +[foo.bar, foo.other] | [0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-494 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-494 new file mode 100644 index 000000000..1f4fc943d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-494 @@ -0,0 +1 @@ +{"a": foo.bar, "b": foo.other} | a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-495 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-495 new file mode 100644 index 000000000..67c7ea9cf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-495 @@ -0,0 +1 @@ +{"a": foo.bar, "b": foo.other} | b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-496 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-496 new file mode 100644 index 000000000..d87f9bba4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-496 @@ -0,0 +1 @@ +{"a": foo.bar, "b": foo.other} | *.baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-497 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-497 new file mode 100644 index 000000000..ebf8e2711 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-497 @@ -0,0 +1 @@ +foo.bam || foo.bar | baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-498 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-498 new file mode 100644 index 000000000..f32bc6db5 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-498 @@ -0,0 +1 @@ +foo | not_there || bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-499 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-499 new file mode 100644 index 000000000..d04459d90 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-499 @@ -0,0 +1 @@ +foo[*].bar[*] | [0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-5 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-5 new file mode 100644 index 000000000..b537264a1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-5 @@ -0,0 +1 @@ +foo.bar.bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-50 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-50 new file mode 100644 index 000000000..c17c1df17 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-50 @@ -0,0 +1 @@ +foo[?key == `null`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-500 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-500 new file mode 100644 index 000000000..3eb869f43 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-500 @@ -0,0 +1 @@ +bar[0:10] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-501 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-501 new file mode 100644 index 000000000..aa5d6be52 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-501 @@ -0,0 +1 @@ +foo[0:10:1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-502 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-502 new file mode 100644 index 000000000..1a4d1682d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-502 @@ -0,0 +1 @@ +foo[0:10] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-503 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-503 new file mode 100644 index 000000000..5925a578b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-503 @@ -0,0 +1 @@ +foo[0:10:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-504 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-504 new file mode 100644 index 000000000..081e93abd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-504 @@ -0,0 +1 @@ +foo[0::1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-505 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-505 new file mode 100644 index 000000000..922700149 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-505 @@ -0,0 +1 @@ +foo[0::] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-506 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-506 new file mode 100644 index 000000000..fd2294d66 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-506 @@ -0,0 +1 @@ +foo[0:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-507 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-507 new file mode 100644 index 000000000..c6b551d5e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-507 @@ -0,0 +1 @@ +foo[:10:1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-508 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-508 new file mode 100644 index 000000000..503f58da6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-508 @@ -0,0 +1 @@ +foo[::1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-509 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-509 new file mode 100644 index 000000000..f78bb770c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-509 @@ -0,0 +1 @@ +foo[:10:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-51 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-51 new file mode 100644 index 000000000..589a214f4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-51 @@ -0,0 +1 @@ +foo[?key == `[1]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-510 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-510 new file mode 100644 index 000000000..eb9d2ba88 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-510 @@ -0,0 +1 @@ +foo[::] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-511 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-511 new file mode 100644 index 000000000..1921a3d98 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-511 @@ -0,0 +1 @@ +foo[:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-512 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-512 new file mode 100644 index 000000000..a87afcb1b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-512 @@ -0,0 +1 @@ +foo[1:9] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-513 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-513 new file mode 100644 index 000000000..dbf51d8cd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-513 @@ -0,0 +1 @@ +foo[0:10:2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-514 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-514 new file mode 100644 index 000000000..f7288763a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-514 @@ -0,0 +1 @@ +foo[5:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-515 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-515 new file mode 100644 index 000000000..64395761d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-515 @@ -0,0 +1 @@ +foo[5::2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-516 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-516 new file mode 100644 index 000000000..706bb14dd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-516 @@ -0,0 +1 @@ +foo[::2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-517 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-517 new file mode 100644 index 000000000..8fcfaee95 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-517 @@ -0,0 +1 @@ +foo[::-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-518 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-518 new file mode 100644 index 000000000..f6a00bf9b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-518 @@ -0,0 +1 @@ +foo[1::2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-519 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-519 new file mode 100644 index 000000000..ea068ee06 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-519 @@ -0,0 +1 @@ +foo[10:0:-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-52 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-52 new file mode 100644 index 000000000..214917ac0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-52 @@ -0,0 +1 @@ +foo[?key == `{"a":2}`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-520 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-520 new file mode 100644 index 000000000..1fe14258e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-520 @@ -0,0 +1 @@ +foo[10:5:-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-521 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-521 new file mode 100644 index 000000000..4ba0e1302 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-521 @@ -0,0 +1 @@ +foo[8:2:-2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-522 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-522 new file mode 100644 index 000000000..25db439ff --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-522 @@ -0,0 +1 @@ +foo[0:20] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-523 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-523 new file mode 100644 index 000000000..8a965920a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-523 @@ -0,0 +1 @@ +foo[10:-20:-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-524 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-524 new file mode 100644 index 000000000..b1e5ba373 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-524 @@ -0,0 +1 @@ +foo[10:-20] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-525 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-525 new file mode 100644 index 000000000..06253112e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-525 @@ -0,0 +1 @@ +foo[-4:-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-526 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-526 new file mode 100644 index 000000000..1e14a6a4c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-526 @@ -0,0 +1 @@ +foo[:-5:-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-527 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-527 new file mode 100644 index 000000000..aef5c2747 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-527 @@ -0,0 +1 @@ +foo[:2].a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-528 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-528 new file mode 100644 index 000000000..93c95fcf6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-528 @@ -0,0 +1 @@ +foo[:2].b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-529 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-529 new file mode 100644 index 000000000..7e0733e59 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-529 @@ -0,0 +1 @@ +foo[:2].a.b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-53 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-53 new file mode 100644 index 000000000..4c002ed80 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-53 @@ -0,0 +1 @@ +foo[?`true` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-530 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-530 new file mode 100644 index 000000000..2438b2576 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-530 @@ -0,0 +1 @@ +bar[::-1].a.b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-531 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-531 new file mode 100644 index 000000000..549994b6b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-531 @@ -0,0 +1 @@ +bar[:2].a.b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-532 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-532 new file mode 100644 index 000000000..ab98292b4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-532 @@ -0,0 +1 @@ +baz[:2].a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-533 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-533 new file mode 100644 index 000000000..65fca9687 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-533 @@ -0,0 +1 @@ +[:] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-534 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-534 new file mode 100644 index 000000000..18c5daf7b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-534 @@ -0,0 +1 @@ +[:2].a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-535 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-535 new file mode 100644 index 000000000..1bb84f7d4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-535 @@ -0,0 +1 @@ +[::-1].a \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-536 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-536 new file mode 100644 index 000000000..7a0416f05 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-536 @@ -0,0 +1 @@ +[:2].b \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-537 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-537 new file mode 100644 index 000000000..4d5f9756e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-537 @@ -0,0 +1 @@ +foo.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-538 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-538 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-538 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-539 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-539 new file mode 100644 index 000000000..f59ec20aa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-539 @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-54 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-54 new file mode 100644 index 000000000..23d27073e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-54 @@ -0,0 +1 @@ +foo[?`false` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-540 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-540 new file mode 100644 index 000000000..dee569574 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-540 @@ -0,0 +1 @@ +*.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-541 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-541 new file mode 100644 index 000000000..1a16f7418 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-541 @@ -0,0 +1 @@ +*.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-542 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-542 new file mode 100644 index 000000000..7e8066d39 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-542 @@ -0,0 +1 @@ +*[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-543 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-543 new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-543 @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-544 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-544 new file mode 100644 index 000000000..6e7ea636e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-544 @@ -0,0 +1 @@ +[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-545 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-545 new file mode 100644 index 000000000..5a5194647 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-545 @@ -0,0 +1 @@ +[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-546 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-546 new file mode 100644 index 000000000..416127425 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-546 @@ -0,0 +1 @@ +*.["0"] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-547 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-547 new file mode 100644 index 000000000..cd9fb6ba7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-547 @@ -0,0 +1 @@ +[*].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-548 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-548 new file mode 100644 index 000000000..9f3ada480 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-548 @@ -0,0 +1 @@ +[*][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-549 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-549 new file mode 100644 index 000000000..9b0b2f818 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-549 @@ -0,0 +1 @@ +foo[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-55 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-55 new file mode 100644 index 000000000..6d840ee56 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-55 @@ -0,0 +1 @@ +foo[?`0` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-550 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-550 new file mode 100644 index 000000000..b23413b92 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-550 @@ -0,0 +1 @@ +foo.[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-551 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-551 new file mode 100644 index 000000000..08ab2e1c4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-551 @@ -0,0 +1 @@ +foo.[abc] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-552 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-552 new file mode 100644 index 000000000..78b05a5c6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-552 @@ -0,0 +1 @@ +foo.[abc, def] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-553 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-553 new file mode 100644 index 000000000..1e7b886e7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-553 @@ -0,0 +1 @@ +a.{foo: bar} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-554 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-554 new file mode 100644 index 000000000..91b4c9896 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-554 @@ -0,0 +1 @@ +a.{foo: bar, baz: bam} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-555 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-555 new file mode 100644 index 000000000..8301ef981 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-555 @@ -0,0 +1 @@ +{"\\":{" ":*}} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-556 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-556 new file mode 100644 index 000000000..8f75cc913 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-556 @@ -0,0 +1 @@ +foo || bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-557 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-557 new file mode 100644 index 000000000..e5f122c56 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-557 @@ -0,0 +1 @@ +foo.[a || b] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-558 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-558 new file mode 100644 index 000000000..39d191432 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-558 @@ -0,0 +1 @@ +foo[?bar==`"baz"`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-559 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-559 new file mode 100644 index 000000000..d08bbe250 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-559 @@ -0,0 +1 @@ +foo[? bar == `"baz"` ] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-56 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-56 new file mode 100644 index 000000000..addaf204c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-56 @@ -0,0 +1 @@ +foo[?`1` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-560 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-560 new file mode 100644 index 000000000..a77f35581 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-560 @@ -0,0 +1 @@ +foo[?a.b.c==d.e.f] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-561 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-561 new file mode 100644 index 000000000..c9697aa48 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-561 @@ -0,0 +1 @@ +foo[?bar==`[0, 1, 2]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-562 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-562 new file mode 100644 index 000000000..fd7064a08 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-562 @@ -0,0 +1 @@ +foo[?bar==`["a", "b", "c"]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-563 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-563 new file mode 100644 index 000000000..61e5e1b8f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-563 @@ -0,0 +1 @@ +foo[?bar==`["foo\`bar"]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-564 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-564 new file mode 100644 index 000000000..bc9d8af1d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-564 @@ -0,0 +1 @@ +[?"\\">`"foo"`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-565 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-565 new file mode 100644 index 000000000..2dd54dc39 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-565 @@ -0,0 +1 @@ +[?"\\" > `"foo"`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-566 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-566 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-566 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-567 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-567 new file mode 100644 index 000000000..7e9668e78 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-567 @@ -0,0 +1 @@ +"foo" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-568 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-568 new file mode 100644 index 000000000..d58ac16bf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-568 @@ -0,0 +1 @@ +"\\" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-569 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-569 new file mode 100644 index 000000000..33ac9fba6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-569 @@ -0,0 +1 @@ +*||*|*|* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-57 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-57 new file mode 100644 index 000000000..acf2435c7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-57 @@ -0,0 +1 @@ +foo[?`[0]` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-570 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-570 new file mode 100644 index 000000000..99e19638c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-570 @@ -0,0 +1 @@ +*[]||[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-571 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-571 new file mode 100644 index 000000000..be0845011 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-571 @@ -0,0 +1 @@ +[*.*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-572 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-572 new file mode 100644 index 000000000..a84b51e1c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-572 @@ -0,0 +1 @@ +foo[]."✓" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-573 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-573 new file mode 100644 index 000000000..c2de55815 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-573 @@ -0,0 +1 @@ +"☯" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-574 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-574 new file mode 100644 index 000000000..dc2dda0bb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-574 @@ -0,0 +1 @@ +"♪♫•*¨*•.¸¸â¤Â¸Â¸.•*¨*•♫♪" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-575 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-575 new file mode 100644 index 000000000..a2d3d5f6a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-575 @@ -0,0 +1 @@ +"☃" \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-576 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-576 new file mode 100644 index 000000000..0971c37ea --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-576 @@ -0,0 +1 @@ +foo.*.baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-577 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-577 new file mode 100644 index 000000000..0e39dfd69 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-577 @@ -0,0 +1 @@ +foo.bar.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-578 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-578 new file mode 100644 index 000000000..89c1ce22d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-578 @@ -0,0 +1 @@ +foo.*.notbaz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-579 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-579 new file mode 100644 index 000000000..5199b9f95 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-579 @@ -0,0 +1 @@ +foo.*.notbaz[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-58 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-58 new file mode 100644 index 000000000..99fe382c6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-58 @@ -0,0 +1 @@ +foo[?`{"bar": [0]}` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-580 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-580 new file mode 100644 index 000000000..5bb6d4ae7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-580 @@ -0,0 +1 @@ +foo.*.notbaz[-1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-581 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-581 new file mode 100644 index 000000000..edac73189 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-581 @@ -0,0 +1 @@ +foo.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-582 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-582 new file mode 100644 index 000000000..458d0a6dd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-582 @@ -0,0 +1 @@ +foo.*.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-583 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-583 new file mode 100644 index 000000000..f757fd534 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-583 @@ -0,0 +1 @@ +foo.*.*.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-584 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-584 new file mode 100644 index 000000000..670049d96 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-584 @@ -0,0 +1 @@ +foo.*.*.*.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-585 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-585 new file mode 100644 index 000000000..3c88caafe --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-585 @@ -0,0 +1 @@ +*.bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-586 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-586 new file mode 100644 index 000000000..f59ec20aa --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-586 @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-587 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-587 new file mode 100644 index 000000000..0852fcc78 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-587 @@ -0,0 +1 @@ +*.sub1 \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-588 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-588 new file mode 100644 index 000000000..dee569574 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-588 @@ -0,0 +1 @@ +*.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-589 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-589 new file mode 100644 index 000000000..66781bba4 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-589 @@ -0,0 +1 @@ +*.*.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-59 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-59 new file mode 100644 index 000000000..4aad20ae6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-59 @@ -0,0 +1 @@ +foo[?`null` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-590 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-590 new file mode 100644 index 000000000..0db15d97e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-590 @@ -0,0 +1 @@ +*.sub1.foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-591 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-591 new file mode 100644 index 000000000..b24be9d7d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-591 @@ -0,0 +1 @@ +foo[*].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-592 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-592 new file mode 100644 index 000000000..e6efe133f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-592 @@ -0,0 +1 @@ +foo[*].notbar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-593 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-593 new file mode 100644 index 000000000..5a5194647 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-593 @@ -0,0 +1 @@ +[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-594 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-594 new file mode 100644 index 000000000..cd9fb6ba7 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-594 @@ -0,0 +1 @@ +[*].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-595 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-595 new file mode 100644 index 000000000..cbf1a5d59 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-595 @@ -0,0 +1 @@ +[*].notbar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-596 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-596 new file mode 100644 index 000000000..8bd13b7eb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-596 @@ -0,0 +1 @@ +foo.bar[*].baz \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-597 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-597 new file mode 100644 index 000000000..7239f3e88 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-597 @@ -0,0 +1 @@ +foo.bar[*].baz[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-598 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-598 new file mode 100644 index 000000000..f5e431d9e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-598 @@ -0,0 +1 @@ +foo.bar[*].baz[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-599 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-599 new file mode 100644 index 000000000..d0c259539 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-599 @@ -0,0 +1 @@ +foo.bar[*].baz[2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-6 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-6 new file mode 100644 index 000000000..b9749b748 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-6 @@ -0,0 +1 @@ +foo.bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-60 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-60 new file mode 100644 index 000000000..dac67509b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-60 @@ -0,0 +1 @@ +foo[?`[1]` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-600 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-600 new file mode 100644 index 000000000..a6388271e --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-600 @@ -0,0 +1 @@ +foo.bar[*].baz[3] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-601 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-601 new file mode 100644 index 000000000..2a66ffe93 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-601 @@ -0,0 +1 @@ +foo.bar[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-602 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-602 new file mode 100644 index 000000000..b6b369543 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-602 @@ -0,0 +1 @@ +foo.bar[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-603 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-603 new file mode 100644 index 000000000..7e57f9e74 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-603 @@ -0,0 +1 @@ +foo.bar[0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-604 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-604 new file mode 100644 index 000000000..c5f8bef0b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-604 @@ -0,0 +1 @@ +foo.bar[0][0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-605 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-605 new file mode 100644 index 000000000..3decf0803 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-605 @@ -0,0 +1 @@ +foo.bar[0][0][0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-606 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-606 new file mode 100644 index 000000000..655e2959b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-606 @@ -0,0 +1 @@ +foo[0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-607 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-607 new file mode 100644 index 000000000..2aa159718 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-607 @@ -0,0 +1 @@ +foo[*].bar[*].kind \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-608 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-608 new file mode 100644 index 000000000..556b380ba --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-608 @@ -0,0 +1 @@ +foo[*].bar[0].kind \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-609 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-609 new file mode 100644 index 000000000..0de3229b8 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-609 @@ -0,0 +1 @@ +foo[*].bar.kind \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-61 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-61 new file mode 100644 index 000000000..130ed3b37 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-61 @@ -0,0 +1 @@ +foo[?`{"a":2}` == key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-610 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-610 new file mode 100644 index 000000000..3b511f133 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-610 @@ -0,0 +1 @@ +foo[*].bar[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-611 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-611 new file mode 100644 index 000000000..c8dfa16e6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-611 @@ -0,0 +1 @@ +foo[*].bar[1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-612 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-612 new file mode 100644 index 000000000..69f04ee23 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-612 @@ -0,0 +1 @@ +foo[*].bar[2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-613 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-613 new file mode 100644 index 000000000..3b511f133 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-613 @@ -0,0 +1 @@ +foo[*].bar[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-614 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-614 new file mode 100644 index 000000000..03e0c0cb9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-614 @@ -0,0 +1 @@ +foo[*][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-615 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-615 new file mode 100644 index 000000000..ac1c89668 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-615 @@ -0,0 +1 @@ +foo[*][1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-616 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-616 new file mode 100644 index 000000000..03e0c0cb9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-616 @@ -0,0 +1 @@ +foo[*][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-617 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-617 new file mode 100644 index 000000000..ac1c89668 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-617 @@ -0,0 +1 @@ +foo[*][1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-618 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-618 new file mode 100644 index 000000000..6494cf1c6 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-618 @@ -0,0 +1 @@ +foo[*][0][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-619 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-619 new file mode 100644 index 000000000..1406be572 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-619 @@ -0,0 +1 @@ +foo[*][1][0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-62 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-62 new file mode 100644 index 000000000..3d15fcc16 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-62 @@ -0,0 +1 @@ +foo[?key != `true`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-620 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-620 new file mode 100644 index 000000000..72b5aa281 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-620 @@ -0,0 +1 @@ +foo[*][0][1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-621 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-621 new file mode 100644 index 000000000..02a26491a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-621 @@ -0,0 +1 @@ +foo[*][1][1] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-622 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-622 new file mode 100644 index 000000000..cb08037e2 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-622 @@ -0,0 +1 @@ +foo[*][2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-623 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-623 new file mode 100644 index 000000000..91d695995 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-623 @@ -0,0 +1 @@ +foo[*][2][2] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-624 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-624 new file mode 100644 index 000000000..f40f261ad --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-624 @@ -0,0 +1 @@ +bar[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-625 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-625 new file mode 100644 index 000000000..03904b1de --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-625 @@ -0,0 +1 @@ +bar[*].baz[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-626 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-626 new file mode 100644 index 000000000..fd7c21c34 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-626 @@ -0,0 +1 @@ +string[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-627 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-627 new file mode 100644 index 000000000..d7ca4719a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-627 @@ -0,0 +1 @@ +hash[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-628 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-628 new file mode 100644 index 000000000..b3ddffe3c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-628 @@ -0,0 +1 @@ +number[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-629 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-629 new file mode 100644 index 000000000..c03cd39eb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-629 @@ -0,0 +1 @@ +nullvalue[*] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-63 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-63 new file mode 100644 index 000000000..08731af69 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-63 @@ -0,0 +1 @@ +foo[?key != `false`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-630 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-630 new file mode 100644 index 000000000..b3c40cd53 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-630 @@ -0,0 +1 @@ +string[*].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-631 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-631 new file mode 100644 index 000000000..c5930d543 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-631 @@ -0,0 +1 @@ +hash[*].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-632 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-632 new file mode 100644 index 000000000..cc0b1a489 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-632 @@ -0,0 +1 @@ +number[*].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-633 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-633 new file mode 100644 index 000000000..d677b9658 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-633 @@ -0,0 +1 @@ +nullvalue[*].foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-634 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-634 new file mode 100644 index 000000000..c11666401 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-634 @@ -0,0 +1 @@ +nullvalue[*].foo[*].bar \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-635 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-635 new file mode 100644 index 000000000..e33997710 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-635 @@ -0,0 +1 @@ +string.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-636 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-636 new file mode 100644 index 000000000..76f53453a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-636 @@ -0,0 +1 @@ +hash.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-637 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-637 new file mode 100644 index 000000000..dd485072f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-637 @@ -0,0 +1 @@ +number.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-638 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-638 new file mode 100644 index 000000000..16000c003 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-638 @@ -0,0 +1 @@ +array.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-639 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-639 new file mode 100644 index 000000000..1d0d03ed3 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-639 @@ -0,0 +1 @@ +nullvalue.* \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-64 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-64 new file mode 100644 index 000000000..b67aebe98 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-64 @@ -0,0 +1 @@ +foo[?key != `0`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-640 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-640 new file mode 100644 index 000000000..7e8066d39 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-640 @@ -0,0 +1 @@ +*[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-641 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-641 new file mode 100644 index 000000000..41ebe5ba9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-641 @@ -0,0 +1 @@ +`foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-642 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-642 new file mode 100644 index 000000000..fe0397993 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-642 @@ -0,0 +1 @@ +`foo\"quote` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-643 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-643 new file mode 100644 index 000000000..1a27fd80c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-643 @@ -0,0 +1 @@ +`✓` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-644 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-644 new file mode 100644 index 000000000..559a13456 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-644 @@ -0,0 +1 @@ +`foo\"bar` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-645 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-645 new file mode 100644 index 000000000..e31621b43 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-645 @@ -0,0 +1 @@ +`1\`` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-646 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-646 new file mode 100644 index 000000000..6bf7a1036 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-646 @@ -0,0 +1 @@ +`\\`.{a:`b`} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-647 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-647 new file mode 100644 index 000000000..41ebe5ba9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-647 @@ -0,0 +1 @@ +`foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-648 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-648 new file mode 100644 index 000000000..28b9bcbbb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-648 @@ -0,0 +1 @@ +` foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-649 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-649 new file mode 100644 index 000000000..41ebe5ba9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-649 @@ -0,0 +1 @@ +`foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-65 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-65 new file mode 100644 index 000000000..d3ac793bb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-65 @@ -0,0 +1 @@ +foo[?key != `1`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-650 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-650 new file mode 100644 index 000000000..fe0397993 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-650 @@ -0,0 +1 @@ +`foo\"quote` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-651 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-651 new file mode 100644 index 000000000..1a27fd80c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-651 @@ -0,0 +1 @@ +`✓` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-652 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-652 new file mode 100644 index 000000000..559a13456 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-652 @@ -0,0 +1 @@ +`foo\"bar` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-653 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-653 new file mode 100644 index 000000000..e31621b43 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-653 @@ -0,0 +1 @@ +`1\`` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-654 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-654 new file mode 100644 index 000000000..6bf7a1036 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-654 @@ -0,0 +1 @@ +`\\`.{a:`b`} \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-655 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-655 new file mode 100644 index 000000000..41ebe5ba9 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-655 @@ -0,0 +1 @@ +`foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-656 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-656 new file mode 100644 index 000000000..28b9bcbbb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-656 @@ -0,0 +1 @@ +` foo` \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-66 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-66 new file mode 100644 index 000000000..065295bc1 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-66 @@ -0,0 +1 @@ +foo[?key != `null`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-67 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-67 new file mode 100644 index 000000000..43d164927 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-67 @@ -0,0 +1 @@ +foo[?key != `[1]`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-68 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-68 new file mode 100644 index 000000000..6b884fa86 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-68 @@ -0,0 +1 @@ +foo[?key != `{"a":2}`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-69 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-69 new file mode 100644 index 000000000..d85c779d0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-69 @@ -0,0 +1 @@ +foo[?`true` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-7 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-7 new file mode 100644 index 000000000..44d6628cd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-7 @@ -0,0 +1 @@ +bad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-70 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-70 new file mode 100644 index 000000000..3e6dcf304 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-70 @@ -0,0 +1 @@ +foo[?`false` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-71 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-71 new file mode 100644 index 000000000..bdb820b30 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-71 @@ -0,0 +1 @@ +foo[?`0` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-72 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-72 new file mode 100644 index 000000000..3f3048a00 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-72 @@ -0,0 +1 @@ +foo[?`1` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-73 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-73 new file mode 100644 index 000000000..dacc25724 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-73 @@ -0,0 +1 @@ +foo[?`null` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-74 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-74 new file mode 100644 index 000000000..32ebae880 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-74 @@ -0,0 +1 @@ +foo[?`[1]` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-75 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-75 new file mode 100644 index 000000000..dcd023e0f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-75 @@ -0,0 +1 @@ +foo[?`{"a":2}` != key] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-76 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-76 new file mode 100644 index 000000000..e08cc13cb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-76 @@ -0,0 +1 @@ +reservations[].instances[?bar==`1`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-77 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-77 new file mode 100644 index 000000000..1ec43f45f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-77 @@ -0,0 +1 @@ +reservations[*].instances[?bar==`1`] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-78 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-78 new file mode 100644 index 000000000..303871163 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-78 @@ -0,0 +1 @@ +reservations[].instances[?bar==`1`][] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-79 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-79 new file mode 100644 index 000000000..e3875746b --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-79 @@ -0,0 +1 @@ +foo[?bar==`1`].bar[0] \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-8 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-8 new file mode 100644 index 000000000..da7bc1ccf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-8 @@ -0,0 +1 @@ +bad.morebad.morebad \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-80 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-80 new file mode 100644 index 000000000..5c3d68356 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-80 @@ -0,0 +1 @@ +foo[?a==`1`].b.c \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-81 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-81 new file mode 100644 index 000000000..6232808f0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-81 @@ -0,0 +1 @@ +abs(foo) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-82 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-82 new file mode 100644 index 000000000..6232808f0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-82 @@ -0,0 +1 @@ +abs(foo) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-83 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-83 new file mode 100644 index 000000000..29497f4ff --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-83 @@ -0,0 +1 @@ +abs(array[1]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-84 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-84 new file mode 100644 index 000000000..29497f4ff --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-84 @@ -0,0 +1 @@ +abs(array[1]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-85 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-85 new file mode 100644 index 000000000..346696563 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-85 @@ -0,0 +1 @@ +abs(`-24`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-86 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-86 new file mode 100644 index 000000000..346696563 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-86 @@ -0,0 +1 @@ +abs(`-24`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-87 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-87 new file mode 100644 index 000000000..c6268f847 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-87 @@ -0,0 +1 @@ +avg(numbers) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-88 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-88 new file mode 100644 index 000000000..7ce703695 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-88 @@ -0,0 +1 @@ +ceil(`1.2`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-89 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-89 new file mode 100644 index 000000000..0561bc26d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-89 @@ -0,0 +1 @@ +ceil(decimals[0]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-9 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-9 new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-9 @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-90 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-90 new file mode 100644 index 000000000..c78c1fc30 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-90 @@ -0,0 +1 @@ +ceil(decimals[1]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-91 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-91 new file mode 100644 index 000000000..ebcb4bbdb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-91 @@ -0,0 +1 @@ +ceil(decimals[2]) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-92 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-92 new file mode 100644 index 000000000..6edbf1afe --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-92 @@ -0,0 +1 @@ +contains('abc', 'a') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-93 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-93 new file mode 100644 index 000000000..d2b2f070d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-93 @@ -0,0 +1 @@ +contains('abc', 'd') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-94 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-94 new file mode 100644 index 000000000..3535da2ec --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-94 @@ -0,0 +1 @@ +contains(strings, 'a') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-95 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-95 new file mode 100644 index 000000000..ba839fe60 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-95 @@ -0,0 +1 @@ +contains(decimals, `1.2`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-96 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-96 new file mode 100644 index 000000000..f43581869 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-96 @@ -0,0 +1 @@ +contains(decimals, `false`) \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-97 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-97 new file mode 100644 index 000000000..adb65fc01 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-97 @@ -0,0 +1 @@ +ends_with(str, 'r') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-98 b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-98 new file mode 100644 index 000000000..93d6901be --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-98 @@ -0,0 +1 @@ +ends_with(str, 'tr') \ No newline at end of file diff --git a/vendor/github.com/jmespath/go-jmespath/fuzz/jmespath.go b/vendor/github.com/jmespath/go-jmespath/fuzz/jmespath.go new file mode 100644 index 000000000..c7df08782 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/fuzz/jmespath.go @@ -0,0 +1,13 @@ +package jmespath + +import "github.com/jmespath/go-jmespath" + +// Fuzz will fuzz test the JMESPath parser. +func Fuzz(data []byte) int { + p := jmespath.NewParser() + _, err := p.Parse(string(data)) + if err != nil { + return 1 + } + return 0 +} diff --git a/vendor/github.com/jmespath/go-jmespath/interpreter.go b/vendor/github.com/jmespath/go-jmespath/interpreter.go new file mode 100644 index 000000000..13c74604c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/interpreter.go @@ -0,0 +1,418 @@ +package jmespath + +import ( + "errors" + "reflect" + "unicode" + "unicode/utf8" +) + +/* This is a tree based interpreter. It walks the AST and directly + interprets the AST to search through a JSON document. +*/ + +type treeInterpreter struct { + fCall *functionCaller +} + +func newInterpreter() *treeInterpreter { + interpreter := treeInterpreter{} + interpreter.fCall = newFunctionCaller() + return &interpreter +} + +type expRef struct { + ref ASTNode +} + +// Execute takes an ASTNode and input data and interprets the AST directly. +// It will produce the result of applying the JMESPath expression associated +// with the ASTNode to the input data "value". +func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) { + switch node.nodeType { + case ASTComparator: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + right, err := intr.Execute(node.children[1], value) + if err != nil { + return nil, err + } + switch node.value { + case tEQ: + return objsEqual(left, right), nil + case tNE: + return !objsEqual(left, right), nil + } + leftNum, ok := left.(float64) + if !ok { + return nil, nil + } + rightNum, ok := right.(float64) + if !ok { + return nil, nil + } + switch node.value { + case tGT: + return leftNum > rightNum, nil + case tGTE: + return leftNum >= rightNum, nil + case tLT: + return leftNum < rightNum, nil + case tLTE: + return leftNum <= rightNum, nil + } + case ASTExpRef: + return expRef{ref: node.children[0]}, nil + case ASTFunctionExpression: + resolvedArgs := []interface{}{} + for _, arg := range node.children { + current, err := intr.Execute(arg, value) + if err != nil { + return nil, err + } + resolvedArgs = append(resolvedArgs, current) + } + return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr) + case ASTField: + if m, ok := value.(map[string]interface{}); ok { + key := node.value.(string) + return m[key], nil + } + return intr.fieldFromStruct(node.value.(string), value) + case ASTFilterProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + sliceType, ok := left.([]interface{}) + if !ok { + if isSliceType(left) { + return intr.filterProjectionWithReflection(node, left) + } + return nil, nil + } + compareNode := node.children[2] + collected := []interface{}{} + for _, element := range sliceType { + result, err := intr.Execute(compareNode, element) + if err != nil { + return nil, err + } + if !isFalse(result) { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + } + return collected, nil + case ASTFlatten: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + sliceType, ok := left.([]interface{}) + if !ok { + // If we can't type convert to []interface{}, there's + // a chance this could still work via reflection if we're + // dealing with user provided types. + if isSliceType(left) { + return intr.flattenWithReflection(left) + } + return nil, nil + } + flattened := []interface{}{} + for _, element := range sliceType { + if elementSlice, ok := element.([]interface{}); ok { + flattened = append(flattened, elementSlice...) + } else if isSliceType(element) { + reflectFlat := []interface{}{} + v := reflect.ValueOf(element) + for i := 0; i < v.Len(); i++ { + reflectFlat = append(reflectFlat, v.Index(i).Interface()) + } + flattened = append(flattened, reflectFlat...) + } else { + flattened = append(flattened, element) + } + } + return flattened, nil + case ASTIdentity, ASTCurrentNode: + return value, nil + case ASTIndex: + if sliceType, ok := value.([]interface{}); ok { + index := node.value.(int) + if index < 0 { + index += len(sliceType) + } + if index < len(sliceType) && index >= 0 { + return sliceType[index], nil + } + return nil, nil + } + // Otherwise try via reflection. + rv := reflect.ValueOf(value) + if rv.Kind() == reflect.Slice { + index := node.value.(int) + if index < 0 { + index += rv.Len() + } + if index < rv.Len() && index >= 0 { + v := rv.Index(index) + return v.Interface(), nil + } + } + return nil, nil + case ASTKeyValPair: + return intr.Execute(node.children[0], value) + case ASTLiteral: + return node.value, nil + case ASTMultiSelectHash: + if value == nil { + return nil, nil + } + collected := make(map[string]interface{}) + for _, child := range node.children { + current, err := intr.Execute(child, value) + if err != nil { + return nil, err + } + key := child.value.(string) + collected[key] = current + } + return collected, nil + case ASTMultiSelectList: + if value == nil { + return nil, nil + } + collected := []interface{}{} + for _, child := range node.children { + current, err := intr.Execute(child, value) + if err != nil { + return nil, err + } + collected = append(collected, current) + } + return collected, nil + case ASTOrExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + matched, err = intr.Execute(node.children[1], value) + if err != nil { + return nil, err + } + } + return matched, nil + case ASTAndExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + return matched, nil + } + return intr.Execute(node.children[1], value) + case ASTNotExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + return true, nil + } + return false, nil + case ASTPipe: + result := value + var err error + for _, child := range node.children { + result, err = intr.Execute(child, result) + if err != nil { + return nil, err + } + } + return result, nil + case ASTProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + sliceType, ok := left.([]interface{}) + if !ok { + if isSliceType(left) { + return intr.projectWithReflection(node, left) + } + return nil, nil + } + collected := []interface{}{} + var current interface{} + for _, element := range sliceType { + current, err = intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + return collected, nil + case ASTSubexpression, ASTIndexExpression: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + return intr.Execute(node.children[1], left) + case ASTSlice: + sliceType, ok := value.([]interface{}) + if !ok { + if isSliceType(value) { + return intr.sliceWithReflection(node, value) + } + return nil, nil + } + parts := node.value.([]*int) + sliceParams := make([]sliceParam, 3) + for i, part := range parts { + if part != nil { + sliceParams[i].Specified = true + sliceParams[i].N = *part + } + } + return slice(sliceType, sliceParams) + case ASTValueProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + mapType, ok := left.(map[string]interface{}) + if !ok { + return nil, nil + } + values := make([]interface{}, len(mapType)) + for _, value := range mapType { + values = append(values, value) + } + collected := []interface{}{} + for _, element := range values { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + return collected, nil + } + return nil, errors.New("Unknown AST node: " + node.nodeType.String()) +} + +func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) { + rv := reflect.ValueOf(value) + first, n := utf8.DecodeRuneInString(key) + fieldName := string(unicode.ToUpper(first)) + key[n:] + if rv.Kind() == reflect.Struct { + v := rv.FieldByName(fieldName) + if !v.IsValid() { + return nil, nil + } + return v.Interface(), nil + } else if rv.Kind() == reflect.Ptr { + // Handle multiple levels of indirection? + if rv.IsNil() { + return nil, nil + } + rv = rv.Elem() + v := rv.FieldByName(fieldName) + if !v.IsValid() { + return nil, nil + } + return v.Interface(), nil + } + return nil, nil +} + +func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) { + v := reflect.ValueOf(value) + flattened := []interface{}{} + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + if reflect.TypeOf(element).Kind() == reflect.Slice { + // Then insert the contents of the element + // slice into the flattened slice, + // i.e flattened = append(flattened, mySlice...) + elementV := reflect.ValueOf(element) + for j := 0; j < elementV.Len(); j++ { + flattened = append( + flattened, elementV.Index(j).Interface()) + } + } else { + flattened = append(flattened, element) + } + } + return flattened, nil +} + +func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) { + v := reflect.ValueOf(value) + parts := node.value.([]*int) + sliceParams := make([]sliceParam, 3) + for i, part := range parts { + if part != nil { + sliceParams[i].Specified = true + sliceParams[i].N = *part + } + } + final := []interface{}{} + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + final = append(final, element) + } + return slice(final, sliceParams) +} + +func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) { + compareNode := node.children[2] + collected := []interface{}{} + v := reflect.ValueOf(value) + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + result, err := intr.Execute(compareNode, element) + if err != nil { + return nil, err + } + if !isFalse(result) { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + } + return collected, nil +} + +func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) { + collected := []interface{}{} + v := reflect.ValueOf(value) + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + result, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if result != nil { + collected = append(collected, result) + } + } + return collected, nil +} diff --git a/vendor/github.com/jmespath/go-jmespath/lexer.go b/vendor/github.com/jmespath/go-jmespath/lexer.go new file mode 100644 index 000000000..817900c8f --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/lexer.go @@ -0,0 +1,420 @@ +package jmespath + +import ( + "bytes" + "encoding/json" + "fmt" + "strconv" + "strings" + "unicode/utf8" +) + +type token struct { + tokenType tokType + value string + position int + length int +} + +type tokType int + +const eof = -1 + +// Lexer contains information about the expression being tokenized. +type Lexer struct { + expression string // The expression provided by the user. + currentPos int // The current position in the string. + lastWidth int // The width of the current rune. This + buf bytes.Buffer // Internal buffer used for building up values. +} + +// SyntaxError is the main error used whenever a lexing or parsing error occurs. +type SyntaxError struct { + msg string // Error message displayed to user + Expression string // Expression that generated a SyntaxError + Offset int // The location in the string where the error occurred +} + +func (e SyntaxError) Error() string { + // In the future, it would be good to underline the specific + // location where the error occurred. + return "SyntaxError: " + e.msg +} + +// HighlightLocation will show where the syntax error occurred. +// It will place a "^" character on a line below the expression +// at the point where the syntax error occurred. +func (e SyntaxError) HighlightLocation() string { + return e.Expression + "\n" + strings.Repeat(" ", e.Offset) + "^" +} + +//go:generate stringer -type=tokType +const ( + tUnknown tokType = iota + tStar + tDot + tFilter + tFlatten + tLparen + tRparen + tLbracket + tRbracket + tLbrace + tRbrace + tOr + tPipe + tNumber + tUnquotedIdentifier + tQuotedIdentifier + tComma + tColon + tLT + tLTE + tGT + tGTE + tEQ + tNE + tJSONLiteral + tStringLiteral + tCurrent + tExpref + tAnd + tNot + tEOF +) + +var basicTokens = map[rune]tokType{ + '.': tDot, + '*': tStar, + ',': tComma, + ':': tColon, + '{': tLbrace, + '}': tRbrace, + ']': tRbracket, // tLbracket not included because it could be "[]" + '(': tLparen, + ')': tRparen, + '@': tCurrent, +} + +// Bit mask for [a-zA-Z_] shifted down 64 bits to fit in a single uint64. +// When using this bitmask just be sure to shift the rune down 64 bits +// before checking against identifierStartBits. +const identifierStartBits uint64 = 576460745995190270 + +// Bit mask for [a-zA-Z0-9], 128 bits -> 2 uint64s. +var identifierTrailingBits = [2]uint64{287948901175001088, 576460745995190270} + +var whiteSpace = map[rune]bool{ + ' ': true, '\t': true, '\n': true, '\r': true, +} + +func (t token) String() string { + return fmt.Sprintf("Token{%+v, %s, %d, %d}", + t.tokenType, t.value, t.position, t.length) +} + +// NewLexer creates a new JMESPath lexer. +func NewLexer() *Lexer { + lexer := Lexer{} + return &lexer +} + +func (lexer *Lexer) next() rune { + if lexer.currentPos >= len(lexer.expression) { + lexer.lastWidth = 0 + return eof + } + r, w := utf8.DecodeRuneInString(lexer.expression[lexer.currentPos:]) + lexer.lastWidth = w + lexer.currentPos += w + return r +} + +func (lexer *Lexer) back() { + lexer.currentPos -= lexer.lastWidth +} + +func (lexer *Lexer) peek() rune { + t := lexer.next() + lexer.back() + return t +} + +// tokenize takes an expression and returns corresponding tokens. +func (lexer *Lexer) tokenize(expression string) ([]token, error) { + var tokens []token + lexer.expression = expression + lexer.currentPos = 0 + lexer.lastWidth = 0 +loop: + for { + r := lexer.next() + if identifierStartBits&(1<<(uint64(r)-64)) > 0 { + t := lexer.consumeUnquotedIdentifier() + tokens = append(tokens, t) + } else if val, ok := basicTokens[r]; ok { + // Basic single char token. + t := token{ + tokenType: val, + value: string(r), + position: lexer.currentPos - lexer.lastWidth, + length: 1, + } + tokens = append(tokens, t) + } else if r == '-' || (r >= '0' && r <= '9') { + t := lexer.consumeNumber() + tokens = append(tokens, t) + } else if r == '[' { + t := lexer.consumeLBracket() + tokens = append(tokens, t) + } else if r == '"' { + t, err := lexer.consumeQuotedIdentifier() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '\'' { + t, err := lexer.consumeRawStringLiteral() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '`' { + t, err := lexer.consumeLiteral() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '|' { + t := lexer.matchOrElse(r, '|', tOr, tPipe) + tokens = append(tokens, t) + } else if r == '<' { + t := lexer.matchOrElse(r, '=', tLTE, tLT) + tokens = append(tokens, t) + } else if r == '>' { + t := lexer.matchOrElse(r, '=', tGTE, tGT) + tokens = append(tokens, t) + } else if r == '!' { + t := lexer.matchOrElse(r, '=', tNE, tNot) + tokens = append(tokens, t) + } else if r == '=' { + t := lexer.matchOrElse(r, '=', tEQ, tUnknown) + tokens = append(tokens, t) + } else if r == '&' { + t := lexer.matchOrElse(r, '&', tAnd, tExpref) + tokens = append(tokens, t) + } else if r == eof { + break loop + } else if _, ok := whiteSpace[r]; ok { + // Ignore whitespace + } else { + return tokens, lexer.syntaxError(fmt.Sprintf("Unknown char: %s", strconv.QuoteRuneToASCII(r))) + } + } + tokens = append(tokens, token{tEOF, "", len(lexer.expression), 0}) + return tokens, nil +} + +// Consume characters until the ending rune "r" is reached. +// If the end of the expression is reached before seeing the +// terminating rune "r", then an error is returned. +// If no error occurs then the matching substring is returned. +// The returned string will not include the ending rune. +func (lexer *Lexer) consumeUntil(end rune) (string, error) { + start := lexer.currentPos + current := lexer.next() + for current != end && current != eof { + if current == '\\' && lexer.peek() != eof { + lexer.next() + } + current = lexer.next() + } + if lexer.lastWidth == 0 { + // Then we hit an EOF so we never reached the closing + // delimiter. + return "", SyntaxError{ + msg: "Unclosed delimiter: " + string(end), + Expression: lexer.expression, + Offset: len(lexer.expression), + } + } + return lexer.expression[start : lexer.currentPos-lexer.lastWidth], nil +} + +func (lexer *Lexer) consumeLiteral() (token, error) { + start := lexer.currentPos + value, err := lexer.consumeUntil('`') + if err != nil { + return token{}, err + } + value = strings.Replace(value, "\\`", "`", -1) + return token{ + tokenType: tJSONLiteral, + value: value, + position: start, + length: len(value), + }, nil +} + +func (lexer *Lexer) consumeRawStringLiteral() (token, error) { + start := lexer.currentPos + currentIndex := start + current := lexer.next() + for current != '\'' && lexer.peek() != eof { + if current == '\\' && lexer.peek() == '\'' { + chunk := lexer.expression[currentIndex : lexer.currentPos-1] + lexer.buf.WriteString(chunk) + lexer.buf.WriteString("'") + lexer.next() + currentIndex = lexer.currentPos + } + current = lexer.next() + } + if lexer.lastWidth == 0 { + // Then we hit an EOF so we never reached the closing + // delimiter. + return token{}, SyntaxError{ + msg: "Unclosed delimiter: '", + Expression: lexer.expression, + Offset: len(lexer.expression), + } + } + if currentIndex < lexer.currentPos { + lexer.buf.WriteString(lexer.expression[currentIndex : lexer.currentPos-1]) + } + value := lexer.buf.String() + // Reset the buffer so it can reused again. + lexer.buf.Reset() + return token{ + tokenType: tStringLiteral, + value: value, + position: start, + length: len(value), + }, nil +} + +func (lexer *Lexer) syntaxError(msg string) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: lexer.expression, + Offset: lexer.currentPos - 1, + } +} + +// Checks for a two char token, otherwise matches a single character +// token. This is used whenever a two char token overlaps a single +// char token, e.g. "||" -> tPipe, "|" -> tOr. +func (lexer *Lexer) matchOrElse(first rune, second rune, matchedType tokType, singleCharType tokType) token { + start := lexer.currentPos - lexer.lastWidth + nextRune := lexer.next() + var t token + if nextRune == second { + t = token{ + tokenType: matchedType, + value: string(first) + string(second), + position: start, + length: 2, + } + } else { + lexer.back() + t = token{ + tokenType: singleCharType, + value: string(first), + position: start, + length: 1, + } + } + return t +} + +func (lexer *Lexer) consumeLBracket() token { + // There's three options here: + // 1. A filter expression "[?" + // 2. A flatten operator "[]" + // 3. A bare rbracket "[" + start := lexer.currentPos - lexer.lastWidth + nextRune := lexer.next() + var t token + if nextRune == '?' { + t = token{ + tokenType: tFilter, + value: "[?", + position: start, + length: 2, + } + } else if nextRune == ']' { + t = token{ + tokenType: tFlatten, + value: "[]", + position: start, + length: 2, + } + } else { + t = token{ + tokenType: tLbracket, + value: "[", + position: start, + length: 1, + } + lexer.back() + } + return t +} + +func (lexer *Lexer) consumeQuotedIdentifier() (token, error) { + start := lexer.currentPos + value, err := lexer.consumeUntil('"') + if err != nil { + return token{}, err + } + var decoded string + asJSON := []byte("\"" + value + "\"") + if err := json.Unmarshal([]byte(asJSON), &decoded); err != nil { + return token{}, err + } + return token{ + tokenType: tQuotedIdentifier, + value: decoded, + position: start - 1, + length: len(decoded), + }, nil +} + +func (lexer *Lexer) consumeUnquotedIdentifier() token { + // Consume runes until we reach the end of an unquoted + // identifier. + start := lexer.currentPos - lexer.lastWidth + for { + r := lexer.next() + if r < 0 || r > 128 || identifierTrailingBits[uint64(r)/64]&(1<<(uint64(r)%64)) == 0 { + lexer.back() + break + } + } + value := lexer.expression[start:lexer.currentPos] + return token{ + tokenType: tUnquotedIdentifier, + value: value, + position: start, + length: lexer.currentPos - start, + } +} + +func (lexer *Lexer) consumeNumber() token { + // Consume runes until we reach something that's not a number. + start := lexer.currentPos - lexer.lastWidth + for { + r := lexer.next() + if r < '0' || r > '9' { + lexer.back() + break + } + } + value := lexer.expression[start:lexer.currentPos] + return token{ + tokenType: tNumber, + value: value, + position: start, + length: lexer.currentPos - start, + } +} diff --git a/vendor/github.com/jmespath/go-jmespath/parser.go b/vendor/github.com/jmespath/go-jmespath/parser.go new file mode 100644 index 000000000..c8f4bcebd --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/parser.go @@ -0,0 +1,603 @@ +package jmespath + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +type astNodeType int + +//go:generate stringer -type astNodeType +const ( + ASTEmpty astNodeType = iota + ASTComparator + ASTCurrentNode + ASTExpRef + ASTFunctionExpression + ASTField + ASTFilterProjection + ASTFlatten + ASTIdentity + ASTIndex + ASTIndexExpression + ASTKeyValPair + ASTLiteral + ASTMultiSelectHash + ASTMultiSelectList + ASTOrExpression + ASTAndExpression + ASTNotExpression + ASTPipe + ASTProjection + ASTSubexpression + ASTSlice + ASTValueProjection +) + +// ASTNode represents the abstract syntax tree of a JMESPath expression. +type ASTNode struct { + nodeType astNodeType + value interface{} + children []ASTNode +} + +func (node ASTNode) String() string { + return node.PrettyPrint(0) +} + +// PrettyPrint will pretty print the parsed AST. +// The AST is an implementation detail and this pretty print +// function is provided as a convenience method to help with +// debugging. You should not rely on its output as the internal +// structure of the AST may change at any time. +func (node ASTNode) PrettyPrint(indent int) string { + spaces := strings.Repeat(" ", indent) + output := fmt.Sprintf("%s%s {\n", spaces, node.nodeType) + nextIndent := indent + 2 + if node.value != nil { + if converted, ok := node.value.(fmt.Stringer); ok { + // Account for things like comparator nodes + // that are enums with a String() method. + output += fmt.Sprintf("%svalue: %s\n", strings.Repeat(" ", nextIndent), converted.String()) + } else { + output += fmt.Sprintf("%svalue: %#v\n", strings.Repeat(" ", nextIndent), node.value) + } + } + lastIndex := len(node.children) + if lastIndex > 0 { + output += fmt.Sprintf("%schildren: {\n", strings.Repeat(" ", nextIndent)) + childIndent := nextIndent + 2 + for _, elem := range node.children { + output += elem.PrettyPrint(childIndent) + } + } + output += fmt.Sprintf("%s}\n", spaces) + return output +} + +var bindingPowers = map[tokType]int{ + tEOF: 0, + tUnquotedIdentifier: 0, + tQuotedIdentifier: 0, + tRbracket: 0, + tRparen: 0, + tComma: 0, + tRbrace: 0, + tNumber: 0, + tCurrent: 0, + tExpref: 0, + tColon: 0, + tPipe: 1, + tOr: 2, + tAnd: 3, + tEQ: 5, + tLT: 5, + tLTE: 5, + tGT: 5, + tGTE: 5, + tNE: 5, + tFlatten: 9, + tStar: 20, + tFilter: 21, + tDot: 40, + tNot: 45, + tLbrace: 50, + tLbracket: 55, + tLparen: 60, +} + +// Parser holds state about the current expression being parsed. +type Parser struct { + expression string + tokens []token + index int +} + +// NewParser creates a new JMESPath parser. +func NewParser() *Parser { + p := Parser{} + return &p +} + +// Parse will compile a JMESPath expression. +func (p *Parser) Parse(expression string) (ASTNode, error) { + lexer := NewLexer() + p.expression = expression + p.index = 0 + tokens, err := lexer.tokenize(expression) + if err != nil { + return ASTNode{}, err + } + p.tokens = tokens + parsed, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if p.current() != tEOF { + return ASTNode{}, p.syntaxError(fmt.Sprintf( + "Unexpected token at the end of the expresssion: %s", p.current())) + } + return parsed, nil +} + +func (p *Parser) parseExpression(bindingPower int) (ASTNode, error) { + var err error + leftToken := p.lookaheadToken(0) + p.advance() + leftNode, err := p.nud(leftToken) + if err != nil { + return ASTNode{}, err + } + currentToken := p.current() + for bindingPower < bindingPowers[currentToken] { + p.advance() + leftNode, err = p.led(currentToken, leftNode) + if err != nil { + return ASTNode{}, err + } + currentToken = p.current() + } + return leftNode, nil +} + +func (p *Parser) parseIndexExpression() (ASTNode, error) { + if p.lookahead(0) == tColon || p.lookahead(1) == tColon { + return p.parseSliceExpression() + } + indexStr := p.lookaheadToken(0).value + parsedInt, err := strconv.Atoi(indexStr) + if err != nil { + return ASTNode{}, err + } + indexNode := ASTNode{nodeType: ASTIndex, value: parsedInt} + p.advance() + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + return indexNode, nil +} + +func (p *Parser) parseSliceExpression() (ASTNode, error) { + parts := []*int{nil, nil, nil} + index := 0 + current := p.current() + for current != tRbracket && index < 3 { + if current == tColon { + index++ + p.advance() + } else if current == tNumber { + parsedInt, err := strconv.Atoi(p.lookaheadToken(0).value) + if err != nil { + return ASTNode{}, err + } + parts[index] = &parsedInt + p.advance() + } else { + return ASTNode{}, p.syntaxError( + "Expected tColon or tNumber" + ", received: " + p.current().String()) + } + current = p.current() + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTSlice, + value: parts, + }, nil +} + +func (p *Parser) match(tokenType tokType) error { + if p.current() == tokenType { + p.advance() + return nil + } + return p.syntaxError("Expected " + tokenType.String() + ", received: " + p.current().String()) +} + +func (p *Parser) led(tokenType tokType, node ASTNode) (ASTNode, error) { + switch tokenType { + case tDot: + if p.current() != tStar { + right, err := p.parseDotRHS(bindingPowers[tDot]) + return ASTNode{ + nodeType: ASTSubexpression, + children: []ASTNode{node, right}, + }, err + } + p.advance() + right, err := p.parseProjectionRHS(bindingPowers[tDot]) + return ASTNode{ + nodeType: ASTValueProjection, + children: []ASTNode{node, right}, + }, err + case tPipe: + right, err := p.parseExpression(bindingPowers[tPipe]) + return ASTNode{nodeType: ASTPipe, children: []ASTNode{node, right}}, err + case tOr: + right, err := p.parseExpression(bindingPowers[tOr]) + return ASTNode{nodeType: ASTOrExpression, children: []ASTNode{node, right}}, err + case tAnd: + right, err := p.parseExpression(bindingPowers[tAnd]) + return ASTNode{nodeType: ASTAndExpression, children: []ASTNode{node, right}}, err + case tLparen: + name := node.value + var args []ASTNode + for p.current() != tRparen { + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if p.current() == tComma { + if err := p.match(tComma); err != nil { + return ASTNode{}, err + } + } + args = append(args, expression) + } + if err := p.match(tRparen); err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTFunctionExpression, + value: name, + children: args, + }, nil + case tFilter: + return p.parseFilter(node) + case tFlatten: + left := ASTNode{nodeType: ASTFlatten, children: []ASTNode{node}} + right, err := p.parseProjectionRHS(bindingPowers[tFlatten]) + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{left, right}, + }, err + case tEQ, tNE, tGT, tGTE, tLT, tLTE: + right, err := p.parseExpression(bindingPowers[tokenType]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTComparator, + value: tokenType, + children: []ASTNode{node, right}, + }, nil + case tLbracket: + tokenType := p.current() + var right ASTNode + var err error + if tokenType == tNumber || tokenType == tColon { + right, err = p.parseIndexExpression() + if err != nil { + return ASTNode{}, err + } + return p.projectIfSlice(node, right) + } + // Otherwise this is a projection. + if err := p.match(tStar); err != nil { + return ASTNode{}, err + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + right, err = p.parseProjectionRHS(bindingPowers[tStar]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{node, right}, + }, nil + } + return ASTNode{}, p.syntaxError("Unexpected token: " + tokenType.String()) +} + +func (p *Parser) nud(token token) (ASTNode, error) { + switch token.tokenType { + case tJSONLiteral: + var parsed interface{} + err := json.Unmarshal([]byte(token.value), &parsed) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTLiteral, value: parsed}, nil + case tStringLiteral: + return ASTNode{nodeType: ASTLiteral, value: token.value}, nil + case tUnquotedIdentifier: + return ASTNode{ + nodeType: ASTField, + value: token.value, + }, nil + case tQuotedIdentifier: + node := ASTNode{nodeType: ASTField, value: token.value} + if p.current() == tLparen { + return ASTNode{}, p.syntaxErrorToken("Can't have quoted identifier as function name.", token) + } + return node, nil + case tStar: + left := ASTNode{nodeType: ASTIdentity} + var right ASTNode + var err error + if p.current() == tRbracket { + right = ASTNode{nodeType: ASTIdentity} + } else { + right, err = p.parseProjectionRHS(bindingPowers[tStar]) + } + return ASTNode{nodeType: ASTValueProjection, children: []ASTNode{left, right}}, err + case tFilter: + return p.parseFilter(ASTNode{nodeType: ASTIdentity}) + case tLbrace: + return p.parseMultiSelectHash() + case tFlatten: + left := ASTNode{ + nodeType: ASTFlatten, + children: []ASTNode{ASTNode{nodeType: ASTIdentity}}, + } + right, err := p.parseProjectionRHS(bindingPowers[tFlatten]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTProjection, children: []ASTNode{left, right}}, nil + case tLbracket: + tokenType := p.current() + //var right ASTNode + if tokenType == tNumber || tokenType == tColon { + right, err := p.parseIndexExpression() + if err != nil { + return ASTNode{}, nil + } + return p.projectIfSlice(ASTNode{nodeType: ASTIdentity}, right) + } else if tokenType == tStar && p.lookahead(1) == tRbracket { + p.advance() + p.advance() + right, err := p.parseProjectionRHS(bindingPowers[tStar]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{ASTNode{nodeType: ASTIdentity}, right}, + }, nil + } else { + return p.parseMultiSelectList() + } + case tCurrent: + return ASTNode{nodeType: ASTCurrentNode}, nil + case tExpref: + expression, err := p.parseExpression(bindingPowers[tExpref]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTExpRef, children: []ASTNode{expression}}, nil + case tNot: + expression, err := p.parseExpression(bindingPowers[tNot]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTNotExpression, children: []ASTNode{expression}}, nil + case tLparen: + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if err := p.match(tRparen); err != nil { + return ASTNode{}, err + } + return expression, nil + case tEOF: + return ASTNode{}, p.syntaxErrorToken("Incomplete expression", token) + } + + return ASTNode{}, p.syntaxErrorToken("Invalid token: "+token.tokenType.String(), token) +} + +func (p *Parser) parseMultiSelectList() (ASTNode, error) { + var expressions []ASTNode + for { + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + expressions = append(expressions, expression) + if p.current() == tRbracket { + break + } + err = p.match(tComma) + if err != nil { + return ASTNode{}, err + } + } + err := p.match(tRbracket) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTMultiSelectList, + children: expressions, + }, nil +} + +func (p *Parser) parseMultiSelectHash() (ASTNode, error) { + var children []ASTNode + for { + keyToken := p.lookaheadToken(0) + if err := p.match(tUnquotedIdentifier); err != nil { + if err := p.match(tQuotedIdentifier); err != nil { + return ASTNode{}, p.syntaxError("Expected tQuotedIdentifier or tUnquotedIdentifier") + } + } + keyName := keyToken.value + err := p.match(tColon) + if err != nil { + return ASTNode{}, err + } + value, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + node := ASTNode{ + nodeType: ASTKeyValPair, + value: keyName, + children: []ASTNode{value}, + } + children = append(children, node) + if p.current() == tComma { + err := p.match(tComma) + if err != nil { + return ASTNode{}, nil + } + } else if p.current() == tRbrace { + err := p.match(tRbrace) + if err != nil { + return ASTNode{}, nil + } + break + } + } + return ASTNode{ + nodeType: ASTMultiSelectHash, + children: children, + }, nil +} + +func (p *Parser) projectIfSlice(left ASTNode, right ASTNode) (ASTNode, error) { + indexExpr := ASTNode{ + nodeType: ASTIndexExpression, + children: []ASTNode{left, right}, + } + if right.nodeType == ASTSlice { + right, err := p.parseProjectionRHS(bindingPowers[tStar]) + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{indexExpr, right}, + }, err + } + return indexExpr, nil +} +func (p *Parser) parseFilter(node ASTNode) (ASTNode, error) { + var right, condition ASTNode + var err error + condition, err = p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + if p.current() == tFlatten { + right = ASTNode{nodeType: ASTIdentity} + } else { + right, err = p.parseProjectionRHS(bindingPowers[tFilter]) + if err != nil { + return ASTNode{}, err + } + } + + return ASTNode{ + nodeType: ASTFilterProjection, + children: []ASTNode{node, right, condition}, + }, nil +} + +func (p *Parser) parseDotRHS(bindingPower int) (ASTNode, error) { + lookahead := p.current() + if tokensOneOf([]tokType{tQuotedIdentifier, tUnquotedIdentifier, tStar}, lookahead) { + return p.parseExpression(bindingPower) + } else if lookahead == tLbracket { + if err := p.match(tLbracket); err != nil { + return ASTNode{}, err + } + return p.parseMultiSelectList() + } else if lookahead == tLbrace { + if err := p.match(tLbrace); err != nil { + return ASTNode{}, err + } + return p.parseMultiSelectHash() + } + return ASTNode{}, p.syntaxError("Expected identifier, lbracket, or lbrace") +} + +func (p *Parser) parseProjectionRHS(bindingPower int) (ASTNode, error) { + current := p.current() + if bindingPowers[current] < 10 { + return ASTNode{nodeType: ASTIdentity}, nil + } else if current == tLbracket { + return p.parseExpression(bindingPower) + } else if current == tFilter { + return p.parseExpression(bindingPower) + } else if current == tDot { + err := p.match(tDot) + if err != nil { + return ASTNode{}, err + } + return p.parseDotRHS(bindingPower) + } else { + return ASTNode{}, p.syntaxError("Error") + } +} + +func (p *Parser) lookahead(number int) tokType { + return p.lookaheadToken(number).tokenType +} + +func (p *Parser) current() tokType { + return p.lookahead(0) +} + +func (p *Parser) lookaheadToken(number int) token { + return p.tokens[p.index+number] +} + +func (p *Parser) advance() { + p.index++ +} + +func tokensOneOf(elements []tokType, token tokType) bool { + for _, elem := range elements { + if elem == token { + return true + } + } + return false +} + +func (p *Parser) syntaxError(msg string) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: p.expression, + Offset: p.lookaheadToken(0).position, + } +} + +// Create a SyntaxError based on the provided token. +// This differs from syntaxError() which creates a SyntaxError +// based on the current lookahead token. +func (p *Parser) syntaxErrorToken(msg string, t token) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: p.expression, + Offset: t.position, + } +} diff --git a/vendor/github.com/jmespath/go-jmespath/toktype_string.go b/vendor/github.com/jmespath/go-jmespath/toktype_string.go new file mode 100644 index 000000000..dae79cbdf --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/toktype_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type=tokType; DO NOT EDIT + +package jmespath + +import "fmt" + +const _tokType_name = "tUnknowntStartDottFiltertFlattentLparentRparentLbrackettRbrackettLbracetRbracetOrtPipetNumbertUnquotedIdentifiertQuotedIdentifiertCommatColontLTtLTEtGTtGTEtEQtNEtJSONLiteraltStringLiteraltCurrenttExpreftAndtNottEOF" + +var _tokType_index = [...]uint8{0, 8, 13, 17, 24, 32, 39, 46, 55, 64, 71, 78, 81, 86, 93, 112, 129, 135, 141, 144, 148, 151, 155, 158, 161, 173, 187, 195, 202, 206, 210, 214} + +func (i tokType) String() string { + if i < 0 || i >= tokType(len(_tokType_index)-1) { + return fmt.Sprintf("tokType(%d)", i) + } + return _tokType_name[_tokType_index[i]:_tokType_index[i+1]] +} diff --git a/vendor/github.com/jmespath/go-jmespath/util.go b/vendor/github.com/jmespath/go-jmespath/util.go new file mode 100644 index 000000000..ddc1b7d7d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/util.go @@ -0,0 +1,185 @@ +package jmespath + +import ( + "errors" + "reflect" +) + +// IsFalse determines if an object is false based on the JMESPath spec. +// JMESPath defines false values to be any of: +// - An empty string array, or hash. +// - The boolean value false. +// - nil +func isFalse(value interface{}) bool { + switch v := value.(type) { + case bool: + return !v + case []interface{}: + return len(v) == 0 + case map[string]interface{}: + return len(v) == 0 + case string: + return len(v) == 0 + case nil: + return true + } + // Try the reflection cases before returning false. + rv := reflect.ValueOf(value) + switch rv.Kind() { + case reflect.Struct: + // A struct type will never be false, even if + // all of its values are the zero type. + return false + case reflect.Slice, reflect.Map: + return rv.Len() == 0 + case reflect.Ptr: + if rv.IsNil() { + return true + } + // If it's a pointer type, we'll try to deref the pointer + // and evaluate the pointer value for isFalse. + element := rv.Elem() + return isFalse(element.Interface()) + } + return false +} + +// ObjsEqual is a generic object equality check. +// It will take two arbitrary objects and recursively determine +// if they are equal. +func objsEqual(left interface{}, right interface{}) bool { + return reflect.DeepEqual(left, right) +} + +// SliceParam refers to a single part of a slice. +// A slice consists of a start, a stop, and a step, similar to +// python slices. +type sliceParam struct { + N int + Specified bool +} + +// Slice supports [start:stop:step] style slicing that's supported in JMESPath. +func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) { + computed, err := computeSliceParams(len(slice), parts) + if err != nil { + return nil, err + } + start, stop, step := computed[0], computed[1], computed[2] + result := []interface{}{} + if step > 0 { + for i := start; i < stop; i += step { + result = append(result, slice[i]) + } + } else { + for i := start; i > stop; i += step { + result = append(result, slice[i]) + } + } + return result, nil +} + +func computeSliceParams(length int, parts []sliceParam) ([]int, error) { + var start, stop, step int + if !parts[2].Specified { + step = 1 + } else if parts[2].N == 0 { + return nil, errors.New("Invalid slice, step cannot be 0") + } else { + step = parts[2].N + } + var stepValueNegative bool + if step < 0 { + stepValueNegative = true + } else { + stepValueNegative = false + } + + if !parts[0].Specified { + if stepValueNegative { + start = length - 1 + } else { + start = 0 + } + } else { + start = capSlice(length, parts[0].N, step) + } + + if !parts[1].Specified { + if stepValueNegative { + stop = -1 + } else { + stop = length + } + } else { + stop = capSlice(length, parts[1].N, step) + } + return []int{start, stop, step}, nil +} + +func capSlice(length int, actual int, step int) int { + if actual < 0 { + actual += length + if actual < 0 { + if step < 0 { + actual = -1 + } else { + actual = 0 + } + } + } else if actual >= length { + if step < 0 { + actual = length - 1 + } else { + actual = length + } + } + return actual +} + +// ToArrayNum converts an empty interface type to a slice of float64. +// If any element in the array cannot be converted, then nil is returned +// along with a second value of false. +func toArrayNum(data interface{}) ([]float64, bool) { + // Is there a better way to do this with reflect? + if d, ok := data.([]interface{}); ok { + result := make([]float64, len(d)) + for i, el := range d { + item, ok := el.(float64) + if !ok { + return nil, false + } + result[i] = item + } + return result, true + } + return nil, false +} + +// ToArrayStr converts an empty interface type to a slice of strings. +// If any element in the array cannot be converted, then nil is returned +// along with a second value of false. If the input data could be entirely +// converted, then the converted data, along with a second value of true, +// will be returned. +func toArrayStr(data interface{}) ([]string, bool) { + // Is there a better way to do this with reflect? + if d, ok := data.([]interface{}); ok { + result := make([]string, len(d)) + for i, el := range d { + item, ok := el.(string) + if !ok { + return nil, false + } + result[i] = item + } + return result, true + } + return nil, false +} + +func isSliceType(v interface{}) bool { + if v == nil { + return false + } + return reflect.TypeOf(v).Kind() == reflect.Slice +} diff --git a/vendor/github.com/kardianos/osext/LICENSE b/vendor/github.com/kardianos/osext/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/kardianos/osext/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/kardianos/osext/README.md b/vendor/github.com/kardianos/osext/README.md new file mode 100644 index 000000000..61350baba --- /dev/null +++ b/vendor/github.com/kardianos/osext/README.md @@ -0,0 +1,16 @@ +### Extensions to the "os" package. + +## Find the current Executable and ExecutableFolder. + +There is sometimes utility in finding the current executable file +that is running. This can be used for upgrading the current executable +or finding resources located relative to the executable file. Both +working directory and the os.Args[0] value are arbitrary and cannot +be relied on; os.Args[0] can be "faked". + +Multi-platform and supports: + * Linux + * OS X + * Windows + * Plan 9 + * BSDs. diff --git a/vendor/github.com/kardianos/osext/osext.go b/vendor/github.com/kardianos/osext/osext.go new file mode 100644 index 000000000..c0de8b7f5 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext.go @@ -0,0 +1,33 @@ +// Copyright 2012 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. + +// Extensions to the standard "os" package. +package osext + +import "path/filepath" + +var cx, ce = executableClean() + +func executableClean() (string, error) { + p, err := executable() + return filepath.Clean(p), err +} + +// Executable returns an absolute path that can be used to +// re-invoke the current program. +// It may not be valid after the current program exits. +func Executable() (string, error) { + return cx, ce +} + +// Returns same path as Executable, returns just the folder +// path. Excludes the executable name and any trailing slash. +func ExecutableFolder() (string, error) { + p, err := Executable() + if err != nil { + return "", err + } + + return filepath.Dir(p), nil +} diff --git a/vendor/github.com/kardianos/osext/osext_plan9.go b/vendor/github.com/kardianos/osext/osext_plan9.go new file mode 100644 index 000000000..655750c54 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_plan9.go @@ -0,0 +1,20 @@ +// Copyright 2012 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. + +package osext + +import ( + "os" + "strconv" + "syscall" +) + +func executable() (string, error) { + f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text") + if err != nil { + return "", err + } + defer f.Close() + return syscall.Fd2path(int(f.Fd())) +} diff --git a/vendor/github.com/kardianos/osext/osext_procfs.go b/vendor/github.com/kardianos/osext/osext_procfs.go new file mode 100644 index 000000000..d59847ee5 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_procfs.go @@ -0,0 +1,36 @@ +// Copyright 2012 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. + +// +build linux netbsd solaris dragonfly + +package osext + +import ( + "errors" + "fmt" + "os" + "runtime" + "strings" +) + +func executable() (string, error) { + switch runtime.GOOS { + case "linux": + const deletedTag = " (deleted)" + execpath, err := os.Readlink("/proc/self/exe") + if err != nil { + return execpath, err + } + execpath = strings.TrimSuffix(execpath, deletedTag) + execpath = strings.TrimPrefix(execpath, deletedTag) + return execpath, nil + case "netbsd": + return os.Readlink("/proc/curproc/exe") + case "dragonfly": + return os.Readlink("/proc/curproc/file") + case "solaris": + return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid())) + } + return "", errors.New("ExecPath not implemented for " + runtime.GOOS) +} diff --git a/vendor/github.com/kardianos/osext/osext_sysctl.go b/vendor/github.com/kardianos/osext/osext_sysctl.go new file mode 100644 index 000000000..66da0bcf9 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_sysctl.go @@ -0,0 +1,126 @@ +// Copyright 2012 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. + +// +build darwin freebsd openbsd + +package osext + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "syscall" + "unsafe" +) + +var initCwd, initCwdErr = os.Getwd() + +func executable() (string, error) { + var mib [4]int32 + switch runtime.GOOS { + case "freebsd": + mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1} + case "darwin": + mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1} + case "openbsd": + mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */} + } + + n := uintptr(0) + // Get length. + _, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0) + if errNum != 0 { + return "", errNum + } + if n == 0 { // This shouldn't happen. + return "", nil + } + buf := make([]byte, n) + _, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0) + if errNum != 0 { + return "", errNum + } + if n == 0 { // This shouldn't happen. + return "", nil + } + + var execPath string + switch runtime.GOOS { + case "openbsd": + // buf now contains **argv, with pointers to each of the C-style + // NULL terminated arguments. + var args []string + argv := uintptr(unsafe.Pointer(&buf[0])) + Loop: + for { + argp := *(**[1 << 20]byte)(unsafe.Pointer(argv)) + if argp == nil { + break + } + for i := 0; uintptr(i) < n; i++ { + // we don't want the full arguments list + if string(argp[i]) == " " { + break Loop + } + if argp[i] != 0 { + continue + } + args = append(args, string(argp[:i])) + n -= uintptr(i) + break + } + if n < unsafe.Sizeof(argv) { + break + } + argv += unsafe.Sizeof(argv) + n -= unsafe.Sizeof(argv) + } + execPath = args[0] + // There is no canonical way to get an executable path on + // OpenBSD, so check PATH in case we are called directly + if execPath[0] != '/' && execPath[0] != '.' { + execIsInPath, err := exec.LookPath(execPath) + if err == nil { + execPath = execIsInPath + } + } + default: + for i, v := range buf { + if v == 0 { + buf = buf[:i] + break + } + } + execPath = string(buf) + } + + var err error + // execPath will not be empty due to above checks. + // Try to get the absolute path if the execPath is not rooted. + if execPath[0] != '/' { + execPath, err = getAbs(execPath) + if err != nil { + return execPath, err + } + } + // For darwin KERN_PROCARGS may return the path to a symlink rather than the + // actual executable. + if runtime.GOOS == "darwin" { + if execPath, err = filepath.EvalSymlinks(execPath); err != nil { + return execPath, err + } + } + return execPath, nil +} + +func getAbs(execPath string) (string, error) { + if initCwdErr != nil { + return execPath, initCwdErr + } + // The execPath may begin with a "../" or a "./" so clean it first. + // Join the two paths, trailing and starting slashes undetermined, so use + // the generic Join function. + return filepath.Join(initCwd, filepath.Clean(execPath)), nil +} diff --git a/vendor/github.com/kardianos/osext/osext_windows.go b/vendor/github.com/kardianos/osext/osext_windows.go new file mode 100644 index 000000000..72d282cf8 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_windows.go @@ -0,0 +1,34 @@ +// Copyright 2012 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. + +package osext + +import ( + "syscall" + "unicode/utf16" + "unsafe" +) + +var ( + kernel = syscall.MustLoadDLL("kernel32.dll") + getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW") +) + +// GetModuleFileName() with hModule = NULL +func executable() (exePath string, err error) { + return getModuleFileName() +} + +func getModuleFileName() (string, error) { + var n uint32 + b := make([]uint16, syscall.MAX_PATH) + size := uint32(len(b)) + + r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size)) + n = uint32(r0) + if n == 0 { + return "", e1 + } + return string(utf16.Decode(b[0:n])), nil +} diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/klauspost/compress/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/compress/flate/copy.go b/vendor/github.com/klauspost/compress/flate/copy.go new file mode 100644 index 000000000..a3200a8f4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/copy.go @@ -0,0 +1,32 @@ +// Copyright 2012 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. + +package flate + +// forwardCopy is like the built-in copy function except that it always goes +// forward from the start, even if the dst and src overlap. +// It is equivalent to: +// for i := 0; i < n; i++ { +// mem[dst+i] = mem[src+i] +// } +func forwardCopy(mem []byte, dst, src, n int) { + if dst <= src { + copy(mem[dst:dst+n], mem[src:src+n]) + return + } + for { + if dst >= src+n { + copy(mem[dst:dst+n], mem[src:src+n]) + return + } + // There is some forward overlap. The destination + // will be filled with a repeated pattern of mem[src:src+k]. + // We copy one instance of the pattern here, then repeat. + // Each time around this loop k will double. + k := dst - src + copy(mem[dst:dst+k], mem[src:src+k]) + n -= k + dst += k + } +} diff --git a/vendor/github.com/klauspost/compress/flate/crc32_amd64.go b/vendor/github.com/klauspost/compress/flate/crc32_amd64.go new file mode 100644 index 000000000..45d52f629 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/crc32_amd64.go @@ -0,0 +1,39 @@ +//+build !noasm +//+build !appengine + +// Copyright 2015, Klaus Post, see LICENSE for details. + +package flate + +import ( + "github.com/klauspost/cpuid" +) + +// crc32sse returns a hash for the first 4 bytes of the slice +// len(a) must be >= 4. +//go:noescape +func crc32sse(a []byte) hash + +// crc32sseAll calculates hashes for each 4-byte set in a. +// dst must be east len(a) - 4 in size. +// The size is not checked by the assembly. +//go:noescape +func crc32sseAll(a []byte, dst []hash) + +// matchLenSSE4 returns the number of matching bytes in a and b +// up to length 'max'. Both slices must be at least 'max' +// bytes in size. +// It uses the PCMPESTRI SSE 4.2 instruction. +//go:noescape +func matchLenSSE4(a, b []byte, max int) int + +// histogram accumulates a histogram of b in h. +// h must be at least 256 entries in length, +// and must be cleared before calling this function. +//go:noescape +func histogram(b []byte, h []int32) + +// Detect SSE 4.2 feature. +func init() { + useSSE42 = cpuid.CPU.SSE42() +} diff --git a/vendor/github.com/klauspost/compress/flate/crc32_amd64.s b/vendor/github.com/klauspost/compress/flate/crc32_amd64.s new file mode 100644 index 000000000..f94969b76 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/crc32_amd64.s @@ -0,0 +1,212 @@ +//+build !noasm !appengine + +// Copyright 2015, Klaus Post, see LICENSE for details. + +// func crc32sse(a []byte) hash +TEXT ·crc32sse(SB), 7, $0 + MOVQ a+0(FP), R10 + XORQ BX, BX + + // CRC32 dword (R10), EBX + BYTE $0xF2; BYTE $0x41; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0x1a + + MOVL BX, ret+24(FP) + RET + +// func crc32sseAll(a []byte, dst []hash) +TEXT ·crc32sseAll(SB), 7, $0 + MOVQ a+0(FP), R8 // R8: src + MOVQ a_len+8(FP), R10 // input length + MOVQ dst+24(FP), R9 // R9: dst + SUBQ $4, R10 + JS end + JZ one_crc + MOVQ R10, R13 + SHRQ $2, R10 // len/4 + ANDQ $3, R13 // len&3 + XORQ BX, BX + ADDQ $1, R13 + TESTQ R10, R10 + JZ rem_loop + +crc_loop: + MOVQ (R8), R11 + XORQ BX, BX + XORQ DX, DX + XORQ DI, DI + MOVQ R11, R12 + SHRQ $8, R11 + MOVQ R12, AX + MOVQ R11, CX + SHRQ $16, R12 + SHRQ $16, R11 + MOVQ R12, SI + + // CRC32 EAX, EBX + BYTE $0xF2; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0xd8 + + // CRC32 ECX, EDX + BYTE $0xF2; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0xd1 + + // CRC32 ESI, EDI + BYTE $0xF2; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0xfe + MOVL BX, (R9) + MOVL DX, 4(R9) + MOVL DI, 8(R9) + + XORQ BX, BX + MOVL R11, AX + + // CRC32 EAX, EBX + BYTE $0xF2; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0xd8 + MOVL BX, 12(R9) + + ADDQ $16, R9 + ADDQ $4, R8 + XORQ BX, BX + SUBQ $1, R10 + JNZ crc_loop + +rem_loop: + MOVL (R8), AX + + // CRC32 EAX, EBX + BYTE $0xF2; BYTE $0x0f + BYTE $0x38; BYTE $0xf1; BYTE $0xd8 + + MOVL BX, (R9) + ADDQ $4, R9 + ADDQ $1, R8 + XORQ BX, BX + SUBQ $1, R13 + JNZ rem_loop + +end: + RET + +one_crc: + MOVQ $1, R13 + XORQ BX, BX + JMP rem_loop + +// func matchLenSSE4(a, b []byte, max int) int +TEXT ·matchLenSSE4(SB), 7, $0 + MOVQ a+0(FP), R8 // R8: &a + MOVQ b+24(FP), R9 // R9: &b + MOVQ max+48(FP), R10 // R10: max + XORQ R11, R11 // match length + + MOVQ R10, R12 + SHRQ $4, R10 // max/16 + ANDQ $15, R12 // max & 15 + CMPQ R10, $0 + JEQ matchlen_verysmall + +loopback_matchlen: + MOVOU (R8), X0 // a[x] + MOVOU (R9), X1 // b[x] + + // PCMPESTRI $0x18, X1, X0 + BYTE $0x66; BYTE $0x0f; BYTE $0x3a + BYTE $0x61; BYTE $0xc1; BYTE $0x18 + + JC match_ended + + ADDQ $16, R8 + ADDQ $16, R9 + ADDQ $16, R11 + + SUBQ $1, R10 + JNZ loopback_matchlen + +matchlen_verysmall: + CMPQ R12, $0 + JEQ done_matchlen + +loopback_matchlen_single: + // Naiive, but small use + MOVB (R8), R13 + MOVB (R9), R14 + CMPB R13, R14 + JNE done_matchlen + ADDQ $1, R8 + ADDQ $1, R9 + ADDQ $1, R11 + SUBQ $1, R12 + JNZ loopback_matchlen_single + MOVQ R11, ret+56(FP) + RET + +match_ended: + ADDQ CX, R11 + +done_matchlen: + MOVQ R11, ret+56(FP) + RET + +// func histogram(b []byte, h []int32) +TEXT ·histogram(SB), 7, $0 + MOVQ b+0(FP), SI // SI: &b + MOVQ b_len+8(FP), R9 // R9: len(b) + MOVQ h+24(FP), DI // DI: Histogram + MOVQ R9, R8 + SHRQ $3, R8 + JZ hist1 + XORQ R11, R11 + +loop_hist8: + MOVQ (SI), R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + MOVB R10, R11 + INCL (DI)(R11*4) + SHRQ $8, R10 + + INCL (DI)(R10*4) + + ADDQ $8, SI + DECQ R8 + JNZ loop_hist8 + +hist1: + ANDQ $7, R9 + JZ end_hist + XORQ R10, R10 + +loop_hist1: + MOVB (SI), R10 + INCL (DI)(R10*4) + INCQ SI + DECQ R9 + JNZ loop_hist1 + +end_hist: + RET diff --git a/vendor/github.com/klauspost/compress/flate/crc32_noasm.go b/vendor/github.com/klauspost/compress/flate/crc32_noasm.go new file mode 100644 index 000000000..1c6d23eed --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/crc32_noasm.go @@ -0,0 +1,34 @@ +//+build !amd64 noasm appengine + +// Copyright 2015, Klaus Post, see LICENSE for details. + +package flate + +func init() { + useSSE42 = false +} + +// crc32sse should never be called. +func crc32sse(a []byte) hash { + panic("no assembler") +} + +// crc32sseAll should never be called. +func crc32sseAll(a []byte, dst []hash) { + panic("no assembler") +} + +// matchLenSSE4 should never be called. +func matchLenSSE4(a, b []byte, max int) int { + panic("no assembler") + return 0 +} + +// histogram accumulates a histogram of b in h. +// h must be at least 256 entries in length, +// and must be cleared before calling this function. +func histogram(b []byte, h []int32) { + for _, t := range b { + h[t]++ + } +} diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go new file mode 100644 index 000000000..19c3df637 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/deflate.go @@ -0,0 +1,1327 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Copyright (c) 2015 Klaus Post +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "fmt" + "io" + "math" +) + +const ( + NoCompression = 0 + BestSpeed = 1 + fastCompression = 3 + BestCompression = 9 + DefaultCompression = -1 + ConstantCompression = -2 // Does only Huffman encoding + logWindowSize = 15 + windowSize = 1 << logWindowSize + windowMask = windowSize - 1 + logMaxOffsetSize = 15 // Standard DEFLATE + minMatchLength = 4 // The smallest match that the compressor looks for + maxMatchLength = 258 // The longest match for the compressor + minOffsetSize = 1 // The shortest offset that makes any sense + + // The maximum number of tokens we put into a single flat block, just too + // stop things from getting too large. + maxFlateBlockTokens = 1 << 14 + maxStoreBlockSize = 65535 + hashBits = 17 // After 17 performance degrades + hashSize = 1 << hashBits + hashMask = (1 << hashBits) - 1 + hashShift = (hashBits + minMatchLength - 1) / minMatchLength + maxHashOffset = 1 << 24 + + skipNever = math.MaxInt32 +) + +var useSSE42 bool + +type compressionLevel struct { + good, lazy, nice, chain, fastSkipHashing, level int +} + +var levels = []compressionLevel{ + {}, // 0 + // For levels 1-3 we don't bother trying with lazy matches + {4, 0, 8, 4, 4, 1}, + {4, 0, 16, 8, 5, 2}, + {4, 0, 24, 24, 6, 3}, + // Levels 4-9 use increasingly more lazy matching + // and increasingly stringent conditions for "good enough". + {4, 4, 16, 16, skipNever, 4}, + {8, 16, 32, 32, skipNever, 5}, + {8, 16, 128, 128, skipNever, 6}, + {8, 32, 128, 256, skipNever, 7}, + {32, 128, 258, 1024, skipNever, 8}, + {32, 258, 258, 4096, skipNever, 9}, +} + +type hashid uint32 + +type compressor struct { + compressionLevel + + w *huffmanBitWriter + bulkHasher func([]byte, []hash) + + // compression algorithm + fill func(*compressor, []byte) int // copy data to window + step func(*compressor) // process window + sync bool // requesting flush + + // Input hash chains + // hashHead[hashValue] contains the largest inputIndex with the specified hash value + // If hashHead[hashValue] is within the current window, then + // hashPrev[hashHead[hashValue] & windowMask] contains the previous index + // with the same hash value. + chainHead int + hashHead []hashid + hashPrev []hashid + hashOffset int + + // input window: unprocessed data is window[index:windowEnd] + index int + window []byte + windowEnd int + blockStart int // window index where current tokens start + byteAvailable bool // if true, still need to process window[index-1]. + + // queued output tokens + tokens tokens + + // deflate state + length int + offset int + hash hash + maxInsertIndex int + err error + ii uint16 // position of last match, intended to overflow to reset. + + hashMatch [maxMatchLength + minMatchLength]hash +} + +type hash int32 + +func (d *compressor) fillDeflate(b []byte) int { + if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) { + // shift the window by windowSize + copy(d.window, d.window[windowSize:2*windowSize]) + d.index -= windowSize + d.windowEnd -= windowSize + if d.blockStart >= windowSize { + d.blockStart -= windowSize + } else { + d.blockStart = math.MaxInt32 + } + d.hashOffset += windowSize + if d.hashOffset > maxHashOffset { + delta := d.hashOffset - 1 + d.hashOffset -= delta + d.chainHead -= delta + for i, v := range d.hashPrev { + if int(v) > delta { + d.hashPrev[i] = hashid(int(v) - delta) + } else { + d.hashPrev[i] = 0 + } + } + for i, v := range d.hashHead { + if int(v) > delta { + d.hashHead[i] = hashid(int(v) - delta) + } else { + d.hashHead[i] = 0 + } + } + } + } + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +func (d *compressor) writeBlock(tok tokens, index int, eof bool) error { + if index > 0 || eof { + var window []byte + if d.blockStart <= index { + window = d.window[d.blockStart:index] + } + d.blockStart = index + d.w.writeBlock(tok, eof, window) + return d.w.err + } + return nil +} + +// writeBlockSkip writes the current block and uses the number of tokens +// to determine if the block should be stored on no matches, or +// only huffman encoded. +func (d *compressor) writeBlockSkip(tok tokens, index int, eof bool) error { + if index > 0 || eof { + if d.blockStart <= index { + window := d.window[d.blockStart:index] + if tok.n == len(window) && !eof { + d.writeStoredBlock(window) + // If we removed less than 10 literals, huffman compress the block. + } else if tok.n > len(window)-10 { + d.w.writeBlockHuff(eof, window) + } else { + // Write a dynamic huffman block. + d.w.writeBlockDynamic(tok, eof, window) + } + } else { + d.w.writeBlock(tok, eof, nil) + } + d.blockStart = index + return d.w.err + } + return nil +} + +// fillWindow will fill the current window with the supplied +// dictionary and calculate all hashes. +// This is much faster than doing a full encode. +// Should only be used after a start/reset. +func (d *compressor) fillWindow(b []byte) { + // Do not fill window if we are in store-only mode, + // use constant or Snappy compression. + if d.compressionLevel.level == 0 { + return + } + // If we are given too much, cut it. + if len(b) > windowSize { + b = b[len(b)-windowSize:] + } + // Add all to window. + n := copy(d.window[d.windowEnd:], b) + + // Calculate 256 hashes at the time (more L1 cache hits) + loops := (n + 256 - minMatchLength) / 256 + for j := 0; j < loops; j++ { + startindex := j * 256 + end := startindex + 256 + minMatchLength - 1 + if end > n { + end = n + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + + if dstSize <= 0 { + continue + } + + dst := d.hashMatch[:dstSize] + d.bulkHasher(tocheck, dst) + var newH hash + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + d.hashPrev[di&windowMask] = d.hashHead[newH] + // Set the head of the hash chain to us. + d.hashHead[newH] = hashid(di + d.hashOffset) + } + d.hash = newH + } + // Update window information. + d.windowEnd += n + d.index = n +} + +// Try to find a match starting at index whose length is greater than prevSize. +// We only look at chainCount possibilities before giving up. +// pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead +func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) { + minMatchLook := maxMatchLength + if lookahead < minMatchLook { + minMatchLook = lookahead + } + + win := d.window[0 : pos+minMatchLook] + + // We quit when we get a match that's at least nice long + nice := len(win) - pos + if d.nice < nice { + nice = d.nice + } + + // If we've got a match that's good enough, only look in 1/4 the chain. + tries := d.chain + length = prevLength + if length >= d.good { + tries >>= 2 + } + + wEnd := win[pos+length] + wPos := win[pos:] + minIndex := pos - windowSize + + for i := prevHead; tries > 0; tries-- { + if wEnd == win[i+length] { + n := matchLen(win[i:], wPos, minMatchLook) + + if n > length && (n > minMatchLength || pos-i <= 4096) { + length = n + offset = pos - i + ok = true + if n >= nice { + // The match is good enough that we don't try to find a better one. + break + } + wEnd = win[pos+n] + } + } + if i == minIndex { + // hashPrev[i & windowMask] has already been overwritten, so stop now. + break + } + i = int(d.hashPrev[i&windowMask]) - d.hashOffset + if i < minIndex || i < 0 { + break + } + } + return +} + +// Try to find a match starting at index whose length is greater than prevSize. +// We only look at chainCount possibilities before giving up. +// pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead +func (d *compressor) findMatchSSE(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) { + minMatchLook := maxMatchLength + if lookahead < minMatchLook { + minMatchLook = lookahead + } + + win := d.window[0 : pos+minMatchLook] + + // We quit when we get a match that's at least nice long + nice := len(win) - pos + if d.nice < nice { + nice = d.nice + } + + // If we've got a match that's good enough, only look in 1/4 the chain. + tries := d.chain + length = prevLength + if length >= d.good { + tries >>= 2 + } + + wEnd := win[pos+length] + wPos := win[pos:] + minIndex := pos - windowSize + + for i := prevHead; tries > 0; tries-- { + if wEnd == win[i+length] { + n := matchLenSSE4(win[i:], wPos, minMatchLook) + + if n > length && (n > minMatchLength || pos-i <= 4096) { + length = n + offset = pos - i + ok = true + if n >= nice { + // The match is good enough that we don't try to find a better one. + break + } + wEnd = win[pos+n] + } + } + if i == minIndex { + // hashPrev[i & windowMask] has already been overwritten, so stop now. + break + } + i = int(d.hashPrev[i&windowMask]) - d.hashOffset + if i < minIndex || i < 0 { + break + } + } + return +} + +func (d *compressor) writeStoredBlock(buf []byte) error { + if d.w.writeStoredHeader(len(buf), false); d.w.err != nil { + return d.w.err + } + d.w.writeBytes(buf) + return d.w.err +} + +// oldHash is the hash function used when no native crc32 calculation +// or similar is present. +func oldHash(b []byte) hash { + return hash(b[0])<<(hashShift*3) + hash(b[1])<<(hashShift*2) + hash(b[2])< d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - d.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + if d.tokens.n > 0 { + if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + return + } + } + if d.index < d.maxInsertIndex { + // Update the hash + d.hash = oldHash(d.window[d.index:d.index+minMatchLength]) & hashMask + ch := d.hashHead[d.hash] + d.chainHead = int(ch) + d.hashPrev[d.index&windowMask] = ch + d.hashHead[d.hash] = hashid(d.index + d.hashOffset) + } + d.length = minMatchLength - 1 + d.offset = 0 + minIndex := d.index - windowSize + if minIndex < 0 { + minIndex = 0 + } + + if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 { + if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok { + d.length = newLength + d.offset = newOffset + } + } + if d.length >= minMatchLength { + d.ii = 0 + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3 + d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize)) + d.tokens.n++ + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + if d.length <= d.fastSkipHashing { + var newIndex int + newIndex = d.index + d.length + // Calculate missing hashes + end := newIndex + if end > d.maxInsertIndex { + end = d.maxInsertIndex + } + end += minMatchLength - 1 + startindex := d.index + 1 + if startindex > d.maxInsertIndex { + startindex = d.maxInsertIndex + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := d.hashMatch[:dstSize] + oldBulkHash(tocheck, dst) + var newH hash + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + d.hashPrev[di&windowMask] = d.hashHead[newH] + // Set the head of the hash chain to us. + d.hashHead[newH] = hashid(di + d.hashOffset) + } + d.hash = newH + } + d.index = newIndex + } else { + // For matches this long, we don't bother inserting each individual + // item into the table. + d.index += d.length + if d.index < d.maxInsertIndex { + d.hash = oldHash(d.window[d.index:d.index+minMatchLength]) & hashMask + } + } + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } else { + d.ii++ + end := d.index + int(d.ii>>uint(d.fastSkipHashing)) + 1 + if end > d.windowEnd { + end = d.windowEnd + } + for i := d.index; i < end; i++ { + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlockSkip(d.tokens, i+1, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } + d.index = end + } + } +} + +// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever, +// meaning it always has lazy matching on. +func (d *compressor) deflateLazy() { + // Sanity enables additional runtime tests. + // It's intended to be used during development + // to supplement the currently ad-hoc unit tests. + const sanity = false + + if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync { + return + } + + d.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + if d.index < d.maxInsertIndex { + d.hash = oldHash(d.window[d.index:d.index+minMatchLength]) & hashMask + } + + for { + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - d.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + // Flush current output block if any. + if d.byteAvailable { + // There is still one pending token that needs to be flushed + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + d.byteAvailable = false + } + if d.tokens.n > 0 { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + return + } + } + if d.index < d.maxInsertIndex { + // Update the hash + d.hash = oldHash(d.window[d.index:d.index+minMatchLength]) & hashMask + ch := d.hashHead[d.hash] + d.chainHead = int(ch) + d.hashPrev[d.index&windowMask] = ch + d.hashHead[d.hash] = hashid(d.index + d.hashOffset) + } + prevLength := d.length + prevOffset := d.offset + d.length = minMatchLength - 1 + d.offset = 0 + minIndex := d.index - windowSize + if minIndex < 0 { + minIndex = 0 + } + + if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy { + if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok { + d.length = newLength + d.offset = newOffset + } + } + if prevLength >= minMatchLength && d.length <= prevLength { + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize)) + d.tokens.n++ + + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + var newIndex int + newIndex = d.index + prevLength - 1 + // Calculate missing hashes + end := newIndex + if end > d.maxInsertIndex { + end = d.maxInsertIndex + } + end += minMatchLength - 1 + startindex := d.index + 1 + if startindex > d.maxInsertIndex { + startindex = d.maxInsertIndex + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := d.hashMatch[:dstSize] + oldBulkHash(tocheck, dst) + var newH hash + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + d.hashPrev[di&windowMask] = d.hashHead[newH] + // Set the head of the hash chain to us. + d.hashHead[newH] = hashid(di + d.hashOffset) + } + d.hash = newH + } + + d.index = newIndex + d.byteAvailable = false + d.length = minMatchLength - 1 + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } else { + // Reset, if we got a match this run. + if d.length >= minMatchLength { + d.ii = 0 + } + // We have a byte waiting. Emit it. + if d.byteAvailable { + d.ii++ + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + d.index++ + + // If we have a long run of no matches, skip additional bytes + // Resets when d.ii overflows after 64KB. + if d.ii > 31 { + n := int(d.ii >> 6) + for j := 0; j < n; j++ { + if d.index >= d.windowEnd-1 { + break + } + + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + d.index++ + } + // Flush last byte + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + d.byteAvailable = false + // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } + } else { + d.index++ + d.byteAvailable = true + } + } + } +} + +// Assumes that d.fastSkipHashing != skipNever, +// otherwise use deflateLazySSE +func (d *compressor) deflateSSE() { + + // Sanity enables additional runtime tests. + // It's intended to be used during development + // to supplement the currently ad-hoc unit tests. + const sanity = false + + if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync { + return + } + + d.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + if d.index < d.maxInsertIndex { + d.hash = oldHash(d.window[d.index:d.index+minMatchLength]) & hashMask + } + + for { + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - d.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + if d.tokens.n > 0 { + if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + return + } + } + if d.index < d.maxInsertIndex { + // Update the hash + d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask + ch := d.hashHead[d.hash] + d.chainHead = int(ch) + d.hashPrev[d.index&windowMask] = ch + d.hashHead[d.hash] = hashid(d.index + d.hashOffset) + } + d.length = minMatchLength - 1 + d.offset = 0 + minIndex := d.index - windowSize + if minIndex < 0 { + minIndex = 0 + } + + if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 { + if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok { + d.length = newLength + d.offset = newOffset + } + } + if d.length >= minMatchLength { + d.ii = 0 + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3 + d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize)) + d.tokens.n++ + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + if d.length <= d.fastSkipHashing { + var newIndex int + newIndex = d.index + d.length + // Calculate missing hashes + end := newIndex + if end > d.maxInsertIndex { + end = d.maxInsertIndex + } + end += minMatchLength - 1 + startindex := d.index + 1 + if startindex > d.maxInsertIndex { + startindex = d.maxInsertIndex + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := d.hashMatch[:dstSize] + + crc32sseAll(tocheck, dst) + var newH hash + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + d.hashPrev[di&windowMask] = d.hashHead[newH] + // Set the head of the hash chain to us. + d.hashHead[newH] = hashid(di + d.hashOffset) + } + d.hash = newH + } + d.index = newIndex + } else { + // For matches this long, we don't bother inserting each individual + // item into the table. + d.index += d.length + if d.index < d.maxInsertIndex { + d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask + } + } + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } else { + d.ii++ + end := d.index + int(d.ii>>uint(d.fastSkipHashing)) + 1 + if end > d.windowEnd { + end = d.windowEnd + } + for i := d.index; i < end; i++ { + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlockSkip(d.tokens, i+1, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } + d.index = end + } + } +} + +// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever, +// meaning it always has lazy matching on. +func (d *compressor) deflateLazySSE() { + // Sanity enables additional runtime tests. + // It's intended to be used during development + // to supplement the currently ad-hoc unit tests. + const sanity = false + + if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync { + return + } + + d.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + if d.index < d.maxInsertIndex { + d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask + } + + for { + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - d.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && d.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + // Flush current output block if any. + if d.byteAvailable { + // There is still one pending token that needs to be flushed + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + d.byteAvailable = false + } + if d.tokens.n > 0 { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + return + } + } + if d.index < d.maxInsertIndex { + // Update the hash + d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask + ch := d.hashHead[d.hash] + d.chainHead = int(ch) + d.hashPrev[d.index&windowMask] = ch + d.hashHead[d.hash] = hashid(d.index + d.hashOffset) + } + prevLength := d.length + prevOffset := d.offset + d.length = minMatchLength - 1 + d.offset = 0 + minIndex := d.index - windowSize + if minIndex < 0 { + minIndex = 0 + } + + if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy { + if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok { + d.length = newLength + d.offset = newOffset + } + } + if prevLength >= minMatchLength && d.length <= prevLength { + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize)) + d.tokens.n++ + + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + var newIndex int + newIndex = d.index + prevLength - 1 + // Calculate missing hashes + end := newIndex + if end > d.maxInsertIndex { + end = d.maxInsertIndex + } + end += minMatchLength - 1 + startindex := d.index + 1 + if startindex > d.maxInsertIndex { + startindex = d.maxInsertIndex + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := d.hashMatch[:dstSize] + crc32sseAll(tocheck, dst) + var newH hash + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + d.hashPrev[di&windowMask] = d.hashHead[newH] + // Set the head of the hash chain to us. + d.hashHead[newH] = hashid(di + d.hashOffset) + } + d.hash = newH + } + + d.index = newIndex + d.byteAvailable = false + d.length = minMatchLength - 1 + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } else { + // Reset, if we got a match this run. + if d.length >= minMatchLength { + d.ii = 0 + } + // We have a byte waiting. Emit it. + if d.byteAvailable { + d.ii++ + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + d.index++ + + // If we have a long run of no matches, skip additional bytes + // Resets when d.ii overflows after 64KB. + if d.ii > 31 { + n := int(d.ii >> 6) + for j := 0; j < n; j++ { + if d.index >= d.windowEnd-1 { + break + } + + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + d.index++ + } + // Flush last byte + d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1])) + d.tokens.n++ + d.byteAvailable = false + // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { + return + } + d.tokens.n = 0 + } + } + } else { + d.index++ + d.byteAvailable = true + } + } + } +} + +func (d *compressor) fillStore(b []byte) int { + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +func (d *compressor) store() { + if d.windowEnd > 0 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + } + d.windowEnd = 0 +} + +// fillHuff will fill the buffer with data for huffman-only compression. +// The number of bytes copied is returned. +func (d *compressor) fillHuff(b []byte) int { + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +// storeHuff will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeHuff() { + // We only compress if we have maxStoreBlockSize or we are at end-of-stream + if d.windowEnd < maxStoreBlockSize && !d.sync { + return + } + if d.windowEnd == 0 { + return + } + d.w.writeBlockHuff(false, d.window[:d.windowEnd]) + d.err = d.w.err + d.windowEnd = 0 +} + +// storeHuff will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeSnappy() { + // We only compress if we have maxStoreBlockSize. + if d.windowEnd < maxStoreBlockSize && !d.sync { + return + } + if d.windowEnd == 0 { + return + } + snappyEncode(&d.tokens, d.window[:d.windowEnd]) + // If we made zero matches, store the block as is. + if d.tokens.n == d.windowEnd { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + // If we removed less than 10 literals, huffman compress the block. + } else if d.tokens.n > d.windowEnd-10 { + d.w.writeBlockHuff(false, d.window[:d.windowEnd]) + d.err = d.w.err + } else { + d.w.writeBlockDynamic(d.tokens, false, d.window[:d.windowEnd]) + d.err = d.w.err + } + d.tokens.n = 0 + d.windowEnd = 0 +} + +// write will add input byte to the stream. +// Unless an error occurs all bytes will be consumed. +func (d *compressor) write(b []byte) (n int, err error) { + if d.err != nil { + return 0, d.err + } + n = len(b) + for len(b) > 0 { + d.step(d) + b = b[d.fill(d, b):] + if d.err != nil { + return 0, d.err + } + } + return n, d.err +} + +func (d *compressor) syncFlush() error { + d.sync = true + if d.err != nil { + return d.err + } + d.step(d) + if d.err == nil { + d.w.writeStoredHeader(0, false) + d.w.flush() + d.err = d.w.err + } + d.sync = false + return d.err +} + +func (d *compressor) init(w io.Writer, level int) (err error) { + d.w = newHuffmanBitWriter(w) + + switch { + case level == NoCompression: + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillStore + d.step = (*compressor).store + case level == ConstantCompression: + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillHuff + d.step = (*compressor).storeHuff + case level == 1: + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillHuff + d.step = (*compressor).storeSnappy + d.tokens.tokens = make([]token, maxStoreBlockSize+1) + case level == DefaultCompression: + level = 6 + fallthrough + case 2 <= level && level <= 9: + d.compressionLevel = levels[level] + d.initDeflate() + d.fill = (*compressor).fillDeflate + if d.fastSkipHashing == skipNever { + if useSSE42 { + d.step = (*compressor).deflateLazySSE + } else { + d.step = (*compressor).deflateLazy + } + } else { + if useSSE42 { + d.step = (*compressor).deflateSSE + } else { + d.step = (*compressor).deflate + + } + } + default: + return fmt.Errorf("flate: invalid compression level %d: want value in range [-2, 9]", level) + } + return nil +} + +// Used for zeroing the hash slice +var hzeroes [256]hashid + +// reset the state of the compressor. +func (d *compressor) reset(w io.Writer) { + d.w.reset(w) + d.sync = false + d.err = nil + switch d.compressionLevel.chain { + case 0: + // level was NoCompression or ConstantCompresssion. + d.windowEnd = 0 + default: + d.chainHead = -1 + for s := d.hashHead; len(s) > 0; { + n := copy(s, hzeroes[:]) + s = s[n:] + } + for s := d.hashPrev; len(s) > 0; s = s[len(hzeroes):] { + copy(s, hzeroes[:]) + } + d.hashOffset = 1 + + d.index, d.windowEnd = 0, 0 + d.blockStart, d.byteAvailable = 0, false + + d.tokens.n = 0 + d.length = minMatchLength - 1 + d.offset = 0 + d.hash = 0 + d.ii = 0 + d.maxInsertIndex = 0 + } +} + +func (d *compressor) close() error { + if d.err != nil { + return d.err + } + d.sync = true + d.step(d) + if d.err != nil { + return d.err + } + if d.w.writeStoredHeader(0, true); d.w.err != nil { + return d.w.err + } + d.w.flush() + return d.w.err +} + +// NewWriter returns a new Writer compressing data at the given level. +// Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression); +// higher levels typically run slower but compress more. Level 0 +// (NoCompression) does not attempt any compression; it only adds the +// necessary DEFLATE framing. Level -1 (DefaultCompression) uses the default +// compression level. +// Level -2 (ConstantCompression) will use Huffman compression only, giving +// a very fast compression for all types of input, but sacrificing considerable +// compression efficiency. +// +// If level is in the range [-2, 9] then the error returned will be nil. +// Otherwise the error returned will be non-nil. +func NewWriter(w io.Writer, level int) (*Writer, error) { + var dw Writer + if err := dw.d.init(w, level); err != nil { + return nil, err + } + return &dw, nil +} + +// NewWriterDict is like NewWriter but initializes the new +// Writer with a preset dictionary. The returned Writer behaves +// as if the dictionary had been written to it without producing +// any compressed output. The compressed data written to w +// can only be decompressed by a Reader initialized with the +// same dictionary. +func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) { + dw := &dictWriter{w} + zw, err := NewWriter(dw, level) + if err != nil { + return nil, err + } + zw.d.fillWindow(dict) + zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method. + return zw, err +} + +type dictWriter struct { + w io.Writer +} + +func (w *dictWriter) Write(b []byte) (n int, err error) { + return w.w.Write(b) +} + +// A Writer takes data written to it and writes the compressed +// form of that data to an underlying writer (see NewWriter). +type Writer struct { + d compressor + dict []byte +} + +// Write writes data to w, which will eventually write the +// compressed form of data to its underlying writer. +func (w *Writer) Write(data []byte) (n int, err error) { + return w.d.write(data) +} + +// Flush flushes any pending compressed data to the underlying writer. +// It is useful mainly in compressed network protocols, to ensure that +// a remote reader has enough data to reconstruct a packet. +// Flush does not return until the data has been written. +// If the underlying writer returns an error, Flush returns that error. +// +// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. +func (w *Writer) Flush() error { + // For more about flushing: + // http://www.bolet.org/~pornin/deflate-flush.html + return w.d.syncFlush() +} + +// Close flushes and closes the writer. +func (w *Writer) Close() error { + return w.d.close() +} + +// Reset discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level and dictionary. +func (w *Writer) Reset(dst io.Writer) { + if dw, ok := w.d.w.w.(*dictWriter); ok { + // w was created with NewWriterDict + dw.w = dst + w.d.reset(dw) + w.d.fillWindow(w.dict) + } else { + // w was created with NewWriter + w.d.reset(dst) + } +} + +// ResetDict discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level, but sets a specific dictionary. +func (w *Writer) ResetDict(dst io.Writer, dict []byte) { + w.dict = dict + w.d.reset(dst) + w.d.fillWindow(w.dict) +} diff --git a/vendor/github.com/klauspost/compress/flate/fixedhuff.go b/vendor/github.com/klauspost/compress/flate/fixedhuff.go new file mode 100644 index 000000000..7df8b9a29 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/fixedhuff.go @@ -0,0 +1,78 @@ +// Copyright 2013 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. + +package flate + +// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT + +var fixedHuffmanDecoder = huffmanDecoder{ + 7, + [huffmanNumChunks]uint32{ + 0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c09, + 0x1087, 0x0608, 0x0208, 0x0a09, 0x0008, 0x0808, 0x0408, 0x0e09, + 0x1047, 0x0588, 0x0188, 0x0909, 0x1147, 0x0788, 0x0388, 0x0d09, + 0x10c7, 0x0688, 0x0288, 0x0b09, 0x0088, 0x0888, 0x0488, 0x0f09, + 0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c89, + 0x10a7, 0x0648, 0x0248, 0x0a89, 0x0048, 0x0848, 0x0448, 0x0e89, + 0x1067, 0x05c8, 0x01c8, 0x0989, 0x1167, 0x07c8, 0x03c8, 0x0d89, + 0x10e7, 0x06c8, 0x02c8, 0x0b89, 0x00c8, 0x08c8, 0x04c8, 0x0f89, + 0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c49, + 0x1097, 0x0628, 0x0228, 0x0a49, 0x0028, 0x0828, 0x0428, 0x0e49, + 0x1057, 0x05a8, 0x01a8, 0x0949, 0x1157, 0x07a8, 0x03a8, 0x0d49, + 0x10d7, 0x06a8, 0x02a8, 0x0b49, 0x00a8, 0x08a8, 0x04a8, 0x0f49, + 0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cc9, + 0x10b7, 0x0668, 0x0268, 0x0ac9, 0x0068, 0x0868, 0x0468, 0x0ec9, + 0x1077, 0x05e8, 0x01e8, 0x09c9, 0x1177, 0x07e8, 0x03e8, 0x0dc9, + 0x10f7, 0x06e8, 0x02e8, 0x0bc9, 0x00e8, 0x08e8, 0x04e8, 0x0fc9, + 0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c29, + 0x1087, 0x0618, 0x0218, 0x0a29, 0x0018, 0x0818, 0x0418, 0x0e29, + 0x1047, 0x0598, 0x0198, 0x0929, 0x1147, 0x0798, 0x0398, 0x0d29, + 0x10c7, 0x0698, 0x0298, 0x0b29, 0x0098, 0x0898, 0x0498, 0x0f29, + 0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0ca9, + 0x10a7, 0x0658, 0x0258, 0x0aa9, 0x0058, 0x0858, 0x0458, 0x0ea9, + 0x1067, 0x05d8, 0x01d8, 0x09a9, 0x1167, 0x07d8, 0x03d8, 0x0da9, + 0x10e7, 0x06d8, 0x02d8, 0x0ba9, 0x00d8, 0x08d8, 0x04d8, 0x0fa9, + 0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c69, + 0x1097, 0x0638, 0x0238, 0x0a69, 0x0038, 0x0838, 0x0438, 0x0e69, + 0x1057, 0x05b8, 0x01b8, 0x0969, 0x1157, 0x07b8, 0x03b8, 0x0d69, + 0x10d7, 0x06b8, 0x02b8, 0x0b69, 0x00b8, 0x08b8, 0x04b8, 0x0f69, + 0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0ce9, + 0x10b7, 0x0678, 0x0278, 0x0ae9, 0x0078, 0x0878, 0x0478, 0x0ee9, + 0x1077, 0x05f8, 0x01f8, 0x09e9, 0x1177, 0x07f8, 0x03f8, 0x0de9, + 0x10f7, 0x06f8, 0x02f8, 0x0be9, 0x00f8, 0x08f8, 0x04f8, 0x0fe9, + 0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c19, + 0x1087, 0x0608, 0x0208, 0x0a19, 0x0008, 0x0808, 0x0408, 0x0e19, + 0x1047, 0x0588, 0x0188, 0x0919, 0x1147, 0x0788, 0x0388, 0x0d19, + 0x10c7, 0x0688, 0x0288, 0x0b19, 0x0088, 0x0888, 0x0488, 0x0f19, + 0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c99, + 0x10a7, 0x0648, 0x0248, 0x0a99, 0x0048, 0x0848, 0x0448, 0x0e99, + 0x1067, 0x05c8, 0x01c8, 0x0999, 0x1167, 0x07c8, 0x03c8, 0x0d99, + 0x10e7, 0x06c8, 0x02c8, 0x0b99, 0x00c8, 0x08c8, 0x04c8, 0x0f99, + 0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c59, + 0x1097, 0x0628, 0x0228, 0x0a59, 0x0028, 0x0828, 0x0428, 0x0e59, + 0x1057, 0x05a8, 0x01a8, 0x0959, 0x1157, 0x07a8, 0x03a8, 0x0d59, + 0x10d7, 0x06a8, 0x02a8, 0x0b59, 0x00a8, 0x08a8, 0x04a8, 0x0f59, + 0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cd9, + 0x10b7, 0x0668, 0x0268, 0x0ad9, 0x0068, 0x0868, 0x0468, 0x0ed9, + 0x1077, 0x05e8, 0x01e8, 0x09d9, 0x1177, 0x07e8, 0x03e8, 0x0dd9, + 0x10f7, 0x06e8, 0x02e8, 0x0bd9, 0x00e8, 0x08e8, 0x04e8, 0x0fd9, + 0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c39, + 0x1087, 0x0618, 0x0218, 0x0a39, 0x0018, 0x0818, 0x0418, 0x0e39, + 0x1047, 0x0598, 0x0198, 0x0939, 0x1147, 0x0798, 0x0398, 0x0d39, + 0x10c7, 0x0698, 0x0298, 0x0b39, 0x0098, 0x0898, 0x0498, 0x0f39, + 0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0cb9, + 0x10a7, 0x0658, 0x0258, 0x0ab9, 0x0058, 0x0858, 0x0458, 0x0eb9, + 0x1067, 0x05d8, 0x01d8, 0x09b9, 0x1167, 0x07d8, 0x03d8, 0x0db9, + 0x10e7, 0x06d8, 0x02d8, 0x0bb9, 0x00d8, 0x08d8, 0x04d8, 0x0fb9, + 0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c79, + 0x1097, 0x0638, 0x0238, 0x0a79, 0x0038, 0x0838, 0x0438, 0x0e79, + 0x1057, 0x05b8, 0x01b8, 0x0979, 0x1157, 0x07b8, 0x03b8, 0x0d79, + 0x10d7, 0x06b8, 0x02b8, 0x0b79, 0x00b8, 0x08b8, 0x04b8, 0x0f79, + 0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0cf9, + 0x10b7, 0x0678, 0x0278, 0x0af9, 0x0078, 0x0878, 0x0478, 0x0ef9, + 0x1077, 0x05f8, 0x01f8, 0x09f9, 0x1177, 0x07f8, 0x03f8, 0x0df9, + 0x10f7, 0x06f8, 0x02f8, 0x0bf9, 0x00f8, 0x08f8, 0x04f8, 0x0ff9, + }, + nil, 0, +} diff --git a/vendor/github.com/klauspost/compress/flate/gen.go b/vendor/github.com/klauspost/compress/flate/gen.go new file mode 100644 index 000000000..154c89a48 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/gen.go @@ -0,0 +1,265 @@ +// Copyright 2012 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. + +// +build ignore + +// This program generates fixedhuff.go +// Invoke as +// +// go run gen.go -output fixedhuff.go + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "io/ioutil" + "log" +) + +var filename = flag.String("output", "fixedhuff.go", "output file name") + +const maxCodeLen = 16 + +// Note: the definition of the huffmanDecoder struct is copied from +// inflate.go, as it is private to the implementation. + +// chunk & 15 is number of bits +// chunk >> 4 is value, including table link + +const ( + huffmanChunkBits = 9 + huffmanNumChunks = 1 << huffmanChunkBits + huffmanCountMask = 15 + huffmanValueShift = 4 +) + +type huffmanDecoder struct { + min int // the minimum code length + chunks [huffmanNumChunks]uint32 // chunks as described above + links [][]uint32 // overflow links + linkMask uint32 // mask the width of the link table +} + +// Initialize Huffman decoding tables from array of code lengths. +// Following this function, h is guaranteed to be initialized into a complete +// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a +// degenerate case where the tree has only a single symbol with length 1. Empty +// trees are permitted. +func (h *huffmanDecoder) init(bits []int) bool { + // Sanity enables additional runtime tests during Huffman + // table construction. It's intended to be used during + // development to supplement the currently ad-hoc unit tests. + const sanity = false + + if h.min != 0 { + *h = huffmanDecoder{} + } + + // Count number of codes of each length, + // compute min and max length. + var count [maxCodeLen]int + var min, max int + for _, n := range bits { + if n == 0 { + continue + } + if min == 0 || n < min { + min = n + } + if n > max { + max = n + } + count[n]++ + } + + // Empty tree. The decompressor.huffSym function will fail later if the tree + // is used. Technically, an empty tree is only valid for the HDIST tree and + // not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree + // is guaranteed to fail since it will attempt to use the tree to decode the + // codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is + // guaranteed to fail later since the compressed data section must be + // composed of at least one symbol (the end-of-block marker). + if max == 0 { + return true + } + + code := 0 + var nextcode [maxCodeLen]int + for i := min; i <= max; i++ { + code <<= 1 + nextcode[i] = code + code += count[i] + } + + // Check that the coding is complete (i.e., that we've + // assigned all 2-to-the-max possible bit sequences). + // Exception: To be compatible with zlib, we also need to + // accept degenerate single-code codings. See also + // TestDegenerateHuffmanCoding. + if code != 1< huffmanChunkBits { + numLinks := 1 << (uint(max) - huffmanChunkBits) + h.linkMask = uint32(numLinks - 1) + + // create link tables + link := nextcode[huffmanChunkBits+1] >> 1 + h.links = make([][]uint32, huffmanNumChunks-link) + for j := uint(link); j < huffmanNumChunks; j++ { + reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8 + reverse >>= uint(16 - huffmanChunkBits) + off := j - uint(link) + if sanity && h.chunks[reverse] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[reverse] = uint32(off<>8]) | int(reverseByte[code&0xff])<<8 + reverse >>= uint(16 - n) + if n <= huffmanChunkBits { + for off := reverse; off < len(h.chunks); off += 1 << uint(n) { + // We should never need to overwrite + // an existing chunk. Also, 0 is + // never a valid chunk, because the + // lower 4 "count" bits should be + // between 1 and 15. + if sanity && h.chunks[off] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[off] = chunk + } + } else { + j := reverse & (huffmanNumChunks - 1) + if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 { + // Longer codes should have been + // associated with a link table above. + panic("impossible: not an indirect chunk") + } + value := h.chunks[j] >> huffmanValueShift + linktab := h.links[value] + reverse >>= huffmanChunkBits + for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) { + if sanity && linktab[off] != 0 { + panic("impossible: overwriting existing chunk") + } + linktab[off] = chunk + } + } + } + + if sanity { + // Above we've sanity checked that we never overwrote + // an existing entry. Here we additionally check that + // we filled the tables completely. + for i, chunk := range h.chunks { + if chunk == 0 { + // As an exception, in the degenerate + // single-code case, we allow odd + // chunks to be missing. + if code == 1 && i%2 == 1 { + continue + } + panic("impossible: missing chunk") + } + } + for _, linktab := range h.links { + for _, chunk := range linktab { + if chunk == 0 { + panic("impossible: missing chunk") + } + } + } + } + + return true +} + +func main() { + flag.Parse() + + var h huffmanDecoder + var bits [288]int + initReverseByte() + for i := 0; i < 144; i++ { + bits[i] = 8 + } + for i := 144; i < 256; i++ { + bits[i] = 9 + } + for i := 256; i < 280; i++ { + bits[i] = 7 + } + for i := 280; i < 288; i++ { + bits[i] = 8 + } + h.init(bits[:]) + if h.links != nil { + log.Fatal("Unexpected links table in fixed Huffman decoder") + } + + var buf bytes.Buffer + + fmt.Fprintf(&buf, `// Copyright 2013 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.`+"\n\n") + + fmt.Fprintln(&buf, "package flate") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, "var fixedHuffmanDecoder = huffmanDecoder{") + fmt.Fprintf(&buf, "\t%d,\n", h.min) + fmt.Fprintln(&buf, "\t[huffmanNumChunks]uint32{") + for i := 0; i < huffmanNumChunks; i++ { + if i&7 == 0 { + fmt.Fprintf(&buf, "\t\t") + } else { + fmt.Fprintf(&buf, " ") + } + fmt.Fprintf(&buf, "0x%04x,", h.chunks[i]) + if i&7 == 7 { + fmt.Fprintln(&buf) + } + } + fmt.Fprintln(&buf, "\t},") + fmt.Fprintln(&buf, "\tnil, 0,") + fmt.Fprintln(&buf, "}") + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(*filename, data, 0644) + if err != nil { + log.Fatal(err) + } +} + +var reverseByte [256]byte + +func initReverseByte() { + for x := 0; x < 256; x++ { + var result byte + for i := uint(0); i < 8; i++ { + result |= byte(((x >> i) & 1) << (7 - i)) + } + reverseByte[x] = result + } +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go new file mode 100644 index 000000000..2a0004e4d --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go @@ -0,0 +1,778 @@ +// 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. + +package flate + +import ( + "io" + "math" +) + +const ( + // The largest offset code. + offsetCodeCount = 30 + + // The special code used to mark the end of a block. + endBlockMarker = 256 + + // The first length code. + lengthCodesStart = 257 + + // The number of codegen codes. + codegenCodeCount = 19 + badCode = 255 + + // Output byte buffer size + // Must be multiple of 6 (48 bits) + 8 + bufferSize = 240 + 8 +) + +// The number of extra bits needed by length code X - LENGTH_CODES_START. +var lengthExtraBits = []int8{ + /* 257 */ 0, 0, 0, + /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, + /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + /* 280 */ 4, 5, 5, 5, 5, 0, +} + +// The length indicated by length code X - LENGTH_CODES_START. +var lengthBase = []uint32{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, + 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 255, +} + +// offset code word extra bits. +var offsetExtraBits = []int8{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + /* extended window */ + 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, +} + +var offsetBase = []uint32{ + /* normal deflate */ + 0x000000, 0x000001, 0x000002, 0x000003, 0x000004, + 0x000006, 0x000008, 0x00000c, 0x000010, 0x000018, + 0x000020, 0x000030, 0x000040, 0x000060, 0x000080, + 0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300, + 0x000400, 0x000600, 0x000800, 0x000c00, 0x001000, + 0x001800, 0x002000, 0x003000, 0x004000, 0x006000, + + /* extended window */ + 0x008000, 0x00c000, 0x010000, 0x018000, 0x020000, + 0x030000, 0x040000, 0x060000, 0x080000, 0x0c0000, + 0x100000, 0x180000, 0x200000, 0x300000, +} + +// The odd order in which the codegen code sizes are written. +var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +type huffmanBitWriter struct { + w io.Writer + // Data waiting to be written is bytes[0:nbytes] + // and then the low nbits of bits. + bits uint64 + nbits uint + bytes [bufferSize]byte + nbytes int + literalFreq []int32 + offsetFreq []int32 + codegen []uint8 + codegenFreq []int32 + literalEncoding *huffmanEncoder + dynamicEncoding *huffmanEncoder + codegenEncoding *huffmanEncoder + err error +} + +func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { + return &huffmanBitWriter{ + w: w, + literalFreq: make([]int32, maxNumLit), + offsetFreq: make([]int32, offsetCodeCount), + codegen: make([]uint8, maxNumLit+offsetCodeCount+1), + codegenFreq: make([]int32, codegenCodeCount), + literalEncoding: newHuffmanEncoder(maxNumLit), + codegenEncoding: newHuffmanEncoder(codegenCodeCount), + dynamicEncoding: newHuffmanEncoder(offsetCodeCount), + } +} + +func (w *huffmanBitWriter) reset(writer io.Writer) { + w.w = writer + w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil + w.bytes = [bufferSize]byte{} + for i := range w.codegen { + w.codegen[i] = 0 + } + for _, s := range [...][]int32{w.literalFreq, w.offsetFreq, w.codegenFreq} { + for i := range s { + s[i] = 0 + } + } + encs := []*huffmanEncoder{w.literalEncoding, w.codegenEncoding, w.dynamicEncoding} + for _, enc := range encs { + for i := range enc.codes { + enc.codes[i] = 0 + } + } +} + +/* Inlined in writeBits +func (w *huffmanBitWriter) flushBits() { + if w.err != nil { + w.nbits = 0 + return + } + bits := w.bits + w.bits >>= 16 + w.nbits -= 16 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + if n += 2; n >= len(w.bytes) { + _, w.err = w.w.Write(w.bytes[0:]) + n = 0 + } + w.nbytes = n +} +*/ + +func (w *huffmanBitWriter) flush() { + if w.err != nil { + w.nbits = 0 + return + } + n := w.nbytes + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + if w.nbits > 8 { // Avoid underflow + w.nbits -= 8 + } else { + w.nbits = 0 + } + n++ + } + w.bits = 0 + _, w.err = w.w.Write(w.bytes[0:n]) + w.nbytes = 0 +} + +func (w *huffmanBitWriter) writeBits(b int32, nb uint) { + w.bits |= uint64(b) << w.nbits + w.nbits += nb + if w.nbits >= 48 { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + w.bytes[n+2] = byte(bits >> 16) + w.bytes[n+3] = byte(bits >> 24) + w.bytes[n+4] = byte(bits >> 32) + w.bytes[n+5] = byte(bits >> 40) + n += 6 + if n >= bufferSize-8 { + _, w.err = w.w.Write(w.bytes[:bufferSize-8]) + n = 0 + } + w.nbytes = n + } +} + +func (w *huffmanBitWriter) writeBytes(bytes []byte) { + if w.err != nil { + return + } + n := w.nbytes + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + w.nbits -= 8 + n++ + } + if w.nbits != 0 { + w.err = InternalError("writeBytes with unfinished bits") + return + } + if n != 0 { + _, w.err = w.w.Write(w.bytes[0:n]) + if w.err != nil { + return + } + } + w.nbytes = 0 + _, w.err = w.w.Write(bytes) +} + +// RFC 1951 3.2.7 specifies a special run-length encoding for specifying +// the literal and offset lengths arrays (which are concatenated into a single +// array). This method generates that run-length encoding. +// +// The result is written into the codegen array, and the frequencies +// of each code is written into the codegenFreq array. +// Codes 0-15 are single byte codes. Codes 16-18 are followed by additional +// information. Code badCode is an end marker +// +// numLiterals The number of literals in literalEncoding +// numOffsets The number of offsets in offsetEncoding +func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, offenc *huffmanEncoder) { + for i := range w.codegenFreq { + w.codegenFreq[i] = 0 + } + // Note that we are using codegen both as a temporary variable for holding + // a copy of the frequencies, and as the place where we put the result. + // This is fine because the output is always shorter than the input used + // so far. + codegen := w.codegen // cache + // Copy the concatenated code sizes to codegen. Put a marker at the end. + //copy(codegen[0:numLiterals], w.literalEncoding.codeBits) + cgnl := codegen[0:numLiterals] + for i := range cgnl { + cgnl[i] = uint8(w.literalEncoding.codes[i].bits()) + } + + //copy(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits) + cgnl = codegen[numLiterals : numLiterals+numOffsets] + for i := range cgnl { + cgnl[i] = uint8(offenc.codes[i].bits()) + } + codegen[numLiterals+numOffsets] = badCode + + size := codegen[0] + count := 1 + outIndex := 0 + for inIndex := 1; size != badCode; inIndex++ { + // INVARIANT: We have seen "count" copies of size that have not yet + // had output generated for them. + nextSize := codegen[inIndex] + if nextSize == size { + count++ + continue + } + // We need to generate codegen indicating "count" of size. + if size != 0 { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + count-- + for count >= 3 { + n := 6 + if n > count { + n = count + } + codegen[outIndex] = 16 + outIndex++ + codegen[outIndex] = uint8(n - 3) + outIndex++ + w.codegenFreq[16]++ + count -= n + } + } else { + for count >= 11 { + n := 138 + if n > count { + n = count + } + codegen[outIndex] = 18 + outIndex++ + codegen[outIndex] = uint8(n - 11) + outIndex++ + w.codegenFreq[18]++ + count -= n + } + if count >= 3 { + // count >= 3 && count <= 10 + codegen[outIndex] = 17 + outIndex++ + codegen[outIndex] = uint8(count - 3) + outIndex++ + w.codegenFreq[17]++ + count = 0 + } + } + count-- + for ; count >= 0; count-- { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + } + // Set up invariant for next time through the loop. + size = nextSize + count = 1 + } + // Marker indicating the end of the codegen. + codegen[outIndex] = badCode +} + +/* non-inlined: +func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) { + if w.err != nil { + return + } + c := code.codes[literal] + w.writeBits(int32(c.code()), int32(c.bits())) +} +*/ + +func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) { + if w.err != nil { + return + } + c := code.codes[literal] + w.bits |= uint64(c.code()) << w.nbits + w.nbits += c.bits() + if w.nbits >= 48 { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + w.bytes[n+2] = byte(bits >> 16) + w.bytes[n+3] = byte(bits >> 24) + w.bytes[n+4] = byte(bits >> 32) + w.bytes[n+5] = byte(bits >> 40) + n += 6 + if n >= bufferSize-8 { + _, w.err = w.w.Write(w.bytes[:bufferSize-8]) + n = 0 + } + w.nbytes = n + } + +} + +// Write the header of a dynamic Huffman block to the output stream. +// +// numLiterals The number of literals specified in codegen +// numOffsets The number of offsets specified in codegen +// numCodegens The number of codegens used in codegen +func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) { + if w.err != nil { + return + } + var firstBits int32 = 4 + if isEof { + firstBits = 5 + } + w.writeBits(firstBits, 3) + w.writeBits(int32(numLiterals-257), 5) + w.writeBits(int32(numOffsets-1), 5) + w.writeBits(int32(numCodegens-4), 4) + + for i := 0; i < numCodegens; i++ { + //value := w.codegenEncoding.codeBits[codegenOrder[i]] + value := w.codegenEncoding.codes[codegenOrder[i]].bits() + w.writeBits(int32(value), 3) + } + + i := 0 + for { + var codeWord int = int(w.codegen[i]) + i++ + if codeWord == badCode { + break + } + // The low byte contains the actual code to generate. + w.writeCode(w.codegenEncoding, uint32(codeWord)) + + switch codeWord { + case 16: + w.writeBits(int32(w.codegen[i]), 2) + i++ + break + case 17: + w.writeBits(int32(w.codegen[i]), 3) + i++ + break + case 18: + w.writeBits(int32(w.codegen[i]), 7) + i++ + break + } + } +} + +func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) { + if w.err != nil { + return + } + var flag int32 + if isEof { + flag = 1 + } + w.writeBits(flag, 3) + w.flush() + w.writeBits(int32(length), 16) + w.writeBits(int32(^uint16(length)), 16) +} + +func (w *huffmanBitWriter) writeFixedHeader(isEof bool) { + if w.err != nil { + return + } + // Indicate that we are a fixed Huffman block + var value int32 = 2 + if isEof { + value = 3 + } + w.writeBits(value, 3) +} + +func (w *huffmanBitWriter) writeBlock(tok tokens, eof bool, input []byte) { + if w.err != nil { + return + } + copy(w.literalFreq, zeroLits[:]) + + for i := range w.offsetFreq { + w.offsetFreq[i] = 0 + } + + tok.tokens[tok.n] = endBlockMarker + tokens := tok.tokens[0 : tok.n+1] + + for _, t := range tokens { + switch t.typ() { + case literalType: + w.literalFreq[t.literal()]++ + case matchType: + length := t.length() + offset := t.offset() + w.literalFreq[lengthCodesStart+lengthCode(length)]++ + w.offsetFreq[offsetCode(offset)]++ + } + } + + // get the number of literals + numLiterals := len(w.literalFreq) + for w.literalFreq[numLiterals-1] == 0 { + numLiterals-- + } + // get the number of offsets + numOffsets := len(w.offsetFreq) + for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { + numOffsets-- + } + if numOffsets == 0 { + // We haven't found a single match. If we want to go with the dynamic encoding, + // we should count at least one offset to be sure that the offset huffman tree could be encoded. + w.offsetFreq[0] = 1 + numOffsets = 1 + } + + w.literalEncoding.generate(w.literalFreq, 15) + w.dynamicEncoding.generate(w.offsetFreq, 15) + + storedBytes := 0 + if input != nil { + storedBytes = len(input) + } + var extraBits int64 + var storedSize int64 = math.MaxInt64 + if storedBytes <= maxStoreBlockSize && input != nil { + storedSize = int64((storedBytes + 5) * 8) + // We only bother calculating the costs of the extra bits required by + // the length of offset fields (which will be the same for both fixed + // and dynamic encoding), if we need to compare those two encodings + // against stored encoding. + for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ { + // First eight length codes have extra size = 0. + extraBits += int64(w.literalFreq[lengthCode]) * int64(lengthExtraBits[lengthCode-lengthCodesStart]) + } + for offsetCode := 4; offsetCode < numOffsets; offsetCode++ { + // First four offset codes have extra size = 0. + extraBits += int64(w.offsetFreq[offsetCode]) * int64(offsetExtraBits[offsetCode]) + } + } + + // Figure out smallest code. + // Fixed Huffman baseline. + var size = int64(3) + + fixedLiteralEncoding.bitLength(w.literalFreq) + + fixedOffsetEncoding.bitLength(w.offsetFreq) + + extraBits + var literalEncoding = fixedLiteralEncoding + var offsetEncoding = fixedOffsetEncoding + + // Dynamic Huffman? + var numCodegens int + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.dynamicEncoding) + w.codegenEncoding.generate(w.codegenFreq, 7) + numCodegens = len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + dynamicHeader := int64(3+5+5+4+(3*numCodegens)) + + w.codegenEncoding.bitLength(w.codegenFreq) + + int64(extraBits) + + int64(w.codegenFreq[16]*2) + + int64(w.codegenFreq[17]*3) + + int64(w.codegenFreq[18]*7) + dynamicSize := dynamicHeader + + w.literalEncoding.bitLength(w.literalFreq) + + w.dynamicEncoding.bitLength(w.offsetFreq) + + if dynamicSize < size { + size = dynamicSize + literalEncoding = w.literalEncoding + offsetEncoding = w.dynamicEncoding + } + + // Stored bytes? + if storedSize < size { + w.writeStoredHeader(storedBytes, eof) + w.writeBytes(input[0:storedBytes]) + return + } + + // Huffman. + if literalEncoding == fixedLiteralEncoding { + w.writeFixedHeader(eof) + } else { + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + } + for _, t := range tokens { + switch t.typ() { + case literalType: + w.writeCode(literalEncoding, t.literal()) + break + case matchType: + // Write the length + length := t.length() + lengthCode := lengthCode(length) + w.writeCode(literalEncoding, lengthCode+lengthCodesStart) + extraLengthBits := uint(lengthExtraBits[lengthCode]) + if extraLengthBits > 0 { + extraLength := int32(length - lengthBase[lengthCode]) + w.writeBits(extraLength, extraLengthBits) + } + // Write the offset + offset := t.offset() + offsetCode := offsetCode(offset) + w.writeCode(offsetEncoding, offsetCode) + extraOffsetBits := uint(offsetExtraBits[offsetCode]) + if extraOffsetBits > 0 { + extraOffset := int32(offset - offsetBase[offsetCode]) + w.writeBits(extraOffset, extraOffsetBits) + } + break + default: + panic("unknown token type: " + string(t)) + } + } +} + +// writeBlockDynamic will write a block as dynamic Huffman table +// compressed. This should be used, if the caller has a reasonable expectation +// that this block contains compressible data. +func (w *huffmanBitWriter) writeBlockDynamic(tok tokens, eof bool, input []byte) { + if w.err != nil { + return + } + copy(w.literalFreq, zeroLits[:]) + + for i := range w.offsetFreq { + w.offsetFreq[i] = 0 + } + + tok.tokens[tok.n] = endBlockMarker + tokens := tok.tokens[0 : tok.n+1] + + for _, t := range tokens { + switch t.typ() { + case literalType: + w.literalFreq[t.literal()]++ + case matchType: + length := t.length() + offset := t.offset() + w.literalFreq[lengthCodesStart+lengthCode(length)]++ + w.offsetFreq[offsetCode(offset)]++ + } + } + + // get the number of literals + numLiterals := len(w.literalFreq) + for w.literalFreq[numLiterals-1] == 0 { + numLiterals-- + } + // get the number of offsets + numOffsets := len(w.offsetFreq) + for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { + numOffsets-- + } + if numOffsets == 0 { + // We haven't found a single match. If we want to go with the dynamic encoding, + // we should count at least one offset to be sure that the offset huffman tree could be encoded. + w.offsetFreq[0] = 1 + numOffsets = 1 + } + + w.literalEncoding.generate(w.literalFreq, 15) + w.dynamicEncoding.generate(w.offsetFreq, 15) + + var numCodegens int + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.dynamicEncoding) + w.codegenEncoding.generate(w.codegenFreq, 7) + numCodegens = len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + var literalEncoding = w.literalEncoding + var offsetEncoding = w.dynamicEncoding + + // Write Huffman table. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + for _, t := range tokens { + switch t.typ() { + case literalType: + w.writeCode(literalEncoding, t.literal()) + break + case matchType: + // Write the length + length := t.length() + lengthCode := lengthCode(length) + w.writeCode(literalEncoding, lengthCode+lengthCodesStart) + extraLengthBits := uint(lengthExtraBits[lengthCode]) + if extraLengthBits > 0 { + extraLength := int32(length - lengthBase[lengthCode]) + w.writeBits(extraLength, extraLengthBits) + } + // Write the offset + offset := t.offset() + offsetCode := offsetCode(offset) + w.writeCode(offsetEncoding, offsetCode) + extraOffsetBits := uint(offsetExtraBits[offsetCode]) + if extraOffsetBits > 0 { + extraOffset := int32(offset - offsetBase[offsetCode]) + w.writeBits(extraOffset, extraOffsetBits) + } + break + default: + panic("unknown token type: " + string(t)) + } + } +} + +// static offset encoder used for huffman only encoding. +var huffOffset *huffmanEncoder +var zeroLits [maxNumLit]int32 + +func init() { + var w = newHuffmanBitWriter(nil) + w.offsetFreq[0] = 1 + huffOffset = newHuffmanEncoder(offsetCodeCount) + huffOffset.generate(w.offsetFreq, 15) +} + +// writeBlockHuff will write a block of bytes as either +// Huffman encoded literals, or uncompressed bytes depending +// on what yields the smallest result. +func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte) { + if w.err != nil { + return + } + + // Clear histogram + copy(w.literalFreq, zeroLits[:]) + + // Add everything as literals + histogram(input, w.literalFreq) + + w.literalFreq[endBlockMarker] = 1 + + const numLiterals = endBlockMarker + 1 + const numOffsets = 1 + + w.literalEncoding.generate(w.literalFreq, 15) + + storedBytes := len(input) + + var extraBits int64 + var storedSize int64 = math.MaxInt64 + if storedBytes <= maxStoreBlockSize { + storedSize = int64((storedBytes + 5) * 8) + // We only bother calculating the costs of the extra bits required by + // the length of offset fields (which will be the same for both fixed + // and dynamic encoding), if we need to compare those two encodings + // against stored encoding. + for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ { + // First eight length codes have extra size = 0. + extraBits += int64(w.literalFreq[lengthCode]) * int64(lengthExtraBits[lengthCode-lengthCodesStart]) + } + } + + // Figure out smallest code. + // Always use dynamic Huffman or Store + var numCodegens int + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, huffOffset) + w.codegenEncoding.generate(w.codegenFreq, 7) + numCodegens = len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + dynamicHeader := int64(3+5+5+4+(3*numCodegens)) + + w.codegenEncoding.bitLength(w.codegenFreq) + + int64(extraBits) + + int64(w.codegenFreq[16]*2) + + int64(w.codegenFreq[17]*3) + + int64(w.codegenFreq[18]*7) + size := dynamicHeader + + w.literalEncoding.bitLength(w.literalFreq) + + 1 /*w.offsetEncoding.bitLength(w.offsetFreq)*/ + + // Store bytes, if we don't get a reasonable improvement. + if storedSize < (size + size>>4) { + w.writeStoredHeader(storedBytes, eof) + w.writeBytes(input[0:storedBytes]) + return + } + + // Huffman. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + for _, t := range input { + // Bitwriting inlined, ~30% speedup + c := w.literalEncoding.codes[t] + w.bits |= uint64(c.code()) << w.nbits + w.nbits += c.bits() + if w.nbits >= 48 { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + w.bytes[n+2] = byte(bits >> 16) + w.bytes[n+3] = byte(bits >> 24) + w.bytes[n+4] = byte(bits >> 32) + w.bytes[n+5] = byte(bits >> 40) + n += 6 + if n >= bufferSize-8 { + _, w.err = w.w.Write(w.bytes[:bufferSize-8]) + if w.err != nil { + return + } + w.nbytes = 0 + } else { + w.nbytes = n + } + } + } + // Write EOB + w.writeCode(w.literalEncoding, endBlockMarker) +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go new file mode 100644 index 000000000..9dba0faf3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go @@ -0,0 +1,363 @@ +// 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. + +package flate + +import ( + "math" + "sort" +) + +type hcode uint32 + +type huffmanEncoder struct { + codes []hcode + freqcache []literalNode + bitCount [17]int32 + lns literalNodeSorter + lfs literalFreqSorter +} + +type literalNode struct { + literal uint16 + freq int32 +} + +// A levelInfo describes the state of the constructed tree for a given depth. +type levelInfo struct { + // Our level. for better printing + level int32 + + // The frequency of the last node at this level + lastFreq int32 + + // The frequency of the next character to add to this level + nextCharFreq int32 + + // The frequency of the next pair (from level below) to add to this level. + // Only valid if the "needed" value of the next lower level is 0. + nextPairFreq int32 + + // The number of chains remaining to generate for this level before moving + // up to the next level + needed int32 +} + +func (h hcode) codeBits() (code uint16, bits uint8) { + return uint16(h), uint8(h >> 16) +} + +func (h *hcode) set(code uint16, bits uint8) { + *h = hcode(code) | hcode(uint32(bits)<<16) +} + +func (h *hcode) setBits(bits uint8) { + *h = hcode(*h&0xffff) | hcode(uint32(bits)<<16) +} + +func toCode(code uint16, bits uint8) hcode { + return hcode(code) | hcode(uint32(bits)<<16) +} + +func (h hcode) code() (code uint16) { + return uint16(h) +} + +func (h hcode) bits() (bits uint) { + return uint(h >> 16) +} + +func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} } + +func newHuffmanEncoder(size int) *huffmanEncoder { + return &huffmanEncoder{codes: make([]hcode, size), freqcache: nil} +} + +// Generates a HuffmanCode corresponding to the fixed literal table +func generateFixedLiteralEncoding() *huffmanEncoder { + h := newHuffmanEncoder(maxNumLit) + codes := h.codes + var ch uint16 + for ch = 0; ch < maxNumLit; ch++ { + var bits uint16 + var size uint8 + switch { + case ch < 144: + // size 8, 000110000 .. 10111111 + bits = ch + 48 + size = 8 + break + case ch < 256: + // size 9, 110010000 .. 111111111 + bits = ch + 400 - 144 + size = 9 + break + case ch < 280: + // size 7, 0000000 .. 0010111 + bits = ch - 256 + size = 7 + break + default: + // size 8, 11000000 .. 11000111 + bits = ch + 192 - 280 + size = 8 + } + codes[ch] = toCode(reverseBits(bits, size), size) + } + return h +} + +func generateFixedOffsetEncoding() *huffmanEncoder { + h := newHuffmanEncoder(30) + codes := h.codes + for ch := uint16(0); ch < 30; ch++ { + codes[ch] = toCode(reverseBits(ch, 5), 5) + } + return h +} + +var fixedLiteralEncoding *huffmanEncoder = generateFixedLiteralEncoding() +var fixedOffsetEncoding *huffmanEncoder = generateFixedOffsetEncoding() + +func (h *huffmanEncoder) bitLength(freq []int32) int64 { + var total int64 + for i, f := range freq { + if f != 0 { + total += int64(f) * int64(h.codes[i].bits()) + } + } + return total +} + +const maxBitsLimit = 16 + +// Return the number of literals assigned to each bit size in the Huffman encoding +// +// This method is only called when list.length >= 3 +// The cases of 0, 1, and 2 literals are handled by special case code. +// +// list An array of the literals with non-zero frequencies +// and their associated frequencies. The array is in order of increasing +// frequency, and has as its last element a special element with frequency +// MaxInt32 +// maxBits The maximum number of bits that should be used to encode any literal. +// Must be less than 16. +// return An integer array in which array[i] indicates the number of literals +// that should be encoded in i bits. +func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { + if maxBits >= maxBitsLimit { + panic("flate: maxBits too large") + } + n := int32(len(list)) + list = list[0 : n+1] + list[n] = maxNode() + + // The tree can't have greater depth than n - 1, no matter what. This + // saves a little bit of work in some small cases + if maxBits > n-1 { + maxBits = n - 1 + } + + // Create information about each of the levels. + // A bogus "Level 0" whose sole purpose is so that + // level1.prev.needed==0. This makes level1.nextPairFreq + // be a legitimate value that never gets chosen. + var levels [maxBitsLimit]levelInfo + // leafCounts[i] counts the number of literals at the left + // of ancestors of the rightmost node at level i. + // leafCounts[i][j] is the number of literals at the left + // of the level j ancestor. + var leafCounts [maxBitsLimit][maxBitsLimit]int32 + + for level := int32(1); level <= maxBits; level++ { + // For every level, the first two items are the first two characters. + // We initialize the levels as if we had already figured this out. + levels[level] = levelInfo{ + level: level, + lastFreq: list[1].freq, + nextCharFreq: list[2].freq, + nextPairFreq: list[0].freq + list[1].freq, + } + leafCounts[level][level] = 2 + if level == 1 { + levels[level].nextPairFreq = math.MaxInt32 + } + } + + // We need a total of 2*n - 2 items at top level and have already generated 2. + levels[maxBits].needed = 2*n - 4 + + level := maxBits + for { + l := &levels[level] + if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 { + // We've run out of both leafs and pairs. + // End all calculations for this level. + // To make sure we never come back to this level or any lower level, + // set nextPairFreq impossibly large. + l.needed = 0 + levels[level+1].nextPairFreq = math.MaxInt32 + level++ + continue + } + + prevFreq := l.lastFreq + if l.nextCharFreq < l.nextPairFreq { + // The next item on this row is a leaf node. + n := leafCounts[level][level] + 1 + l.lastFreq = l.nextCharFreq + // Lower leafCounts are the same of the previous node. + leafCounts[level][level] = n + l.nextCharFreq = list[n].freq + } else { + // The next item on this row is a pair from the previous row. + // nextPairFreq isn't valid until we generate two + // more values in the level below + l.lastFreq = l.nextPairFreq + // Take leaf counts from the lower level, except counts[level] remains the same. + copy(leafCounts[level][:level], leafCounts[level-1][:level]) + levels[l.level-1].needed = 2 + } + + if l.needed--; l.needed == 0 { + // We've done everything we need to do for this level. + // Continue calculating one level up. Fill in nextPairFreq + // of that level with the sum of the two nodes we've just calculated on + // this level. + if l.level == maxBits { + // All done! + break + } + levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq + level++ + } else { + // If we stole from below, move down temporarily to replenish it. + for levels[level-1].needed > 0 { + level-- + } + } + } + + // Somethings is wrong if at the end, the top level is null or hasn't used + // all of the leaves. + if leafCounts[maxBits][maxBits] != n { + panic("leafCounts[maxBits][maxBits] != n") + } + + bitCount := h.bitCount[:maxBits+1] + //make([]int32, maxBits+1) + bits := 1 + counts := &leafCounts[maxBits] + for level := maxBits; level > 0; level-- { + // chain.leafCount gives the number of literals requiring at least "bits" + // bits to encode. + bitCount[bits] = counts[level] - counts[level-1] + bits++ + } + return bitCount +} + +// Look at the leaves and assign them a bit count and an encoding as specified +// in RFC 1951 3.2.2 +func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) { + code := uint16(0) + for n, bits := range bitCount { + code <<= 1 + if n == 0 || bits == 0 { + continue + } + // The literals list[len(list)-bits] .. list[len(list)-bits] + // are encoded using "bits" bits, and get the values + // code, code + 1, .... The code values are + // assigned in literal order (not frequency order). + chunk := list[len(list)-int(bits):] + + h.lns.Sort(chunk) + for _, node := range chunk { + h.codes[node.literal] = toCode(reverseBits(code, uint8(n)), uint8(n)) + code++ + } + list = list[0 : len(list)-int(bits)] + } +} + +// Update this Huffman Code object to be the minimum code for the specified frequency count. +// +// freq An array of frequencies, in which frequency[i] gives the frequency of literal i. +// maxBits The maximum number of bits to use for any literal. +func (h *huffmanEncoder) generate(freq []int32, maxBits int32) { + if h.freqcache == nil { + h.freqcache = make([]literalNode, 300) + } + list := h.freqcache[:len(freq)+1] + // Number of non-zero literals + count := 0 + // Set list to be the set of all non-zero literals and their frequencies + for i, f := range freq { + if f != 0 { + list[count] = literalNode{uint16(i), f} + count++ + } else { + list[count] = literalNode{} + //h.codeBits[i] = 0 + h.codes[i].setBits(0) + } + } + list[len(freq)] = literalNode{} + // If freq[] is shorter than codeBits[], fill rest of codeBits[] with zeros + // FIXME: Doesn't do what it says on the tin (klauspost) + //h.codeBits = h.codeBits[0:len(freq)] + + list = list[0:count] + if count <= 2 { + // Handle the small cases here, because they are awkward for the general case code. With + // two or fewer literals, everything has bit length 1. + for i, node := range list { + // "list" is in order of increasing literal value. + h.codes[node.literal].set(uint16(i), 1) + //h.codeBits[node.literal] = 1 + //h.code[node.literal] = uint16(i) + } + return + } + h.lfs.Sort(list) + + // Get the number of literals for each bit count + bitCount := h.bitCounts(list, maxBits) + // And do the assignment + h.assignEncodingAndSize(bitCount, list) +} + +type literalNodeSorter []literalNode + +func (s *literalNodeSorter) Sort(a []literalNode) { + *s = literalNodeSorter(a) + sort.Sort(s) +} + +func (s literalNodeSorter) Len() int { return len(s) } + +func (s literalNodeSorter) Less(i, j int) bool { + return s[i].literal < s[j].literal +} + +func (s literalNodeSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +type literalFreqSorter []literalNode + +func (s *literalFreqSorter) Sort(a []literalNode) { + *s = literalFreqSorter(a) + sort.Sort(s) +} + +func (s literalFreqSorter) Len() int { return len(s) } + +func (s literalFreqSorter) Less(i, j int) bool { + if s[i].freq == s[j].freq { + return s[i].literal < s[j].literal + } + return s[i].freq < s[j].freq +} + +func (s literalFreqSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go new file mode 100644 index 000000000..91e27e7e2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -0,0 +1,846 @@ +// 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. + +//go:generate go run gen.go -output fixedhuff.go + +// Package flate implements the DEFLATE compressed data format, described in +// RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file +// formats. +package flate + +import ( + "bufio" + "io" + "strconv" +) + +const ( + maxCodeLen = 16 // max length of Huffman code + maxHist = 32768 // max history required + // The next three numbers come from the RFC section 3.2.7, with the + // additional proviso in section 3.2.5 which implies that distance codes + // 30 and 31 should never occur in compressed data. + maxNumLit = 286 + maxNumDist = 30 + numCodes = 19 // number of codes in Huffman meta-code +) + +// A CorruptInputError reports the presence of corrupt input at a given offset. +type CorruptInputError int64 + +func (e CorruptInputError) Error() string { + return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10) +} + +// An InternalError reports an error in the flate code itself. +type InternalError string + +func (e InternalError) Error() string { return "flate: internal error: " + string(e) } + +// A ReadError reports an error encountered while reading input. +type ReadError struct { + Offset int64 // byte offset where error occurred + Err error // error returned by underlying Read +} + +func (e *ReadError) Error() string { + return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error() +} + +// A WriteError reports an error encountered while writing output. +type WriteError struct { + Offset int64 // byte offset where error occurred + Err error // error returned by underlying Write +} + +func (e *WriteError) Error() string { + return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error() +} + +// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to +// to switch to a new underlying Reader. This permits reusing a ReadCloser +// instead of allocating a new one. +type Resetter interface { + // Reset discards any buffered data and resets the Resetter as if it was + // newly initialized with the given reader. + Reset(r io.Reader, dict []byte) error +} + +// Note that much of the implementation of huffmanDecoder is also copied +// into gen.go (in package main) for the purpose of precomputing the +// fixed huffman tables so they can be included statically. + +// The data structure for decoding Huffman tables is based on that of +// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits), +// For codes smaller than the table width, there are multiple entries +// (each combination of trailing bits has the same value). For codes +// larger than the table width, the table contains a link to an overflow +// table. The width of each entry in the link table is the maximum code +// size minus the chunk width. + +// Note that you can do a lookup in the table even without all bits +// filled. Since the extra bits are zero, and the DEFLATE Huffman codes +// have the property that shorter codes come before longer ones, the +// bit length estimate in the result is a lower bound on the actual +// number of bits. + +// chunk & 15 is number of bits +// chunk >> 4 is value, including table link + +const ( + huffmanChunkBits = 9 + huffmanNumChunks = 1 << huffmanChunkBits + huffmanCountMask = 15 + huffmanValueShift = 4 +) + +type huffmanDecoder struct { + min int // the minimum code length + chunks [huffmanNumChunks]uint32 // chunks as described above + links [][]uint32 // overflow links + linkMask uint32 // mask the width of the link table +} + +// Initialize Huffman decoding tables from array of code lengths. +// Following this function, h is guaranteed to be initialized into a complete +// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a +// degenerate case where the tree has only a single symbol with length 1. Empty +// trees are permitted. +func (h *huffmanDecoder) init(bits []int) bool { + // Sanity enables additional runtime tests during Huffman + // table construction. It's intended to be used during + // development to supplement the currently ad-hoc unit tests. + const sanity = false + + if h.min != 0 { + *h = huffmanDecoder{} + } + + // Count number of codes of each length, + // compute min and max length. + var count [maxCodeLen]int + var min, max int + for _, n := range bits { + if n == 0 { + continue + } + if min == 0 || n < min { + min = n + } + if n > max { + max = n + } + count[n]++ + } + + // Empty tree. The decompressor.huffSym function will fail later if the tree + // is used. Technically, an empty tree is only valid for the HDIST tree and + // not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree + // is guaranteed to fail since it will attempt to use the tree to decode the + // codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is + // guaranteed to fail later since the compressed data section must be + // composed of at least one symbol (the end-of-block marker). + if max == 0 { + return true + } + + code := 0 + var nextcode [maxCodeLen]int + for i := min; i <= max; i++ { + code <<= 1 + nextcode[i] = code + code += count[i] + } + + // Check that the coding is complete (i.e., that we've + // assigned all 2-to-the-max possible bit sequences). + // Exception: To be compatible with zlib, we also need to + // accept degenerate single-code codings. See also + // TestDegenerateHuffmanCoding. + if code != 1< huffmanChunkBits { + numLinks := 1 << (uint(max) - huffmanChunkBits) + h.linkMask = uint32(numLinks - 1) + + // create link tables + link := nextcode[huffmanChunkBits+1] >> 1 + h.links = make([][]uint32, huffmanNumChunks-link) + for j := uint(link); j < huffmanNumChunks; j++ { + reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8 + reverse >>= uint(16 - huffmanChunkBits) + off := j - uint(link) + if sanity && h.chunks[reverse] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[reverse] = uint32(off<>8]) | int(reverseByte[code&0xff])<<8 + reverse >>= uint(16 - n) + if n <= huffmanChunkBits { + for off := reverse; off < len(h.chunks); off += 1 << uint(n) { + // We should never need to overwrite + // an existing chunk. Also, 0 is + // never a valid chunk, because the + // lower 4 "count" bits should be + // between 1 and 15. + if sanity && h.chunks[off] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[off] = chunk + } + } else { + j := reverse & (huffmanNumChunks - 1) + if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 { + // Longer codes should have been + // associated with a link table above. + panic("impossible: not an indirect chunk") + } + value := h.chunks[j] >> huffmanValueShift + linktab := h.links[value] + reverse >>= huffmanChunkBits + for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) { + if sanity && linktab[off] != 0 { + panic("impossible: overwriting existing chunk") + } + linktab[off] = chunk + } + } + } + + if sanity { + // Above we've sanity checked that we never overwrote + // an existing entry. Here we additionally check that + // we filled the tables completely. + for i, chunk := range h.chunks { + if chunk == 0 { + // As an exception, in the degenerate + // single-code case, we allow odd + // chunks to be missing. + if code == 1 && i%2 == 1 { + continue + } + panic("impossible: missing chunk") + } + } + for _, linktab := range h.links { + for _, chunk := range linktab { + if chunk == 0 { + panic("impossible: missing chunk") + } + } + } + } + + return true +} + +// The actual read interface needed by NewReader. +// If the passed in io.Reader does not also have ReadByte, +// the NewReader will introduce its own buffering. +type Reader interface { + io.Reader + io.ByteReader +} + +// Decompress state. +type decompressor struct { + // Input source. + r Reader + roffset int64 + woffset int64 + + // Input bits, in top of b. + b uint32 + nb uint + + // Huffman decoders for literal/length, distance. + h1, h2 huffmanDecoder + + // Length arrays used to define Huffman codes. + bits *[maxNumLit + maxNumDist]int + codebits *[numCodes]int + + // Output history, buffer. + hist *[maxHist]byte + hp int // current output position in buffer + hw int // have written hist[0:hw] already + hfull bool // buffer has filled at least once + + // Temporary buffer (avoids repeated allocation). + buf [4]byte + + // Next step in the decompression, + // and decompression state. + step func(*decompressor) + final bool + err error + toRead []byte + hl, hd *huffmanDecoder + copyLen int + copyDist int +} + +func (f *decompressor) nextBlock() { + if f.final { + if f.hw != f.hp { + f.flush((*decompressor).nextBlock) + return + } + f.err = io.EOF + return + } + for f.nb < 1+2 { + if f.err = f.moreBits(); f.err != nil { + return + } + } + f.final = f.b&1 == 1 + f.b >>= 1 + typ := f.b & 3 + f.b >>= 2 + f.nb -= 1 + 2 + switch typ { + case 0: + f.dataBlock() + case 1: + // compressed, fixed Huffman tables + f.hl = &fixedHuffmanDecoder + f.hd = nil + f.huffmanBlock() + case 2: + // compressed, dynamic Huffman tables + if f.err = f.readHuffman(); f.err != nil { + break + } + f.hl = &f.h1 + f.hd = &f.h2 + f.huffmanBlock() + default: + // 3 is reserved. + f.err = CorruptInputError(f.roffset) + } +} + +func (f *decompressor) Read(b []byte) (int, error) { + for { + if len(f.toRead) > 0 { + n := copy(b, f.toRead) + f.toRead = f.toRead[n:] + return n, nil + } + if f.err != nil { + return 0, f.err + } + f.step(f) + } +} + +// Support the io.WriteTo interface for io.Copy and friends. +func (f *decompressor) WriteTo(w io.Writer) (int64, error) { + total := int64(0) + for { + if f.err != nil { + if f.err == io.EOF { + return total, nil + } + return total, f.err + } + if len(f.toRead) > 0 { + var n int + n, f.err = w.Write(f.toRead) + if f.err != nil { + return total, f.err + } + if n != len(f.toRead) { + return total, io.ErrShortWrite + } + f.toRead = f.toRead[:0] + total += int64(n) + } + f.step(f) + } +} + +func (f *decompressor) Close() error { + if f.err == io.EOF { + return nil + } + return f.err +} + +// RFC 1951 section 3.2.7. +// Compression with dynamic Huffman codes + +var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +func (f *decompressor) readHuffman() error { + // HLIT[5], HDIST[5], HCLEN[4]. + for f.nb < 5+5+4 { + if err := f.moreBits(); err != nil { + return err + } + } + nlit := int(f.b&0x1F) + 257 + if nlit > maxNumLit { + return CorruptInputError(f.roffset) + } + f.b >>= 5 + ndist := int(f.b&0x1F) + 1 + if ndist > maxNumDist { + return CorruptInputError(f.roffset) + } + f.b >>= 5 + nclen := int(f.b&0xF) + 4 + // numCodes is 19, so nclen is always valid. + f.b >>= 4 + f.nb -= 5 + 5 + 4 + + // (HCLEN+4)*3 bits: code lengths in the magic codeOrder order. + for i := 0; i < nclen; i++ { + for f.nb < 3 { + if err := f.moreBits(); err != nil { + return err + } + } + f.codebits[codeOrder[i]] = int(f.b & 0x7) + f.b >>= 3 + f.nb -= 3 + } + for i := nclen; i < len(codeOrder); i++ { + f.codebits[codeOrder[i]] = 0 + } + if !f.h1.init(f.codebits[0:]) { + return CorruptInputError(f.roffset) + } + + // HLIT + 257 code lengths, HDIST + 1 code lengths, + // using the code length Huffman code. + for i, n := 0, nlit+ndist; i < n; { + x, err := f.huffSym(&f.h1) + if err != nil { + return err + } + if x < 16 { + // Actual length. + f.bits[i] = x + i++ + continue + } + // Repeat previous length or zero. + var rep int + var nb uint + var b int + switch x { + default: + return InternalError("unexpected length code") + case 16: + rep = 3 + nb = 2 + if i == 0 { + return CorruptInputError(f.roffset) + } + b = f.bits[i-1] + case 17: + rep = 3 + nb = 3 + b = 0 + case 18: + rep = 11 + nb = 7 + b = 0 + } + for f.nb < nb { + if err := f.moreBits(); err != nil { + return err + } + } + rep += int(f.b & uint32(1<>= nb + f.nb -= nb + if i+rep > n { + return CorruptInputError(f.roffset) + } + for j := 0; j < rep; j++ { + f.bits[i] = b + i++ + } + } + + if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit:nlit+ndist]) { + return CorruptInputError(f.roffset) + } + + // In order to preserve the property that we never read any extra bytes + // after the end of the DEFLATE stream, huffSym conservatively reads min + // bits at a time until it decodes the symbol. However, since every block + // must end with an EOB marker, we can use that as the minimum number of + // bits to read and guarantee we never read past the end of the stream. + if f.bits[endBlockMarker] > 0 { + f.h1.min = f.bits[endBlockMarker] // Length of EOB marker + } + + return nil +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBlock() { + for { + v, err := f.huffSym(f.hl) + if err != nil { + f.err = err + return + } + var n uint // number of bits extra + var length int + switch { + case v < 256: + f.hist[f.hp] = byte(v) + f.hp++ + if f.hp == len(f.hist) { + // After the flush, continue this loop. + f.flush((*decompressor).huffmanBlock) + return + } + continue + case v == 256: + // Done with huffman block; read next block. + f.step = (*decompressor).nextBlock + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = f.moreBits(); err != nil { + f.err = err + return + } + } + length += int(f.b & uint32(1<>= n + f.nb -= n + } + + var dist int + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + f.err = err + return + } + } + dist = int(reverseByte[(f.b&0x1F)<<3]) + f.b >>= 5 + f.nb -= 5 + } else { + if dist, err = f.huffSym(f.hd); err != nil { + f.err = err + return + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << nb + for f.nb < nb { + if err = f.moreBits(); err != nil { + f.err = err + return + } + } + extra |= int(f.b & uint32(1<>= nb + f.nb -= nb + dist = 1<<(nb+1) + 1 + extra + default: + f.err = CorruptInputError(f.roffset) + return + } + + // Copy history[-dist:-dist+length] into output. + if dist > len(f.hist) { + f.err = InternalError("bad history distance") + return + } + + // No check on length; encoding can be prescient. + if !f.hfull && dist > f.hp { + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, dist + if f.copyHist() { + return + } + } +} + +// copyHist copies f.copyLen bytes from f.hist (f.copyDist bytes ago) to itself. +// It reports whether the f.hist buffer is full. +func (f *decompressor) copyHist() bool { + p := f.hp - f.copyDist + if p < 0 { + p += len(f.hist) + } + for f.copyLen > 0 { + n := f.copyLen + if x := len(f.hist) - f.hp; n > x { + n = x + } + if x := len(f.hist) - p; n > x { + n = x + } + forwardCopy(f.hist[:], f.hp, p, n) + p += n + f.hp += n + f.copyLen -= n + if f.hp == len(f.hist) { + // After flush continue copying out of history. + f.flush((*decompressor).copyHuff) + return true + } + if p == len(f.hist) { + p = 0 + } + } + return false +} + +func (f *decompressor) copyHuff() { + if f.copyHist() { + return + } + f.huffmanBlock() +} + +// Copy a single uncompressed data block from input to output. +func (f *decompressor) dataBlock() { + // Uncompressed. + // Discard current half-byte. + f.nb = 0 + f.b = 0 + + // Length then ones-complement of length. + nr, err := io.ReadFull(f.r, f.buf[0:4]) + f.roffset += int64(nr) + if err != nil { + f.err = &ReadError{f.roffset, err} + return + } + n := int(f.buf[0]) | int(f.buf[1])<<8 + nn := int(f.buf[2]) | int(f.buf[3])<<8 + if uint16(nn) != uint16(^n) { + f.err = CorruptInputError(f.roffset) + return + } + + if n == 0 { + // 0-length block means sync + f.flush((*decompressor).nextBlock) + return + } + + f.copyLen = n + f.copyData() +} + +// copyData copies f.copyLen bytes from the underlying reader into f.hist. +// It pauses for reads when f.hist is full. +func (f *decompressor) copyData() { + n := f.copyLen + for n > 0 { + m := len(f.hist) - f.hp + if m > n { + m = n + } + m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m]) + f.roffset += int64(m) + if err != nil { + f.err = &ReadError{f.roffset, err} + return + } + n -= m + f.hp += m + if f.hp == len(f.hist) { + f.copyLen = n + f.flush((*decompressor).copyData) + return + } + } + f.step = (*decompressor).nextBlock +} + +func (f *decompressor) setDict(dict []byte) { + if len(dict) > len(f.hist) { + // Will only remember the tail. + dict = dict[len(dict)-len(f.hist):] + } + + f.hp = copy(f.hist[:], dict) + if f.hp == len(f.hist) { + f.hp = 0 + f.hfull = true + } + f.hw = f.hp +} + +func (f *decompressor) moreBits() error { + c, err := f.r.ReadByte() + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return err + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil +} + +// Read the next Huffman-encoded symbol from f according to h. +func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(h.min) + for { + for f.nb < n { + if err := f.moreBits(); err != nil { + return 0, err + } + } + chunk := h.chunks[f.b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= f.nb { + if n == 0 { + f.err = CorruptInputError(f.roffset) + return 0, f.err + } + f.b >>= n + f.nb -= n + return int(chunk >> huffmanValueShift), nil + } + } +} + +// Flush any buffered output to the underlying writer. +func (f *decompressor) flush(step func(*decompressor)) { + f.toRead = f.hist[f.hw:f.hp] + f.woffset += int64(f.hp - f.hw) + f.hw = f.hp + if f.hp == len(f.hist) { + f.hp = 0 + f.hw = 0 + f.hfull = true + } + f.step = step +} + +func makeReader(r io.Reader) Reader { + if rr, ok := r.(Reader); ok { + return rr + } + return bufio.NewReader(r) +} + +func (f *decompressor) Reset(r io.Reader, dict []byte) error { + *f = decompressor{ + r: makeReader(r), + bits: f.bits, + codebits: f.codebits, + hist: f.hist, + step: (*decompressor).nextBlock, + } + if dict != nil { + f.setDict(dict) + } + return nil +} + +// NewReader returns a new ReadCloser that can be used +// to read the uncompressed version of r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser +// when finished reading. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReader(r io.Reader) io.ReadCloser { + var f decompressor + f.bits = new([maxNumLit + maxNumDist]int) + f.codebits = new([numCodes]int) + f.r = makeReader(r) + f.hist = new([maxHist]byte) + f.step = (*decompressor).nextBlock + return &f +} + +// NewReaderDict is like NewReader but initializes the reader +// with a preset dictionary. The returned Reader behaves as if +// the uncompressed data stream started with the given dictionary, +// which has already been read. NewReaderDict is typically used +// to read data compressed by NewWriterDict. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { + var f decompressor + f.r = makeReader(r) + f.hist = new([maxHist]byte) + f.bits = new([maxNumLit + maxNumDist]int) + f.codebits = new([numCodes]int) + f.step = (*decompressor).nextBlock + f.setDict(dict) + return &f +} diff --git a/vendor/github.com/klauspost/compress/flate/reverse_bits.go b/vendor/github.com/klauspost/compress/flate/reverse_bits.go new file mode 100644 index 000000000..c1a02720d --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/reverse_bits.go @@ -0,0 +1,48 @@ +// 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. + +package flate + +var reverseByte = [256]byte{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +} + +func reverseUint16(v uint16) uint16 { + return uint16(reverseByte[v>>8]) | uint16(reverseByte[v&0xFF])<<8 +} + +func reverseBits(number uint16, bitLength byte) uint16 { + return reverseUint16(number << uint8(16-bitLength)) +} diff --git a/vendor/github.com/klauspost/compress/flate/snappy.go b/vendor/github.com/klauspost/compress/flate/snappy.go new file mode 100644 index 000000000..f0513afaa --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/snappy.go @@ -0,0 +1,96 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Modified for deflate by Klaus Post (c) 2015. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +// We limit how far copy back-references can go, the same as the C++ code. +const maxOffset = 1 << 15 + +// emitLiteral writes a literal chunk and returns the number of bytes written. +func emitLiteral(dst *tokens, lit []byte) { + ol := dst.n + for i, v := range lit { + dst.tokens[i+ol] = token(v) + } + dst.n += len(lit) +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +func emitCopy(dst *tokens, offset, length int) { + dst.tokens[dst.n] = matchToken(uint32(length-3), uint32(offset-minOffsetSize)) + dst.n++ +} + +// snappyEncode uses Snappy-like compression, but stores as Huffman +// blocks. +func snappyEncode(dst *tokens, src []byte) { + // Return early if src is short. + if len(src) <= 4 { + if len(src) != 0 { + emitLiteral(dst, src) + } + return + } + + // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. + const maxTableSize = 1 << 14 + shift, tableSize := uint(32-8), 1<<8 + for tableSize < maxTableSize && tableSize < len(src) { + shift-- + tableSize *= 2 + } + var table [maxTableSize]int + + // Iterate over the source bytes. + var ( + s int // The iterator position. + t int // The last position with the same hash as s. + lit int // The start position of any pending literal bytes. + ) + + for s+3 < len(src) { + // Update the hash table. + b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3] + h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24 + p := &table[(h*0x1e35a7bd)>>shift] + // We need to to store values in [-1, inf) in table. To save + // some initialization time, (re)use the table's zero value + // and shift the values against this zero: add 1 on writes, + // subtract 1 on reads. + t, *p = *p-1, s+1 + // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte. + if t < 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] { + // Skip 1 byte for 16 consecutive missed. + s += 1 + ((s - lit) >> 4) + continue + } + // Otherwise, we have a match. First, emit any pending literal bytes. + if lit != s { + emitLiteral(dst, src[lit:s]) + } + // Extend the match to be as long as possible. + s0 := s + s1 := s + maxMatchLength + if s1 > len(src) { + s1 = len(src) + } + s, t = s+4, t+4 + for s < s1 && src[s] == src[t] { + s++ + t++ + } + // Emit the copied bytes. + // inlined: emitCopy(dst, s-t, s-s0) + + dst.tokens[dst.n] = matchToken(uint32(s-s0-3), uint32(s-t-minOffsetSize)) + dst.n++ + lit = s + } + + // Emit any final pending literal bytes and return. + if lit != len(src) { + emitLiteral(dst, src[lit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/token.go b/vendor/github.com/klauspost/compress/flate/token.go new file mode 100644 index 000000000..94fa5eb93 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/token.go @@ -0,0 +1,105 @@ +// 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. + +package flate + +const ( + // 2 bits: type 0 = literal 1=EOF 2=Match 3=Unused + // 8 bits: xlength = length - MIN_MATCH_LENGTH + // 22 bits xoffset = offset - MIN_OFFSET_SIZE, or literal + lengthShift = 22 + offsetMask = 1< pair into a match token. +func matchToken(xlength uint32, xoffset uint32) token { + return token(matchType + xlength<> lengthShift) } + +func lengthCode(len uint32) uint32 { return lengthCodes[len] } + +// Returns the offset code corresponding to a specific offset +func offsetCode(off uint32) uint32 { + if off < uint32(len(offsetCodes)) { + return offsetCodes[off] + } else if off>>7 < uint32(len(offsetCodes)) { + return offsetCodes[off>>7] + 14 + } else { + return offsetCodes[off>>14] + 28 + } +} diff --git a/vendor/github.com/klauspost/cpuid/.gitignore b/vendor/github.com/klauspost/cpuid/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/klauspost/cpuid/.travis.yml b/vendor/github.com/klauspost/cpuid/.travis.yml new file mode 100644 index 000000000..fb74de6b8 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip diff --git a/vendor/github.com/klauspost/cpuid/LICENSE b/vendor/github.com/klauspost/cpuid/LICENSE new file mode 100644 index 000000000..5cec7ee94 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Klaus Post + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/klauspost/cpuid/README.md b/vendor/github.com/klauspost/cpuid/README.md new file mode 100644 index 000000000..b2b6bee87 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/README.md @@ -0,0 +1,145 @@ +# cpuid +Package cpuid provides information about the CPU running the current program. + +CPU features are detected on startup, and kept for fast access through the life of the application. +Currently x86 / x64 (AMD64) is supported, and no external C (cgo) code is used, which should make the library very easy to use. + +You can access the CPU information by accessing the shared CPU variable of the cpuid library. + +Package home: https://github.com/klauspost/cpuid + +[![GoDoc][1]][2] [![Build Status][3]][4] + +[1]: https://godoc.org/github.com/klauspost/cpuid?status.svg +[2]: https://godoc.org/github.com/klauspost/cpuid +[3]: https://travis-ci.org/klauspost/cpuid.svg +[4]: https://travis-ci.org/klauspost/cpuid + +# features +## CPU Instructions +* **CMOV** (i686 CMOV) +* **NX** (NX (No-Execute) bit) +* **AMD3DNOW** (AMD 3DNOW) +* **AMD3DNOWEXT** (AMD 3DNowExt) +* **MMX** (standard MMX) +* **MMXEXT** (SSE integer functions or AMD MMX ext) +* **SSE** (SSE functions) +* **SSE2** (P4 SSE functions) +* **SSE3** (Prescott SSE3 functions) +* **SSSE3** (Conroe SSSE3 functions) +* **SSE4** (Penryn SSE4.1 functions) +* **SSE4A** (AMD Barcelona microarchitecture SSE4a instructions) +* **SSE42** (Nehalem SSE4.2 functions) +* **AVX** (AVX functions) +* **AVX2** (AVX2 functions) +* **FMA3** (Intel FMA 3) +* **FMA4** (Bulldozer FMA4 functions) +* **XOP** (Bulldozer XOP functions) +* **F16C** (Half-precision floating-point conversion) +* **BMI1** (Bit Manipulation Instruction Set 1) +* **BMI2** (Bit Manipulation Instruction Set 2) +* **TBM** (AMD Trailing Bit Manipulation) +* **LZCNT** (LZCNT instruction) +* **POPCNT** (POPCNT instruction) +* **AESNI** (Advanced Encryption Standard New Instructions) +* **CLMUL** (Carry-less Multiplication) +* **HTT** (Hyperthreading (enabled)) +* **HLE** (Hardware Lock Elision) +* **RTM** (Restricted Transactional Memory) +* **RDRAND** (RDRAND instruction is available) +* **RDSEED** (RDSEED instruction is available) +* **ADX** (Intel ADX (Multi-Precision Add-Carry Instruction Extensions)) +* **SHA** (Intel SHA Extensions) +* **AVX512F** (AVX-512 Foundation) +* **AVX512DQ** (AVX-512 Doubleword and Quadword Instructions) +* **AVX512IFMA** (AVX-512 Integer Fused Multiply-Add Instructions) +* **AVX512PF** (AVX-512 Prefetch Instructions) +* **AVX512ER** (AVX-512 Exponential and Reciprocal Instructions) +* **AVX512CD** (AVX-512 Conflict Detection Instructions) +* **AVX512BW** (AVX-512 Byte and Word Instructions) +* **AVX512VL** (AVX-512 Vector Length Extensions) +* **AVX512VBMI** (AVX-512 Vector Bit Manipulation Instructions) +* **MPX** (Intel MPX (Memory Protection Extensions)) +* **ERMS** (Enhanced REP MOVSB/STOSB) +* **RDTSCP** (RDTSCP Instruction) +* **CX16** (CMPXCHG16B Instruction) +* **SGX** (Software Guard Extensions, with activation details) + +## Performance +* **RDTSCP()** Returns current cycle count. Can be used for benchmarking. +* **SSE2SLOW** (SSE2 is supported, but usually not faster) +* **SSE3SLOW** (SSE3 is supported, but usually not faster) +* **ATOM** (Atom processor, some SSSE3 instructions are slower) +* **Cache line** (Probable size of a cache line). +* **L1, L2, L3 Cache size** on newer Intel/AMD CPUs. + +## Cpu Vendor/VM +* **Intel** +* **AMD** +* **VIA** +* **Transmeta** +* **NSC** +* **KVM** (Kernel-based Virtual Machine) +* **MSVM** (Microsoft Hyper-V or Windows Virtual PC) +* **VMware** +* **XenHVM** + +# installing + +```go get github.com/klauspost/cpuid``` + +# example + +```Go +package main + +import ( + "fmt" + "github.com/klauspost/cpuid" +) + +func main() { + // Print basic CPU information: + fmt.Println("Name:", cpuid.CPU.BrandName) + fmt.Println("PhysicalCores:", cpuid.CPU.PhysicalCores) + fmt.Println("ThreadsPerCore:", cpuid.CPU.ThreadsPerCore) + fmt.Println("LogicalCores:", cpuid.CPU.LogicalCores) + fmt.Println("Family", cpuid.CPU.Family, "Model:", cpuid.CPU.Model) + fmt.Println("Features:", cpuid.CPU.Features) + fmt.Println("Cacheline bytes:", cpuid.CPU.CacheLine) + fmt.Println("L1 Data Cache:", cpuid.CPU.Cache.L1D, "bytes") + fmt.Println("L1 Instruction Cache:", cpuid.CPU.Cache.L1D, "bytes") + fmt.Println("L2 Cache:", cpuid.CPU.Cache.L2, "bytes") + fmt.Println("L3 Cache:", cpuid.CPU.Cache.L3, "bytes") + + // Test if we have a specific feature: + if cpuid.CPU.SSE() { + fmt.Println("We have Streaming SIMD Extensions") + } +} +``` + +Sample output: +``` +>go run main.go +Name: Intel(R) Core(TM) i5-2540M CPU @ 2.60GHz +PhysicalCores: 2 +ThreadsPerCore: 2 +LogicalCores: 4 +Family 6 Model: 42 +Features: CMOV,MMX,MMXEXT,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,AVX,AESNI,CLMUL +Cacheline bytes: 64 +We have Streaming SIMD Extensions +``` + +# private package + +In the "private" folder you can find an autogenerated version of the library you can include in your own packages. + +For this purpose all exports are removed, and functions and constants are lowercased. + +This is not a recommended way of using the library, but provided for convenience, if it is difficult for you to use external packages. + +# license + +This code is published under an MIT license. See LICENSE file for more information. diff --git a/vendor/github.com/klauspost/cpuid/cpuid.go b/vendor/github.com/klauspost/cpuid/cpuid.go new file mode 100644 index 000000000..9230ca562 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/cpuid.go @@ -0,0 +1,1022 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// Package cpuid provides information about the CPU running the current program. +// +// CPU features are detected on startup, and kept for fast access through the life of the application. +// Currently x86 / x64 (AMD64) is supported. +// +// You can access the CPU information by accessing the shared CPU variable of the cpuid library. +// +// Package home: https://github.com/klauspost/cpuid +package cpuid + +import "strings" + +// Vendor is a representation of a CPU vendor. +type Vendor int + +const ( + Other Vendor = iota + Intel + AMD + VIA + Transmeta + NSC + KVM // Kernel-based Virtual Machine + MSVM // Microsoft Hyper-V or Windows Virtual PC + VMware + XenHVM +) + +const ( + CMOV = 1 << iota // i686 CMOV + NX // NX (No-Execute) bit + AMD3DNOW // AMD 3DNOW + AMD3DNOWEXT // AMD 3DNowExt + MMX // standard MMX + MMXEXT // SSE integer functions or AMD MMX ext + SSE // SSE functions + SSE2 // P4 SSE functions + SSE3 // Prescott SSE3 functions + SSSE3 // Conroe SSSE3 functions + SSE4 // Penryn SSE4.1 functions + SSE4A // AMD Barcelona microarchitecture SSE4a instructions + SSE42 // Nehalem SSE4.2 functions + AVX // AVX functions + AVX2 // AVX2 functions + FMA3 // Intel FMA 3 + FMA4 // Bulldozer FMA4 functions + XOP // Bulldozer XOP functions + F16C // Half-precision floating-point conversion + BMI1 // Bit Manipulation Instruction Set 1 + BMI2 // Bit Manipulation Instruction Set 2 + TBM // AMD Trailing Bit Manipulation + LZCNT // LZCNT instruction + POPCNT // POPCNT instruction + AESNI // Advanced Encryption Standard New Instructions + CLMUL // Carry-less Multiplication + HTT // Hyperthreading (enabled) + HLE // Hardware Lock Elision + RTM // Restricted Transactional Memory + RDRAND // RDRAND instruction is available + RDSEED // RDSEED instruction is available + ADX // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + SHA // Intel SHA Extensions + AVX512F // AVX-512 Foundation + AVX512DQ // AVX-512 Doubleword and Quadword Instructions + AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions + AVX512PF // AVX-512 Prefetch Instructions + AVX512ER // AVX-512 Exponential and Reciprocal Instructions + AVX512CD // AVX-512 Conflict Detection Instructions + AVX512BW // AVX-512 Byte and Word Instructions + AVX512VL // AVX-512 Vector Length Extensions + AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions + MPX // Intel MPX (Memory Protection Extensions) + ERMS // Enhanced REP MOVSB/STOSB + RDTSCP // RDTSCP Instruction + CX16 // CMPXCHG16B Instruction + SGX // Software Guard Extensions + + // Performance indicators + SSE2SLOW // SSE2 is supported, but usually not faster + SSE3SLOW // SSE3 is supported, but usually not faster + ATOM // Atom processor, some SSSE3 instructions are slower +) + +var flagNames = map[Flags]string{ + CMOV: "CMOV", // i686 CMOV + NX: "NX", // NX (No-Execute) bit + AMD3DNOW: "AMD3DNOW", // AMD 3DNOW + AMD3DNOWEXT: "AMD3DNOWEXT", // AMD 3DNowExt + MMX: "MMX", // Standard MMX + MMXEXT: "MMXEXT", // SSE integer functions or AMD MMX ext + SSE: "SSE", // SSE functions + SSE2: "SSE2", // P4 SSE2 functions + SSE3: "SSE3", // Prescott SSE3 functions + SSSE3: "SSSE3", // Conroe SSSE3 functions + SSE4: "SSE4.1", // Penryn SSE4.1 functions + SSE4A: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions + SSE42: "SSE4.2", // Nehalem SSE4.2 functions + AVX: "AVX", // AVX functions + AVX2: "AVX2", // AVX functions + FMA3: "FMA3", // Intel FMA 3 + FMA4: "FMA4", // Bulldozer FMA4 functions + XOP: "XOP", // Bulldozer XOP functions + F16C: "F16C", // Half-precision floating-point conversion + BMI1: "BMI1", // Bit Manipulation Instruction Set 1 + BMI2: "BMI2", // Bit Manipulation Instruction Set 2 + TBM: "TBM", // AMD Trailing Bit Manipulation + LZCNT: "LZCNT", // LZCNT instruction + POPCNT: "POPCNT", // POPCNT instruction + AESNI: "AESNI", // Advanced Encryption Standard New Instructions + CLMUL: "CLMUL", // Carry-less Multiplication + HTT: "HTT", // Hyperthreading (enabled) + HLE: "HLE", // Hardware Lock Elision + RTM: "RTM", // Restricted Transactional Memory + RDRAND: "RDRAND", // RDRAND instruction is available + RDSEED: "RDSEED", // RDSEED instruction is available + ADX: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + SHA: "SHA", // Intel SHA Extensions + AVX512F: "AVX512F", // AVX-512 Foundation + AVX512DQ: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions + AVX512IFMA: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions + AVX512PF: "AVX512PF", // AVX-512 Prefetch Instructions + AVX512ER: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions + AVX512CD: "AVX512CD", // AVX-512 Conflict Detection Instructions + AVX512BW: "AVX512BW", // AVX-512 Byte and Word Instructions + AVX512VL: "AVX512VL", // AVX-512 Vector Length Extensions + AVX512VBMI: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions + MPX: "MPX", // Intel MPX (Memory Protection Extensions) + ERMS: "ERMS", // Enhanced REP MOVSB/STOSB + RDTSCP: "RDTSCP", // RDTSCP Instruction + CX16: "CX16", // CMPXCHG16B Instruction + SGX: "SGX", // Software Guard Extensions + + // Performance indicators + SSE2SLOW: "SSE2SLOW", // SSE2 supported, but usually not faster + SSE3SLOW: "SSE3SLOW", // SSE3 supported, but usually not faster + ATOM: "ATOM", // Atom processor, some SSSE3 instructions are slower + +} + +// CPUInfo contains information about the detected system CPU. +type CPUInfo struct { + BrandName string // Brand name reported by the CPU + VendorID Vendor // Comparable CPU vendor ID + Features Flags // Features of the CPU + PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. + ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable. + LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. + Family int // CPU family number + Model int // CPU model number + CacheLine int // Cache line size in bytes. Will be 0 if undetectable. + Cache struct { + L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected + L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected + L2 int // L2 Cache (per core or shared). Will be -1 if undetected + L3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected + } + SGX SGXSupport + maxFunc uint32 + maxExFunc uint32 +} + +var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) +var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32) +var xgetbv func(index uint32) (eax, edx uint32) +var rdtscpAsm func() (eax, ebx, ecx, edx uint32) + +// CPU contains information about the CPU as detected on startup, +// or when Detect last was called. +// +// Use this as the primary entry point to you data, +// this way queries are +var CPU CPUInfo + +func init() { + initCPU() + Detect() +} + +// Detect will re-detect current CPU info. +// This will replace the content of the exported CPU variable. +// +// Unless you expect the CPU to change while you are running your program +// you should not need to call this function. +// If you call this, you must ensure that no other goroutine is accessing the +// exported CPU variable. +func Detect() { + CPU.maxFunc = maxFunctionID() + CPU.maxExFunc = maxExtendedFunction() + CPU.BrandName = brandName() + CPU.CacheLine = cacheLine() + CPU.Family, CPU.Model = familyModel() + CPU.Features = support() + CPU.SGX = sgx(CPU.Features&SGX != 0) + CPU.ThreadsPerCore = threadsPerCore() + CPU.LogicalCores = logicalCores() + CPU.PhysicalCores = physicalCores() + CPU.VendorID = vendorID() + CPU.cacheSize() +} + +// Generated here: http://play.golang.org/p/BxFH2Gdc0G + +// Cmov indicates support of CMOV instructions +func (c CPUInfo) Cmov() bool { + return c.Features&CMOV != 0 +} + +// Amd3dnow indicates support of AMD 3DNOW! instructions +func (c CPUInfo) Amd3dnow() bool { + return c.Features&AMD3DNOW != 0 +} + +// Amd3dnowExt indicates support of AMD 3DNOW! Extended instructions +func (c CPUInfo) Amd3dnowExt() bool { + return c.Features&AMD3DNOWEXT != 0 +} + +// MMX indicates support of MMX instructions +func (c CPUInfo) MMX() bool { + return c.Features&MMX != 0 +} + +// MMXExt indicates support of MMXEXT instructions +// (SSE integer functions or AMD MMX ext) +func (c CPUInfo) MMXExt() bool { + return c.Features&MMXEXT != 0 +} + +// SSE indicates support of SSE instructions +func (c CPUInfo) SSE() bool { + return c.Features&SSE != 0 +} + +// SSE2 indicates support of SSE 2 instructions +func (c CPUInfo) SSE2() bool { + return c.Features&SSE2 != 0 +} + +// SSE3 indicates support of SSE 3 instructions +func (c CPUInfo) SSE3() bool { + return c.Features&SSE3 != 0 +} + +// SSSE3 indicates support of SSSE 3 instructions +func (c CPUInfo) SSSE3() bool { + return c.Features&SSSE3 != 0 +} + +// SSE4 indicates support of SSE 4 (also called SSE 4.1) instructions +func (c CPUInfo) SSE4() bool { + return c.Features&SSE4 != 0 +} + +// SSE42 indicates support of SSE4.2 instructions +func (c CPUInfo) SSE42() bool { + return c.Features&SSE42 != 0 +} + +// AVX indicates support of AVX instructions +// and operating system support of AVX instructions +func (c CPUInfo) AVX() bool { + return c.Features&AVX != 0 +} + +// AVX2 indicates support of AVX2 instructions +func (c CPUInfo) AVX2() bool { + return c.Features&AVX2 != 0 +} + +// FMA3 indicates support of FMA3 instructions +func (c CPUInfo) FMA3() bool { + return c.Features&FMA3 != 0 +} + +// FMA4 indicates support of FMA4 instructions +func (c CPUInfo) FMA4() bool { + return c.Features&FMA4 != 0 +} + +// XOP indicates support of XOP instructions +func (c CPUInfo) XOP() bool { + return c.Features&XOP != 0 +} + +// F16C indicates support of F16C instructions +func (c CPUInfo) F16C() bool { + return c.Features&F16C != 0 +} + +// BMI1 indicates support of BMI1 instructions +func (c CPUInfo) BMI1() bool { + return c.Features&BMI1 != 0 +} + +// BMI2 indicates support of BMI2 instructions +func (c CPUInfo) BMI2() bool { + return c.Features&BMI2 != 0 +} + +// TBM indicates support of TBM instructions +// (AMD Trailing Bit Manipulation) +func (c CPUInfo) TBM() bool { + return c.Features&TBM != 0 +} + +// Lzcnt indicates support of LZCNT instruction +func (c CPUInfo) Lzcnt() bool { + return c.Features&LZCNT != 0 +} + +// Popcnt indicates support of POPCNT instruction +func (c CPUInfo) Popcnt() bool { + return c.Features&POPCNT != 0 +} + +// HTT indicates the processor has Hyperthreading enabled +func (c CPUInfo) HTT() bool { + return c.Features&HTT != 0 +} + +// SSE2Slow indicates that SSE2 may be slow on this processor +func (c CPUInfo) SSE2Slow() bool { + return c.Features&SSE2SLOW != 0 +} + +// SSE3Slow indicates that SSE3 may be slow on this processor +func (c CPUInfo) SSE3Slow() bool { + return c.Features&SSE3SLOW != 0 +} + +// AesNi indicates support of AES-NI instructions +// (Advanced Encryption Standard New Instructions) +func (c CPUInfo) AesNi() bool { + return c.Features&AESNI != 0 +} + +// Clmul indicates support of CLMUL instructions +// (Carry-less Multiplication) +func (c CPUInfo) Clmul() bool { + return c.Features&CLMUL != 0 +} + +// NX indicates support of NX (No-Execute) bit +func (c CPUInfo) NX() bool { + return c.Features&NX != 0 +} + +// SSE4A indicates support of AMD Barcelona microarchitecture SSE4a instructions +func (c CPUInfo) SSE4A() bool { + return c.Features&SSE4A != 0 +} + +// HLE indicates support of Hardware Lock Elision +func (c CPUInfo) HLE() bool { + return c.Features&HLE != 0 +} + +// RTM indicates support of Restricted Transactional Memory +func (c CPUInfo) RTM() bool { + return c.Features&RTM != 0 +} + +// Rdrand indicates support of RDRAND instruction is available +func (c CPUInfo) Rdrand() bool { + return c.Features&RDRAND != 0 +} + +// Rdseed indicates support of RDSEED instruction is available +func (c CPUInfo) Rdseed() bool { + return c.Features&RDSEED != 0 +} + +// ADX indicates support of Intel ADX (Multi-Precision Add-Carry Instruction Extensions) +func (c CPUInfo) ADX() bool { + return c.Features&ADX != 0 +} + +// SHA indicates support of Intel SHA Extensions +func (c CPUInfo) SHA() bool { + return c.Features&SHA != 0 +} + +// AVX512F indicates support of AVX-512 Foundation +func (c CPUInfo) AVX512F() bool { + return c.Features&AVX512F != 0 +} + +// AVX512DQ indicates support of AVX-512 Doubleword and Quadword Instructions +func (c CPUInfo) AVX512DQ() bool { + return c.Features&AVX512DQ != 0 +} + +// AVX512IFMA indicates support of AVX-512 Integer Fused Multiply-Add Instructions +func (c CPUInfo) AVX512IFMA() bool { + return c.Features&AVX512IFMA != 0 +} + +// AVX512PF indicates support of AVX-512 Prefetch Instructions +func (c CPUInfo) AVX512PF() bool { + return c.Features&AVX512PF != 0 +} + +// AVX512ER indicates support of AVX-512 Exponential and Reciprocal Instructions +func (c CPUInfo) AVX512ER() bool { + return c.Features&AVX512ER != 0 +} + +// AVX512CD indicates support of AVX-512 Conflict Detection Instructions +func (c CPUInfo) AVX512CD() bool { + return c.Features&AVX512CD != 0 +} + +// AVX512BW indicates support of AVX-512 Byte and Word Instructions +func (c CPUInfo) AVX512BW() bool { + return c.Features&AVX512BW != 0 +} + +// AVX512VL indicates support of AVX-512 Vector Length Extensions +func (c CPUInfo) AVX512VL() bool { + return c.Features&AVX512VL != 0 +} + +// AVX512VBMI indicates support of AVX-512 Vector Bit Manipulation Instructions +func (c CPUInfo) AVX512VBMI() bool { + return c.Features&AVX512VBMI != 0 +} + +// MPX indicates support of Intel MPX (Memory Protection Extensions) +func (c CPUInfo) MPX() bool { + return c.Features&MPX != 0 +} + +// ERMS indicates support of Enhanced REP MOVSB/STOSB +func (c CPUInfo) ERMS() bool { + return c.Features&ERMS != 0 +} + +func (c CPUInfo) RDTSCP() bool { + return c.Features&RDTSCP != 0 +} + +func (c CPUInfo) CX16() bool { + return c.Features&CX16 != 0 +} + +// Atom indicates an Atom processor +func (c CPUInfo) Atom() bool { + return c.Features&ATOM != 0 +} + +// Intel returns true if vendor is recognized as Intel +func (c CPUInfo) Intel() bool { + return c.VendorID == Intel +} + +// AMD returns true if vendor is recognized as AMD +func (c CPUInfo) AMD() bool { + return c.VendorID == AMD +} + +// Transmeta returns true if vendor is recognized as Transmeta +func (c CPUInfo) Transmeta() bool { + return c.VendorID == Transmeta +} + +// NSC returns true if vendor is recognized as National Semiconductor +func (c CPUInfo) NSC() bool { + return c.VendorID == NSC +} + +// VIA returns true if vendor is recognized as VIA +func (c CPUInfo) VIA() bool { + return c.VendorID == VIA +} + +// RTCounter returns the 64-bit time-stamp counter +// Uses the RDTSCP instruction. The value 0 is returned +// if the CPU does not support the instruction. +func (c CPUInfo) RTCounter() uint64 { + if !c.RDTSCP() { + return 0 + } + a, _, _, d := rdtscpAsm() + return uint64(a) | (uint64(d) << 32) +} + +// Ia32TscAux returns the IA32_TSC_AUX part of the RDTSCP. +// This variable is OS dependent, but on Linux contains information +// about the current cpu/core the code is running on. +// If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned. +func (c CPUInfo) Ia32TscAux() uint32 { + if !c.RDTSCP() { + return 0 + } + _, _, ecx, _ := rdtscpAsm() + return ecx +} + +// LogicalCPU will return the Logical CPU the code is currently executing on. +// This is likely to change when the OS re-schedules the running thread +// to another CPU. +// If the current core cannot be detected, -1 will be returned. +func (c CPUInfo) LogicalCPU() int { + if c.maxFunc < 1 { + return -1 + } + _, ebx, _, _ := cpuid(1) + return int(ebx >> 24) +} + +// VM Will return true if the cpu id indicates we are in +// a virtual machine. This is only a hint, and will very likely +// have many false negatives. +func (c CPUInfo) VM() bool { + switch c.VendorID { + case MSVM, KVM, VMware, XenHVM: + return true + } + return false +} + +// Flags contains detected cpu features and caracteristics +type Flags uint64 + +// String returns a string representation of the detected +// CPU features. +func (f Flags) String() string { + return strings.Join(f.Strings(), ",") +} + +// Strings returns and array of the detected features. +func (f Flags) Strings() []string { + s := support() + r := make([]string, 0, 20) + for i := uint(0); i < 64; i++ { + key := Flags(1 << i) + val := flagNames[key] + if s&key != 0 { + r = append(r, val) + } + } + return r +} + +func maxExtendedFunction() uint32 { + eax, _, _, _ := cpuid(0x80000000) + return eax +} + +func maxFunctionID() uint32 { + a, _, _, _ := cpuid(0) + return a +} + +func brandName() string { + if maxExtendedFunction() >= 0x80000004 { + v := make([]uint32, 0, 48) + for i := uint32(0); i < 3; i++ { + a, b, c, d := cpuid(0x80000002 + i) + v = append(v, a, b, c, d) + } + return strings.Trim(string(valAsString(v...)), " ") + } + return "unknown" +} + +func threadsPerCore() int { + mfi := maxFunctionID() + if mfi < 0x4 || vendorID() != Intel { + return 1 + } + + if mfi < 0xb { + _, b, _, d := cpuid(1) + if (d & (1 << 28)) != 0 { + // v will contain logical core count + v := (b >> 16) & 255 + if v > 1 { + a4, _, _, _ := cpuid(4) + // physical cores + v2 := (a4 >> 26) + 1 + if v2 > 0 { + return int(v) / int(v2) + } + } + } + return 1 + } + _, b, _, _ := cpuidex(0xb, 0) + if b&0xffff == 0 { + return 1 + } + return int(b & 0xffff) +} + +func logicalCores() int { + mfi := maxFunctionID() + switch vendorID() { + case Intel: + // Use this on old Intel processors + if mfi < 0xb { + if mfi < 1 { + return 0 + } + // CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial APIC ID) + // that can be assigned to logical processors in a physical package. + // The value may not be the same as the number of logical processors that are present in the hardware of a physical package. + _, ebx, _, _ := cpuid(1) + logical := (ebx >> 16) & 0xff + return int(logical) + } + _, b, _, _ := cpuidex(0xb, 1) + return int(b & 0xffff) + case AMD: + _, b, _, _ := cpuid(1) + return int((b >> 16) & 0xff) + default: + return 0 + } +} + +func familyModel() (int, int) { + if maxFunctionID() < 0x1 { + return 0, 0 + } + eax, _, _, _ := cpuid(1) + family := ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff) + model := ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0) + return int(family), int(model) +} + +func physicalCores() int { + switch vendorID() { + case Intel: + return logicalCores() / threadsPerCore() + case AMD: + if maxExtendedFunction() >= 0x80000008 { + _, _, c, _ := cpuid(0x80000008) + return int(c&0xff) + 1 + } + } + return 0 +} + +// Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID +var vendorMapping = map[string]Vendor{ + "AMDisbetter!": AMD, + "AuthenticAMD": AMD, + "CentaurHauls": VIA, + "GenuineIntel": Intel, + "TransmetaCPU": Transmeta, + "GenuineTMx86": Transmeta, + "Geode by NSC": NSC, + "VIA VIA VIA ": VIA, + "KVMKVMKVMKVM": KVM, + "Microsoft Hv": MSVM, + "VMwareVMware": VMware, + "XenVMMXenVMM": XenHVM, +} + +func vendorID() Vendor { + _, b, c, d := cpuid(0) + v := valAsString(b, d, c) + vend, ok := vendorMapping[string(v)] + if !ok { + return Other + } + return vend +} + +func cacheLine() int { + if maxFunctionID() < 0x1 { + return 0 + } + + _, ebx, _, _ := cpuid(1) + cache := (ebx & 0xff00) >> 5 // cflush size + if cache == 0 && maxExtendedFunction() >= 0x80000006 { + _, _, ecx, _ := cpuid(0x80000006) + cache = ecx & 0xff // cacheline size + } + // TODO: Read from Cache and TLB Information + return int(cache) +} + +func (c *CPUInfo) cacheSize() { + c.Cache.L1D = -1 + c.Cache.L1I = -1 + c.Cache.L2 = -1 + c.Cache.L3 = -1 + vendor := vendorID() + switch vendor { + case Intel: + if maxFunctionID() < 4 { + return + } + for i := uint32(0); ; i++ { + eax, ebx, ecx, _ := cpuidex(4, i) + cacheType := eax & 15 + if cacheType == 0 { + break + } + cacheLevel := (eax >> 5) & 7 + coherency := int(ebx&0xfff) + 1 + partitions := int((ebx>>12)&0x3ff) + 1 + associativity := int((ebx>>22)&0x3ff) + 1 + sets := int(ecx) + 1 + size := associativity * partitions * coherency * sets + switch cacheLevel { + case 1: + if cacheType == 1 { + // 1 = Data Cache + c.Cache.L1D = size + } else if cacheType == 2 { + // 2 = Instruction Cache + c.Cache.L1I = size + } else { + if c.Cache.L1D < 0 { + c.Cache.L1I = size + } + if c.Cache.L1I < 0 { + c.Cache.L1I = size + } + } + case 2: + c.Cache.L2 = size + case 3: + c.Cache.L3 = size + } + } + case AMD: + // Untested. + if maxExtendedFunction() < 0x80000005 { + return + } + _, _, ecx, edx := cpuid(0x80000005) + c.Cache.L1D = int(((ecx >> 24) & 0xFF) * 1024) + c.Cache.L1I = int(((edx >> 24) & 0xFF) * 1024) + + if maxExtendedFunction() < 0x80000006 { + return + } + _, _, ecx, _ = cpuid(0x80000006) + c.Cache.L2 = int(((ecx >> 16) & 0xFFFF) * 1024) + } + + return +} + +type SGXSupport struct { + Available bool + SGX1Supported bool + SGX2Supported bool + MaxEnclaveSizeNot64 int64 + MaxEnclaveSize64 int64 +} + +func sgx(available bool) (rval SGXSupport) { + rval.Available = available + + if !available { + return + } + + a, _, _, d := cpuidex(0x12, 0) + rval.SGX1Supported = a&0x01 != 0 + rval.SGX2Supported = a&0x02 != 0 + rval.MaxEnclaveSizeNot64 = 1 << (d & 0xFF) // pow 2 + rval.MaxEnclaveSize64 = 1 << ((d >> 8) & 0xFF) // pow 2 + + return +} + +func support() Flags { + mfi := maxFunctionID() + vend := vendorID() + if mfi < 0x1 { + return 0 + } + rval := uint64(0) + _, _, c, d := cpuid(1) + if (d & (1 << 15)) != 0 { + rval |= CMOV + } + if (d & (1 << 23)) != 0 { + rval |= MMX + } + if (d & (1 << 25)) != 0 { + rval |= MMXEXT + } + if (d & (1 << 25)) != 0 { + rval |= SSE + } + if (d & (1 << 26)) != 0 { + rval |= SSE2 + } + if (c & 1) != 0 { + rval |= SSE3 + } + if (c & 0x00000200) != 0 { + rval |= SSSE3 + } + if (c & 0x00080000) != 0 { + rval |= SSE4 + } + if (c & 0x00100000) != 0 { + rval |= SSE42 + } + if (c & (1 << 25)) != 0 { + rval |= AESNI + } + if (c & (1 << 1)) != 0 { + rval |= CLMUL + } + if c&(1<<23) != 0 { + rval |= POPCNT + } + if c&(1<<30) != 0 { + rval |= RDRAND + } + if c&(1<<29) != 0 { + rval |= F16C + } + if c&(1<<13) != 0 { + rval |= CX16 + } + if vend == Intel && (d&(1<<28)) != 0 && mfi >= 4 { + if threadsPerCore() > 1 { + rval |= HTT + } + } + + // Check XGETBV, OXSAVE and AVX bits + if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 { + // Check for OS support + eax, _ := xgetbv(0) + if (eax & 0x6) == 0x6 { + rval |= AVX + if (c & 0x00001000) != 0 { + rval |= FMA3 + } + } + } + + // Check AVX2, AVX2 requires OS support, but BMI1/2 don't. + if mfi >= 7 { + _, ebx, ecx, _ := cpuidex(7, 0) + if (rval&AVX) != 0 && (ebx&0x00000020) != 0 { + rval |= AVX2 + } + if (ebx & 0x00000008) != 0 { + rval |= BMI1 + if (ebx & 0x00000100) != 0 { + rval |= BMI2 + } + } + if ebx&(1<<2) != 0 { + rval |= SGX + } + if ebx&(1<<4) != 0 { + rval |= HLE + } + if ebx&(1<<9) != 0 { + rval |= ERMS + } + if ebx&(1<<11) != 0 { + rval |= RTM + } + if ebx&(1<<14) != 0 { + rval |= MPX + } + if ebx&(1<<18) != 0 { + rval |= RDSEED + } + if ebx&(1<<19) != 0 { + rval |= ADX + } + if ebx&(1<<29) != 0 { + rval |= SHA + } + + // Only detect AVX-512 features if XGETBV is supported + if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) { + // Check for OS support + eax, _ := xgetbv(0) + + // Verify that XCR0[7:5] = ‘111b’ (OPMASK state, upper 256-bit of ZMM0-ZMM15 and + // ZMM16-ZMM31 state are enabled by OS) + /// and that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS). + if (eax>>5)&7 == 7 && (eax>>1)&3 == 3 { + if ebx&(1<<16) != 0 { + rval |= AVX512F + } + if ebx&(1<<17) != 0 { + rval |= AVX512DQ + } + if ebx&(1<<21) != 0 { + rval |= AVX512IFMA + } + if ebx&(1<<26) != 0 { + rval |= AVX512PF + } + if ebx&(1<<27) != 0 { + rval |= AVX512ER + } + if ebx&(1<<28) != 0 { + rval |= AVX512CD + } + if ebx&(1<<30) != 0 { + rval |= AVX512BW + } + if ebx&(1<<31) != 0 { + rval |= AVX512VL + } + // ecx + if ecx&(1<<1) != 0 { + rval |= AVX512VBMI + } + } + } + } + + if maxExtendedFunction() >= 0x80000001 { + _, _, c, d := cpuid(0x80000001) + if (c & (1 << 5)) != 0 { + rval |= LZCNT + rval |= POPCNT + } + if (d & (1 << 31)) != 0 { + rval |= AMD3DNOW + } + if (d & (1 << 30)) != 0 { + rval |= AMD3DNOWEXT + } + if (d & (1 << 23)) != 0 { + rval |= MMX + } + if (d & (1 << 22)) != 0 { + rval |= MMXEXT + } + if (c & (1 << 6)) != 0 { + rval |= SSE4A + } + if d&(1<<20) != 0 { + rval |= NX + } + if d&(1<<27) != 0 { + rval |= RDTSCP + } + + /* Allow for selectively disabling SSE2 functions on AMD processors + with SSE2 support but not SSE4a. This includes Athlon64, some + Opteron, and some Sempron processors. MMX, SSE, or 3DNow! are faster + than SSE2 often enough to utilize this special-case flag. + AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case + so that SSE2 is used unless explicitly disabled by checking + AV_CPU_FLAG_SSE2SLOW. */ + if vendorID() != Intel && + rval&SSE2 != 0 && (c&0x00000040) == 0 { + rval |= SSE2SLOW + } + + /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be + * used unless the OS has AVX support. */ + if (rval & AVX) != 0 { + if (c & 0x00000800) != 0 { + rval |= XOP + } + if (c & 0x00010000) != 0 { + rval |= FMA4 + } + } + + if vendorID() == Intel { + family, model := familyModel() + if family == 6 && (model == 9 || model == 13 || model == 14) { + /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and + * 6/14 (core1 "yonah") theoretically support sse2, but it's + * usually slower than mmx. */ + if (rval & SSE2) != 0 { + rval |= SSE2SLOW + } + if (rval & SSE3) != 0 { + rval |= SSE3SLOW + } + } + /* The Atom processor has SSSE3 support, which is useful in many cases, + * but sometimes the SSSE3 version is slower than the SSE2 equivalent + * on the Atom, but is generally faster on other processors supporting + * SSSE3. This flag allows for selectively disabling certain SSSE3 + * functions on the Atom. */ + if family == 6 && model == 28 { + rval |= ATOM + } + } + } + return Flags(rval) +} + +func valAsString(values ...uint32) []byte { + r := make([]byte, 4*len(values)) + for i, v := range values { + dst := r[i*4:] + dst[0] = byte(v & 0xff) + dst[1] = byte((v >> 8) & 0xff) + dst[2] = byte((v >> 16) & 0xff) + dst[3] = byte((v >> 24) & 0xff) + switch { + case dst[0] == 0: + return r[:i*4] + case dst[1] == 0: + return r[:i*4+1] + case dst[2] == 0: + return r[:i*4+2] + case dst[3] == 0: + return r[:i*4+3] + } + } + return r +} diff --git a/vendor/github.com/klauspost/cpuid/cpuid_386.s b/vendor/github.com/klauspost/cpuid/cpuid_386.s new file mode 100644 index 000000000..9947f7b6f --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/cpuid_386.s @@ -0,0 +1,40 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuid(SB), 7, $0 + XORL CX, CX + MOVL op+0(FP), AX + CPUID + MOVL AX, eax+4(FP) + MOVL BX, ebx+8(FP) + MOVL CX, ecx+12(FP) + MOVL DX, edx+16(FP) + RET + +// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuidex(SB), 7, $0 + MOVL op+0(FP), AX + MOVL op2+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func xgetbv(index uint32) (eax, edx uint32) +TEXT ·asmXgetbv(SB), 7, $0 + MOVL index+0(FP), CX + BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV + MOVL AX, eax+4(FP) + MOVL DX, edx+8(FP) + RET + +// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) +TEXT ·asmRdtscpAsm(SB), 7, $0 + BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP + MOVL AX, eax+0(FP) + MOVL BX, ebx+4(FP) + MOVL CX, ecx+8(FP) + MOVL DX, edx+12(FP) + RET diff --git a/vendor/github.com/klauspost/cpuid/cpuid_amd64.s b/vendor/github.com/klauspost/cpuid/cpuid_amd64.s new file mode 100644 index 000000000..68a7c9d88 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/cpuid_amd64.s @@ -0,0 +1,40 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuid(SB), 7, $0 + XORQ CX, CX + MOVL op+0(FP), AX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuidex(SB), 7, $0 + MOVL op+0(FP), AX + MOVL op2+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func asmXgetbv(index uint32) (eax, edx uint32) +TEXT ·asmXgetbv(SB), 7, $0 + MOVL index+0(FP), CX + BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV + MOVL AX, eax+8(FP) + MOVL DX, edx+12(FP) + RET + +// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) +TEXT ·asmRdtscpAsm(SB), 7, $0 + BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP + MOVL AX, eax+0(FP) + MOVL BX, ebx+4(FP) + MOVL CX, ecx+8(FP) + MOVL DX, edx+12(FP) + RET diff --git a/vendor/github.com/klauspost/cpuid/detect_intel.go b/vendor/github.com/klauspost/cpuid/detect_intel.go new file mode 100644 index 000000000..d5475ebfa --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/detect_intel.go @@ -0,0 +1,17 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// +build 386 amd64 + +package cpuid + +func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +func asmXgetbv(index uint32) (eax, edx uint32) +func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) + +func initCPU() { + cpuid = asmCpuid + cpuidex = asmCpuidex + xgetbv = asmXgetbv + rdtscpAsm = asmRdtscpAsm +} diff --git a/vendor/github.com/klauspost/cpuid/detect_ref.go b/vendor/github.com/klauspost/cpuid/detect_ref.go new file mode 100644 index 000000000..6f9231b13 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/detect_ref.go @@ -0,0 +1,23 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// +build !amd64,!386 + +package cpuid + +func initCPU() { + cpuid = func(op uint32) (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } + + cpuidex = func(op, op2 uint32) (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } + + xgetbv = func(index uint32) (eax, edx uint32) { + return 0, 0 + } + + rdtscpAsm = func() (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } +} diff --git a/vendor/github.com/klauspost/cpuid/generate.go b/vendor/github.com/klauspost/cpuid/generate.go new file mode 100644 index 000000000..c060b8165 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/generate.go @@ -0,0 +1,3 @@ +package cpuid + +//go:generate go run private-gen.go diff --git a/vendor/github.com/klauspost/cpuid/private-gen.go b/vendor/github.com/klauspost/cpuid/private-gen.go new file mode 100644 index 000000000..437333d29 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private-gen.go @@ -0,0 +1,476 @@ +// +build ignore + +package main + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/token" + "io" + "io/ioutil" + "log" + "os" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +var inFiles = []string{"cpuid.go", "cpuid_test.go"} +var copyFiles = []string{"cpuid_amd64.s", "cpuid_386.s", "detect_ref.go", "detect_intel.go"} +var fileSet = token.NewFileSet() +var reWrites = []rewrite{ + initRewrite("CPUInfo -> cpuInfo"), + initRewrite("Vendor -> vendor"), + initRewrite("Flags -> flags"), + initRewrite("Detect -> detect"), + initRewrite("CPU -> cpu"), +} +var excludeNames = map[string]bool{"string": true, "join": true, "trim": true, + // cpuid_test.go + "t": true, "println": true, "logf": true, "log": true, "fatalf": true, "fatal": true, +} + +var excludePrefixes = []string{"test", "benchmark"} + +func main() { + Package := "private" + parserMode := parser.ParseComments + exported := make(map[string]rewrite) + for _, file := range inFiles { + in, err := os.Open(file) + if err != nil { + log.Fatalf("opening input", err) + } + + src, err := ioutil.ReadAll(in) + if err != nil { + log.Fatalf("reading input", err) + } + + astfile, err := parser.ParseFile(fileSet, file, src, parserMode) + if err != nil { + log.Fatalf("parsing input", err) + } + + for _, rw := range reWrites { + astfile = rw(astfile) + } + + // Inspect the AST and print all identifiers and literals. + var startDecl token.Pos + var endDecl token.Pos + ast.Inspect(astfile, func(n ast.Node) bool { + var s string + switch x := n.(type) { + case *ast.Ident: + if x.IsExported() { + t := strings.ToLower(x.Name) + for _, pre := range excludePrefixes { + if strings.HasPrefix(t, pre) { + return true + } + } + if excludeNames[t] != true { + //if x.Pos() > startDecl && x.Pos() < endDecl { + exported[x.Name] = initRewrite(x.Name + " -> " + t) + } + } + + case *ast.GenDecl: + if x.Tok == token.CONST && x.Lparen > 0 { + startDecl = x.Lparen + endDecl = x.Rparen + // fmt.Printf("Decl:%s -> %s\n", fileSet.Position(startDecl), fileSet.Position(endDecl)) + } + } + if s != "" { + fmt.Printf("%s:\t%s\n", fileSet.Position(n.Pos()), s) + } + return true + }) + + for _, rw := range exported { + astfile = rw(astfile) + } + + var buf bytes.Buffer + + printer.Fprint(&buf, fileSet, astfile) + + // Remove package documentation and insert information + s := buf.String() + ind := strings.Index(buf.String(), "\npackage cpuid") + s = s[ind:] + s = "// Generated, DO NOT EDIT,\n" + + "// but copy it to your own project and rename the package.\n" + + "// See more at http://github.com/klauspost/cpuid\n" + + s + + outputName := Package + string(os.PathSeparator) + file + + err = ioutil.WriteFile(outputName, []byte(s), 0644) + if err != nil { + log.Fatalf("writing output: %s", err) + } + log.Println("Generated", outputName) + } + + for _, file := range copyFiles { + dst := "" + if strings.HasPrefix(file, "cpuid") { + dst = Package + string(os.PathSeparator) + file + } else { + dst = Package + string(os.PathSeparator) + "cpuid_" + file + } + err := copyFile(file, dst) + if err != nil { + log.Fatalf("copying file: %s", err) + } + log.Println("Copied", dst) + } +} + +// CopyFile copies a file from src to dst. If src and dst files exist, and are +// the same, then return success. Copy the file contents from src to dst. +func copyFile(src, dst string) (err error) { + sfi, err := os.Stat(src) + if err != nil { + return + } + if !sfi.Mode().IsRegular() { + // cannot copy non-regular files (e.g., directories, + // symlinks, devices, etc.) + return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String()) + } + dfi, err := os.Stat(dst) + if err != nil { + if !os.IsNotExist(err) { + return + } + } else { + if !(dfi.Mode().IsRegular()) { + return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String()) + } + if os.SameFile(sfi, dfi) { + return + } + } + err = copyFileContents(src, dst) + return +} + +// copyFileContents copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all it's contents will be replaced by the contents +// of the source file. +func copyFileContents(src, dst string) (err error) { + in, err := os.Open(src) + if err != nil { + return + } + defer in.Close() + out, err := os.Create(dst) + if err != nil { + return + } + defer func() { + cerr := out.Close() + if err == nil { + err = cerr + } + }() + if _, err = io.Copy(out, in); err != nil { + return + } + err = out.Sync() + return +} + +type rewrite func(*ast.File) *ast.File + +// Mostly copied from gofmt +func initRewrite(rewriteRule string) rewrite { + f := strings.Split(rewriteRule, "->") + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n") + os.Exit(2) + } + pattern := parseExpr(f[0], "pattern") + replace := parseExpr(f[1], "replacement") + return func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) } +} + +// parseExpr parses s as an expression. +// It might make sense to expand this to allow statement patterns, +// but there are problems with preserving formatting and also +// with what a wildcard for a statement looks like. +func parseExpr(s, what string) ast.Expr { + x, err := parser.ParseExpr(s) + if err != nil { + fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err) + os.Exit(2) + } + return x +} + +// Keep this function for debugging. +/* +func dump(msg string, val reflect.Value) { + fmt.Printf("%s:\n", msg) + ast.Print(fileSet, val.Interface()) + fmt.Println() +} +*/ + +// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file. +func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { + cmap := ast.NewCommentMap(fileSet, p, p.Comments) + m := make(map[string]reflect.Value) + pat := reflect.ValueOf(pattern) + repl := reflect.ValueOf(replace) + + var rewriteVal func(val reflect.Value) reflect.Value + rewriteVal = func(val reflect.Value) reflect.Value { + // don't bother if val is invalid to start with + if !val.IsValid() { + return reflect.Value{} + } + for k := range m { + delete(m, k) + } + val = apply(rewriteVal, val) + if match(m, pat, val) { + val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos())) + } + return val + } + + r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File) + r.Comments = cmap.Filter(r).Comments() // recreate comments list + return r +} + +// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y. +func set(x, y reflect.Value) { + // don't bother if x cannot be set or y is invalid + if !x.CanSet() || !y.IsValid() { + return + } + defer func() { + if x := recover(); x != nil { + if s, ok := x.(string); ok && + (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) { + // x cannot be set to y - ignore this rewrite + return + } + panic(x) + } + }() + x.Set(y) +} + +// Values/types for special cases. +var ( + objectPtrNil = reflect.ValueOf((*ast.Object)(nil)) + scopePtrNil = reflect.ValueOf((*ast.Scope)(nil)) + + identType = reflect.TypeOf((*ast.Ident)(nil)) + objectPtrType = reflect.TypeOf((*ast.Object)(nil)) + positionType = reflect.TypeOf(token.NoPos) + callExprType = reflect.TypeOf((*ast.CallExpr)(nil)) + scopePtrType = reflect.TypeOf((*ast.Scope)(nil)) +) + +// apply replaces each AST field x in val with f(x), returning val. +// To avoid extra conversions, f operates on the reflect.Value form. +func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value { + if !val.IsValid() { + return reflect.Value{} + } + + // *ast.Objects introduce cycles and are likely incorrect after + // rewrite; don't follow them but replace with nil instead + if val.Type() == objectPtrType { + return objectPtrNil + } + + // similarly for scopes: they are likely incorrect after a rewrite; + // replace them with nil + if val.Type() == scopePtrType { + return scopePtrNil + } + + switch v := reflect.Indirect(val); v.Kind() { + case reflect.Slice: + for i := 0; i < v.Len(); i++ { + e := v.Index(i) + set(e, f(e)) + } + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + e := v.Field(i) + set(e, f(e)) + } + case reflect.Interface: + e := v.Elem() + set(v, f(e)) + } + return val +} + +func isWildcard(s string) bool { + rune, size := utf8.DecodeRuneInString(s) + return size == len(s) && unicode.IsLower(rune) +} + +// match returns true if pattern matches val, +// recording wildcard submatches in m. +// If m == nil, match checks whether pattern == val. +func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { + // Wildcard matches any expression. If it appears multiple + // times in the pattern, it must match the same expression + // each time. + if m != nil && pattern.IsValid() && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) && val.IsValid() { + // wildcards only match valid (non-nil) expressions. + if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() { + if old, ok := m[name]; ok { + return match(nil, old, val) + } + m[name] = val + return true + } + } + } + + // Otherwise, pattern and val must match recursively. + if !pattern.IsValid() || !val.IsValid() { + return !pattern.IsValid() && !val.IsValid() + } + if pattern.Type() != val.Type() { + return false + } + + // Special cases. + switch pattern.Type() { + case identType: + // For identifiers, only the names need to match + // (and none of the other *ast.Object information). + // This is a common case, handle it all here instead + // of recursing down any further via reflection. + p := pattern.Interface().(*ast.Ident) + v := val.Interface().(*ast.Ident) + return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name + case objectPtrType, positionType: + // object pointers and token positions always match + return true + case callExprType: + // For calls, the Ellipsis fields (token.Position) must + // match since that is how f(x) and f(x...) are different. + // Check them here but fall through for the remaining fields. + p := pattern.Interface().(*ast.CallExpr) + v := val.Interface().(*ast.CallExpr) + if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() { + return false + } + } + + p := reflect.Indirect(pattern) + v := reflect.Indirect(val) + if !p.IsValid() || !v.IsValid() { + return !p.IsValid() && !v.IsValid() + } + + switch p.Kind() { + case reflect.Slice: + if p.Len() != v.Len() { + return false + } + for i := 0; i < p.Len(); i++ { + if !match(m, p.Index(i), v.Index(i)) { + return false + } + } + return true + + case reflect.Struct: + for i := 0; i < p.NumField(); i++ { + if !match(m, p.Field(i), v.Field(i)) { + return false + } + } + return true + + case reflect.Interface: + return match(m, p.Elem(), v.Elem()) + } + + // Handle token integers, etc. + return p.Interface() == v.Interface() +} + +// subst returns a copy of pattern with values from m substituted in place +// of wildcards and pos used as the position of tokens from the pattern. +// if m == nil, subst returns a copy of pattern and doesn't change the line +// number information. +func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value { + if !pattern.IsValid() { + return reflect.Value{} + } + + // Wildcard gets replaced with map value. + if m != nil && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) { + if old, ok := m[name]; ok { + return subst(nil, old, reflect.Value{}) + } + } + } + + if pos.IsValid() && pattern.Type() == positionType { + // use new position only if old position was valid in the first place + if old := pattern.Interface().(token.Pos); !old.IsValid() { + return pattern + } + return pos + } + + // Otherwise copy. + switch p := pattern; p.Kind() { + case reflect.Slice: + v := reflect.MakeSlice(p.Type(), p.Len(), p.Len()) + for i := 0; i < p.Len(); i++ { + v.Index(i).Set(subst(m, p.Index(i), pos)) + } + return v + + case reflect.Struct: + v := reflect.New(p.Type()).Elem() + for i := 0; i < p.NumField(); i++ { + v.Field(i).Set(subst(m, p.Field(i), pos)) + } + return v + + case reflect.Ptr: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos).Addr()) + } + return v + + case reflect.Interface: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos)) + } + return v + } + + return pattern +} diff --git a/vendor/github.com/klauspost/cpuid/private/README.md b/vendor/github.com/klauspost/cpuid/private/README.md new file mode 100644 index 000000000..57a68f882 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/README.md @@ -0,0 +1,6 @@ +# cpuid private + +This is a specially converted of the cpuid package, so it can be included in +a package without exporting anything. + +Package home: https://github.com/klauspost/cpuid diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid.go b/vendor/github.com/klauspost/cpuid/private/cpuid.go new file mode 100644 index 000000000..be99cb0b7 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/cpuid.go @@ -0,0 +1,987 @@ +// Generated, DO NOT EDIT, +// but copy it to your own project and rename the package. +// See more at http://github.com/klauspost/cpuid + +package cpuid + +import ( + "strings" +) + +// Vendor is a representation of a CPU vendor. +type vendor int + +const ( + other vendor = iota + intel + amd + via + transmeta + nsc + kvm // Kernel-based Virtual Machine + msvm // Microsoft Hyper-V or Windows Virtual PC + vmware + xenhvm +) + +const ( + cmov = 1 << iota // i686 CMOV + nx // NX (No-Execute) bit + amd3dnow // AMD 3DNOW + amd3dnowext // AMD 3DNowExt + mmx // standard MMX + mmxext // SSE integer functions or AMD MMX ext + sse // SSE functions + sse2 // P4 SSE functions + sse3 // Prescott SSE3 functions + ssse3 // Conroe SSSE3 functions + sse4 // Penryn SSE4.1 functions + sse4a // AMD Barcelona microarchitecture SSE4a instructions + sse42 // Nehalem SSE4.2 functions + avx // AVX functions + avx2 // AVX2 functions + fma3 // Intel FMA 3 + fma4 // Bulldozer FMA4 functions + xop // Bulldozer XOP functions + f16c // Half-precision floating-point conversion + bmi1 // Bit Manipulation Instruction Set 1 + bmi2 // Bit Manipulation Instruction Set 2 + tbm // AMD Trailing Bit Manipulation + lzcnt // LZCNT instruction + popcnt // POPCNT instruction + aesni // Advanced Encryption Standard New Instructions + clmul // Carry-less Multiplication + htt // Hyperthreading (enabled) + hle // Hardware Lock Elision + rtm // Restricted Transactional Memory + rdrand // RDRAND instruction is available + rdseed // RDSEED instruction is available + adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + sha // Intel SHA Extensions + avx512f // AVX-512 Foundation + avx512dq // AVX-512 Doubleword and Quadword Instructions + avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions + avx512pf // AVX-512 Prefetch Instructions + avx512er // AVX-512 Exponential and Reciprocal Instructions + avx512cd // AVX-512 Conflict Detection Instructions + avx512bw // AVX-512 Byte and Word Instructions + avx512vl // AVX-512 Vector Length Extensions + avx512vbmi // AVX-512 Vector Bit Manipulation Instructions + mpx // Intel MPX (Memory Protection Extensions) + erms // Enhanced REP MOVSB/STOSB + rdtscp // RDTSCP Instruction + cx16 // CMPXCHG16B Instruction + + // Performance indicators + sse2slow // SSE2 is supported, but usually not faster + sse3slow // SSE3 is supported, but usually not faster + atom // Atom processor, some SSSE3 instructions are slower +) + +var flagNames = map[flags]string{ + cmov: "CMOV", // i686 CMOV + nx: "NX", // NX (No-Execute) bit + amd3dnow: "AMD3DNOW", // AMD 3DNOW + amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt + mmx: "MMX", // Standard MMX + mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext + sse: "SSE", // SSE functions + sse2: "SSE2", // P4 SSE2 functions + sse3: "SSE3", // Prescott SSE3 functions + ssse3: "SSSE3", // Conroe SSSE3 functions + sse4: "SSE4.1", // Penryn SSE4.1 functions + sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions + sse42: "SSE4.2", // Nehalem SSE4.2 functions + avx: "AVX", // AVX functions + avx2: "AVX2", // AVX functions + fma3: "FMA3", // Intel FMA 3 + fma4: "FMA4", // Bulldozer FMA4 functions + xop: "XOP", // Bulldozer XOP functions + f16c: "F16C", // Half-precision floating-point conversion + bmi1: "BMI1", // Bit Manipulation Instruction Set 1 + bmi2: "BMI2", // Bit Manipulation Instruction Set 2 + tbm: "TBM", // AMD Trailing Bit Manipulation + lzcnt: "LZCNT", // LZCNT instruction + popcnt: "POPCNT", // POPCNT instruction + aesni: "AESNI", // Advanced Encryption Standard New Instructions + clmul: "CLMUL", // Carry-less Multiplication + htt: "HTT", // Hyperthreading (enabled) + hle: "HLE", // Hardware Lock Elision + rtm: "RTM", // Restricted Transactional Memory + rdrand: "RDRAND", // RDRAND instruction is available + rdseed: "RDSEED", // RDSEED instruction is available + adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + sha: "SHA", // Intel SHA Extensions + avx512f: "AVX512F", // AVX-512 Foundation + avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions + avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions + avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions + avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions + avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions + avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions + avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions + avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions + mpx: "MPX", // Intel MPX (Memory Protection Extensions) + erms: "ERMS", // Enhanced REP MOVSB/STOSB + rdtscp: "RDTSCP", // RDTSCP Instruction + cx16: "CX16", // CMPXCHG16B Instruction + + // Performance indicators + sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster + sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster + atom: "ATOM", // Atom processor, some SSSE3 instructions are slower + +} + +// CPUInfo contains information about the detected system CPU. +type cpuInfo struct { + brandname string // Brand name reported by the CPU + vendorid vendor // Comparable CPU vendor ID + features flags // Features of the CPU + physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. + threadspercore int // Number of threads per physical core. Will be 1 if undetectable. + logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. + family int // CPU family number + model int // CPU model number + cacheline int // Cache line size in bytes. Will be 0 if undetectable. + cache struct { + l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected + l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected + l2 int // L2 Cache (per core or shared). Will be -1 if undetected + l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected + } + maxFunc uint32 + maxExFunc uint32 +} + +var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) +var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32) +var xgetbv func(index uint32) (eax, edx uint32) +var rdtscpAsm func() (eax, ebx, ecx, edx uint32) + +// CPU contains information about the CPU as detected on startup, +// or when Detect last was called. +// +// Use this as the primary entry point to you data, +// this way queries are +var cpu cpuInfo + +func init() { + initCPU() + detect() +} + +// Detect will re-detect current CPU info. +// This will replace the content of the exported CPU variable. +// +// Unless you expect the CPU to change while you are running your program +// you should not need to call this function. +// If you call this, you must ensure that no other goroutine is accessing the +// exported CPU variable. +func detect() { + cpu.maxFunc = maxFunctionID() + cpu.maxExFunc = maxExtendedFunction() + cpu.brandname = brandName() + cpu.cacheline = cacheLine() + cpu.family, cpu.model = familyModel() + cpu.features = support() + cpu.threadspercore = threadsPerCore() + cpu.logicalcores = logicalCores() + cpu.physicalcores = physicalCores() + cpu.vendorid = vendorID() + cpu.cacheSize() +} + +// Generated here: http://play.golang.org/p/BxFH2Gdc0G + +// Cmov indicates support of CMOV instructions +func (c cpuInfo) cmov() bool { + return c.features&cmov != 0 +} + +// Amd3dnow indicates support of AMD 3DNOW! instructions +func (c cpuInfo) amd3dnow() bool { + return c.features&amd3dnow != 0 +} + +// Amd3dnowExt indicates support of AMD 3DNOW! Extended instructions +func (c cpuInfo) amd3dnowext() bool { + return c.features&amd3dnowext != 0 +} + +// MMX indicates support of MMX instructions +func (c cpuInfo) mmx() bool { + return c.features&mmx != 0 +} + +// MMXExt indicates support of MMXEXT instructions +// (SSE integer functions or AMD MMX ext) +func (c cpuInfo) mmxext() bool { + return c.features&mmxext != 0 +} + +// SSE indicates support of SSE instructions +func (c cpuInfo) sse() bool { + return c.features&sse != 0 +} + +// SSE2 indicates support of SSE 2 instructions +func (c cpuInfo) sse2() bool { + return c.features&sse2 != 0 +} + +// SSE3 indicates support of SSE 3 instructions +func (c cpuInfo) sse3() bool { + return c.features&sse3 != 0 +} + +// SSSE3 indicates support of SSSE 3 instructions +func (c cpuInfo) ssse3() bool { + return c.features&ssse3 != 0 +} + +// SSE4 indicates support of SSE 4 (also called SSE 4.1) instructions +func (c cpuInfo) sse4() bool { + return c.features&sse4 != 0 +} + +// SSE42 indicates support of SSE4.2 instructions +func (c cpuInfo) sse42() bool { + return c.features&sse42 != 0 +} + +// AVX indicates support of AVX instructions +// and operating system support of AVX instructions +func (c cpuInfo) avx() bool { + return c.features&avx != 0 +} + +// AVX2 indicates support of AVX2 instructions +func (c cpuInfo) avx2() bool { + return c.features&avx2 != 0 +} + +// FMA3 indicates support of FMA3 instructions +func (c cpuInfo) fma3() bool { + return c.features&fma3 != 0 +} + +// FMA4 indicates support of FMA4 instructions +func (c cpuInfo) fma4() bool { + return c.features&fma4 != 0 +} + +// XOP indicates support of XOP instructions +func (c cpuInfo) xop() bool { + return c.features&xop != 0 +} + +// F16C indicates support of F16C instructions +func (c cpuInfo) f16c() bool { + return c.features&f16c != 0 +} + +// BMI1 indicates support of BMI1 instructions +func (c cpuInfo) bmi1() bool { + return c.features&bmi1 != 0 +} + +// BMI2 indicates support of BMI2 instructions +func (c cpuInfo) bmi2() bool { + return c.features&bmi2 != 0 +} + +// TBM indicates support of TBM instructions +// (AMD Trailing Bit Manipulation) +func (c cpuInfo) tbm() bool { + return c.features&tbm != 0 +} + +// Lzcnt indicates support of LZCNT instruction +func (c cpuInfo) lzcnt() bool { + return c.features&lzcnt != 0 +} + +// Popcnt indicates support of POPCNT instruction +func (c cpuInfo) popcnt() bool { + return c.features&popcnt != 0 +} + +// HTT indicates the processor has Hyperthreading enabled +func (c cpuInfo) htt() bool { + return c.features&htt != 0 +} + +// SSE2Slow indicates that SSE2 may be slow on this processor +func (c cpuInfo) sse2slow() bool { + return c.features&sse2slow != 0 +} + +// SSE3Slow indicates that SSE3 may be slow on this processor +func (c cpuInfo) sse3slow() bool { + return c.features&sse3slow != 0 +} + +// AesNi indicates support of AES-NI instructions +// (Advanced Encryption Standard New Instructions) +func (c cpuInfo) aesni() bool { + return c.features&aesni != 0 +} + +// Clmul indicates support of CLMUL instructions +// (Carry-less Multiplication) +func (c cpuInfo) clmul() bool { + return c.features&clmul != 0 +} + +// NX indicates support of NX (No-Execute) bit +func (c cpuInfo) nx() bool { + return c.features&nx != 0 +} + +// SSE4A indicates support of AMD Barcelona microarchitecture SSE4a instructions +func (c cpuInfo) sse4a() bool { + return c.features&sse4a != 0 +} + +// HLE indicates support of Hardware Lock Elision +func (c cpuInfo) hle() bool { + return c.features&hle != 0 +} + +// RTM indicates support of Restricted Transactional Memory +func (c cpuInfo) rtm() bool { + return c.features&rtm != 0 +} + +// Rdrand indicates support of RDRAND instruction is available +func (c cpuInfo) rdrand() bool { + return c.features&rdrand != 0 +} + +// Rdseed indicates support of RDSEED instruction is available +func (c cpuInfo) rdseed() bool { + return c.features&rdseed != 0 +} + +// ADX indicates support of Intel ADX (Multi-Precision Add-Carry Instruction Extensions) +func (c cpuInfo) adx() bool { + return c.features&adx != 0 +} + +// SHA indicates support of Intel SHA Extensions +func (c cpuInfo) sha() bool { + return c.features&sha != 0 +} + +// AVX512F indicates support of AVX-512 Foundation +func (c cpuInfo) avx512f() bool { + return c.features&avx512f != 0 +} + +// AVX512DQ indicates support of AVX-512 Doubleword and Quadword Instructions +func (c cpuInfo) avx512dq() bool { + return c.features&avx512dq != 0 +} + +// AVX512IFMA indicates support of AVX-512 Integer Fused Multiply-Add Instructions +func (c cpuInfo) avx512ifma() bool { + return c.features&avx512ifma != 0 +} + +// AVX512PF indicates support of AVX-512 Prefetch Instructions +func (c cpuInfo) avx512pf() bool { + return c.features&avx512pf != 0 +} + +// AVX512ER indicates support of AVX-512 Exponential and Reciprocal Instructions +func (c cpuInfo) avx512er() bool { + return c.features&avx512er != 0 +} + +// AVX512CD indicates support of AVX-512 Conflict Detection Instructions +func (c cpuInfo) avx512cd() bool { + return c.features&avx512cd != 0 +} + +// AVX512BW indicates support of AVX-512 Byte and Word Instructions +func (c cpuInfo) avx512bw() bool { + return c.features&avx512bw != 0 +} + +// AVX512VL indicates support of AVX-512 Vector Length Extensions +func (c cpuInfo) avx512vl() bool { + return c.features&avx512vl != 0 +} + +// AVX512VBMI indicates support of AVX-512 Vector Bit Manipulation Instructions +func (c cpuInfo) avx512vbmi() bool { + return c.features&avx512vbmi != 0 +} + +// MPX indicates support of Intel MPX (Memory Protection Extensions) +func (c cpuInfo) mpx() bool { + return c.features&mpx != 0 +} + +// ERMS indicates support of Enhanced REP MOVSB/STOSB +func (c cpuInfo) erms() bool { + return c.features&erms != 0 +} + +func (c cpuInfo) rdtscp() bool { + return c.features&rdtscp != 0 +} + +func (c cpuInfo) cx16() bool { + return c.features&cx16 != 0 +} + +// Atom indicates an Atom processor +func (c cpuInfo) atom() bool { + return c.features&atom != 0 +} + +// Intel returns true if vendor is recognized as Intel +func (c cpuInfo) intel() bool { + return c.vendorid == intel +} + +// AMD returns true if vendor is recognized as AMD +func (c cpuInfo) amd() bool { + return c.vendorid == amd +} + +// Transmeta returns true if vendor is recognized as Transmeta +func (c cpuInfo) transmeta() bool { + return c.vendorid == transmeta +} + +// NSC returns true if vendor is recognized as National Semiconductor +func (c cpuInfo) nsc() bool { + return c.vendorid == nsc +} + +// VIA returns true if vendor is recognized as VIA +func (c cpuInfo) via() bool { + return c.vendorid == via +} + +// RTCounter returns the 64-bit time-stamp counter +// Uses the RDTSCP instruction. The value 0 is returned +// if the CPU does not support the instruction. +func (c cpuInfo) rtcounter() uint64 { + if !c.rdtscp() { + return 0 + } + a, _, _, d := rdtscpAsm() + return uint64(a) | (uint64(d) << 32) +} + +// Ia32TscAux returns the IA32_TSC_AUX part of the RDTSCP. +// This variable is OS dependent, but on Linux contains information +// about the current cpu/core the code is running on. +// If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned. +func (c cpuInfo) ia32tscaux() uint32 { + if !c.rdtscp() { + return 0 + } + _, _, ecx, _ := rdtscpAsm() + return ecx +} + +// LogicalCPU will return the Logical CPU the code is currently executing on. +// This is likely to change when the OS re-schedules the running thread +// to another CPU. +// If the current core cannot be detected, -1 will be returned. +func (c cpuInfo) logicalcpu() int { + if c.maxFunc < 1 { + return -1 + } + _, ebx, _, _ := cpuid(1) + return int(ebx >> 24) +} + +// VM Will return true if the cpu id indicates we are in +// a virtual machine. This is only a hint, and will very likely +// have many false negatives. +func (c cpuInfo) vm() bool { + switch c.vendorid { + case msvm, kvm, vmware, xenhvm: + return true + } + return false +} + +// Flags contains detected cpu features and caracteristics +type flags uint64 + +// String returns a string representation of the detected +// CPU features. +func (f flags) String() string { + return strings.Join(f.strings(), ",") +} + +// Strings returns and array of the detected features. +func (f flags) strings() []string { + s := support() + r := make([]string, 0, 20) + for i := uint(0); i < 64; i++ { + key := flags(1 << i) + val := flagNames[key] + if s&key != 0 { + r = append(r, val) + } + } + return r +} + +func maxExtendedFunction() uint32 { + eax, _, _, _ := cpuid(0x80000000) + return eax +} + +func maxFunctionID() uint32 { + a, _, _, _ := cpuid(0) + return a +} + +func brandName() string { + if maxExtendedFunction() >= 0x80000004 { + v := make([]uint32, 0, 48) + for i := uint32(0); i < 3; i++ { + a, b, c, d := cpuid(0x80000002 + i) + v = append(v, a, b, c, d) + } + return strings.Trim(string(valAsString(v...)), " ") + } + return "unknown" +} + +func threadsPerCore() int { + mfi := maxFunctionID() + if mfi < 0x4 || vendorID() != intel { + return 1 + } + + if mfi < 0xb { + _, b, _, d := cpuid(1) + if (d & (1 << 28)) != 0 { + // v will contain logical core count + v := (b >> 16) & 255 + if v > 1 { + a4, _, _, _ := cpuid(4) + // physical cores + v2 := (a4 >> 26) + 1 + if v2 > 0 { + return int(v) / int(v2) + } + } + } + return 1 + } + _, b, _, _ := cpuidex(0xb, 0) + if b&0xffff == 0 { + return 1 + } + return int(b & 0xffff) +} + +func logicalCores() int { + mfi := maxFunctionID() + switch vendorID() { + case intel: + // Use this on old Intel processors + if mfi < 0xb { + if mfi < 1 { + return 0 + } + // CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial APIC ID) + // that can be assigned to logical processors in a physical package. + // The value may not be the same as the number of logical processors that are present in the hardware of a physical package. + _, ebx, _, _ := cpuid(1) + logical := (ebx >> 16) & 0xff + return int(logical) + } + _, b, _, _ := cpuidex(0xb, 1) + return int(b & 0xffff) + case amd: + _, b, _, _ := cpuid(1) + return int((b >> 16) & 0xff) + default: + return 0 + } +} + +func familyModel() (int, int) { + if maxFunctionID() < 0x1 { + return 0, 0 + } + eax, _, _, _ := cpuid(1) + family := ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff) + model := ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0) + return int(family), int(model) +} + +func physicalCores() int { + switch vendorID() { + case intel: + return logicalCores() / threadsPerCore() + case amd: + if maxExtendedFunction() >= 0x80000008 { + _, _, c, _ := cpuid(0x80000008) + return int(c&0xff) + 1 + } + } + return 0 +} + +// Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID +var vendorMapping = map[string]vendor{ + "AMDisbetter!": amd, + "AuthenticAMD": amd, + "CentaurHauls": via, + "GenuineIntel": intel, + "TransmetaCPU": transmeta, + "GenuineTMx86": transmeta, + "Geode by NSC": nsc, + "VIA VIA VIA ": via, + "KVMKVMKVMKVM": kvm, + "Microsoft Hv": msvm, + "VMwareVMware": vmware, + "XenVMMXenVMM": xenhvm, +} + +func vendorID() vendor { + _, b, c, d := cpuid(0) + v := valAsString(b, d, c) + vend, ok := vendorMapping[string(v)] + if !ok { + return other + } + return vend +} + +func cacheLine() int { + if maxFunctionID() < 0x1 { + return 0 + } + + _, ebx, _, _ := cpuid(1) + cache := (ebx & 0xff00) >> 5 // cflush size + if cache == 0 && maxExtendedFunction() >= 0x80000006 { + _, _, ecx, _ := cpuid(0x80000006) + cache = ecx & 0xff // cacheline size + } + // TODO: Read from Cache and TLB Information + return int(cache) +} + +func (c *cpuInfo) cacheSize() { + c.cache.l1d = -1 + c.cache.l1i = -1 + c.cache.l2 = -1 + c.cache.l3 = -1 + vendor := vendorID() + switch vendor { + case intel: + if maxFunctionID() < 4 { + return + } + for i := uint32(0); ; i++ { + eax, ebx, ecx, _ := cpuidex(4, i) + cacheType := eax & 15 + if cacheType == 0 { + break + } + cacheLevel := (eax >> 5) & 7 + coherency := int(ebx&0xfff) + 1 + partitions := int((ebx>>12)&0x3ff) + 1 + associativity := int((ebx>>22)&0x3ff) + 1 + sets := int(ecx) + 1 + size := associativity * partitions * coherency * sets + switch cacheLevel { + case 1: + if cacheType == 1 { + // 1 = Data Cache + c.cache.l1d = size + } else if cacheType == 2 { + // 2 = Instruction Cache + c.cache.l1i = size + } else { + if c.cache.l1d < 0 { + c.cache.l1i = size + } + if c.cache.l1i < 0 { + c.cache.l1i = size + } + } + case 2: + c.cache.l2 = size + case 3: + c.cache.l3 = size + } + } + case amd: + // Untested. + if maxExtendedFunction() < 0x80000005 { + return + } + _, _, ecx, edx := cpuid(0x80000005) + c.cache.l1d = int(((ecx >> 24) & 0xFF) * 1024) + c.cache.l1i = int(((edx >> 24) & 0xFF) * 1024) + + if maxExtendedFunction() < 0x80000006 { + return + } + _, _, ecx, _ = cpuid(0x80000006) + c.cache.l2 = int(((ecx >> 16) & 0xFFFF) * 1024) + } + + return +} + +func support() flags { + mfi := maxFunctionID() + vend := vendorID() + if mfi < 0x1 { + return 0 + } + rval := uint64(0) + _, _, c, d := cpuid(1) + if (d & (1 << 15)) != 0 { + rval |= cmov + } + if (d & (1 << 23)) != 0 { + rval |= mmx + } + if (d & (1 << 25)) != 0 { + rval |= mmxext + } + if (d & (1 << 25)) != 0 { + rval |= sse + } + if (d & (1 << 26)) != 0 { + rval |= sse2 + } + if (c & 1) != 0 { + rval |= sse3 + } + if (c & 0x00000200) != 0 { + rval |= ssse3 + } + if (c & 0x00080000) != 0 { + rval |= sse4 + } + if (c & 0x00100000) != 0 { + rval |= sse42 + } + if (c & (1 << 25)) != 0 { + rval |= aesni + } + if (c & (1 << 1)) != 0 { + rval |= clmul + } + if c&(1<<23) != 0 { + rval |= popcnt + } + if c&(1<<30) != 0 { + rval |= rdrand + } + if c&(1<<29) != 0 { + rval |= f16c + } + if c&(1<<13) != 0 { + rval |= cx16 + } + if vend == intel && (d&(1<<28)) != 0 && mfi >= 4 { + if threadsPerCore() > 1 { + rval |= htt + } + } + + // Check XGETBV, OXSAVE and AVX bits + if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 { + // Check for OS support + eax, _ := xgetbv(0) + if (eax & 0x6) == 0x6 { + rval |= avx + if (c & 0x00001000) != 0 { + rval |= fma3 + } + } + } + + // Check AVX2, AVX2 requires OS support, but BMI1/2 don't. + if mfi >= 7 { + _, ebx, ecx, _ := cpuidex(7, 0) + if (rval&avx) != 0 && (ebx&0x00000020) != 0 { + rval |= avx2 + } + if (ebx & 0x00000008) != 0 { + rval |= bmi1 + if (ebx & 0x00000100) != 0 { + rval |= bmi2 + } + } + if ebx&(1<<4) != 0 { + rval |= hle + } + if ebx&(1<<9) != 0 { + rval |= erms + } + if ebx&(1<<11) != 0 { + rval |= rtm + } + if ebx&(1<<14) != 0 { + rval |= mpx + } + if ebx&(1<<18) != 0 { + rval |= rdseed + } + if ebx&(1<<19) != 0 { + rval |= adx + } + if ebx&(1<<29) != 0 { + rval |= sha + } + + // Only detect AVX-512 features if XGETBV is supported + if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) { + // Check for OS support + eax, _ := xgetbv(0) + + // Verify that XCR0[7:5] = ‘111b’ (OPMASK state, upper 256-bit of ZMM0-ZMM15 and + // ZMM16-ZMM31 state are enabled by OS) + /// and that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS). + if (eax>>5)&7 == 7 && (eax>>1)&3 == 3 { + if ebx&(1<<16) != 0 { + rval |= avx512f + } + if ebx&(1<<17) != 0 { + rval |= avx512dq + } + if ebx&(1<<21) != 0 { + rval |= avx512ifma + } + if ebx&(1<<26) != 0 { + rval |= avx512pf + } + if ebx&(1<<27) != 0 { + rval |= avx512er + } + if ebx&(1<<28) != 0 { + rval |= avx512cd + } + if ebx&(1<<30) != 0 { + rval |= avx512bw + } + if ebx&(1<<31) != 0 { + rval |= avx512vl + } + // ecx + if ecx&(1<<1) != 0 { + rval |= avx512vbmi + } + } + } + } + + if maxExtendedFunction() >= 0x80000001 { + _, _, c, d := cpuid(0x80000001) + if (c & (1 << 5)) != 0 { + rval |= lzcnt + rval |= popcnt + } + if (d & (1 << 31)) != 0 { + rval |= amd3dnow + } + if (d & (1 << 30)) != 0 { + rval |= amd3dnowext + } + if (d & (1 << 23)) != 0 { + rval |= mmx + } + if (d & (1 << 22)) != 0 { + rval |= mmxext + } + if (c & (1 << 6)) != 0 { + rval |= sse4a + } + if d&(1<<20) != 0 { + rval |= nx + } + if d&(1<<27) != 0 { + rval |= rdtscp + } + + /* Allow for selectively disabling SSE2 functions on AMD processors + with SSE2 support but not SSE4a. This includes Athlon64, some + Opteron, and some Sempron processors. MMX, SSE, or 3DNow! are faster + than SSE2 often enough to utilize this special-case flag. + AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case + so that SSE2 is used unless explicitly disabled by checking + AV_CPU_FLAG_SSE2SLOW. */ + if vendorID() != intel && + rval&sse2 != 0 && (c&0x00000040) == 0 { + rval |= sse2slow + } + + /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be + * used unless the OS has AVX support. */ + if (rval & avx) != 0 { + if (c & 0x00000800) != 0 { + rval |= xop + } + if (c & 0x00010000) != 0 { + rval |= fma4 + } + } + + if vendorID() == intel { + family, model := familyModel() + if family == 6 && (model == 9 || model == 13 || model == 14) { + /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and + * 6/14 (core1 "yonah") theoretically support sse2, but it's + * usually slower than mmx. */ + if (rval & sse2) != 0 { + rval |= sse2slow + } + if (rval & sse3) != 0 { + rval |= sse3slow + } + } + /* The Atom processor has SSSE3 support, which is useful in many cases, + * but sometimes the SSSE3 version is slower than the SSE2 equivalent + * on the Atom, but is generally faster on other processors supporting + * SSSE3. This flag allows for selectively disabling certain SSSE3 + * functions on the Atom. */ + if family == 6 && model == 28 { + rval |= atom + } + } + } + return flags(rval) +} + +func valAsString(values ...uint32) []byte { + r := make([]byte, 4*len(values)) + for i, v := range values { + dst := r[i*4:] + dst[0] = byte(v & 0xff) + dst[1] = byte((v >> 8) & 0xff) + dst[2] = byte((v >> 16) & 0xff) + dst[3] = byte((v >> 24) & 0xff) + switch { + case dst[0] == 0: + return r[:i*4] + case dst[1] == 0: + return r[:i*4+1] + case dst[2] == 0: + return r[:i*4+2] + case dst[3] == 0: + return r[:i*4+3] + } + } + return r +} diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid_386.s b/vendor/github.com/klauspost/cpuid/private/cpuid_386.s new file mode 100644 index 000000000..9947f7b6f --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/cpuid_386.s @@ -0,0 +1,40 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuid(SB), 7, $0 + XORL CX, CX + MOVL op+0(FP), AX + CPUID + MOVL AX, eax+4(FP) + MOVL BX, ebx+8(FP) + MOVL CX, ecx+12(FP) + MOVL DX, edx+16(FP) + RET + +// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuidex(SB), 7, $0 + MOVL op+0(FP), AX + MOVL op2+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func xgetbv(index uint32) (eax, edx uint32) +TEXT ·asmXgetbv(SB), 7, $0 + MOVL index+0(FP), CX + BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV + MOVL AX, eax+4(FP) + MOVL DX, edx+8(FP) + RET + +// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) +TEXT ·asmRdtscpAsm(SB), 7, $0 + BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP + MOVL AX, eax+0(FP) + MOVL BX, ebx+4(FP) + MOVL CX, ecx+8(FP) + MOVL DX, edx+12(FP) + RET diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid_amd64.s b/vendor/github.com/klauspost/cpuid/private/cpuid_amd64.s new file mode 100644 index 000000000..68a7c9d88 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/cpuid_amd64.s @@ -0,0 +1,40 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuid(SB), 7, $0 + XORQ CX, CX + MOVL op+0(FP), AX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +TEXT ·asmCpuidex(SB), 7, $0 + MOVL op+0(FP), AX + MOVL op2+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func asmXgetbv(index uint32) (eax, edx uint32) +TEXT ·asmXgetbv(SB), 7, $0 + MOVL index+0(FP), CX + BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV + MOVL AX, eax+8(FP) + MOVL DX, edx+12(FP) + RET + +// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) +TEXT ·asmRdtscpAsm(SB), 7, $0 + BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP + MOVL AX, eax+0(FP) + MOVL BX, ebx+4(FP) + MOVL CX, ecx+8(FP) + MOVL DX, edx+12(FP) + RET diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid_detect_intel.go b/vendor/github.com/klauspost/cpuid/private/cpuid_detect_intel.go new file mode 100644 index 000000000..d5475ebfa --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/cpuid_detect_intel.go @@ -0,0 +1,17 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// +build 386 amd64 + +package cpuid + +func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) +func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) +func asmXgetbv(index uint32) (eax, edx uint32) +func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) + +func initCPU() { + cpuid = asmCpuid + cpuidex = asmCpuidex + xgetbv = asmXgetbv + rdtscpAsm = asmRdtscpAsm +} diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid_detect_ref.go b/vendor/github.com/klauspost/cpuid/private/cpuid_detect_ref.go new file mode 100644 index 000000000..6f9231b13 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/private/cpuid_detect_ref.go @@ -0,0 +1,23 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// +build !amd64,!386 + +package cpuid + +func initCPU() { + cpuid = func(op uint32) (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } + + cpuidex = func(op, op2 uint32) (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } + + xgetbv = func(index uint32) (eax, edx uint32) { + return 0, 0 + } + + rdtscpAsm = func() (eax, ebx, ecx, edx uint32) { + return 0, 0, 0, 0 + } +} diff --git a/vendor/github.com/klauspost/crc32/.gitignore b/vendor/github.com/klauspost/crc32/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/klauspost/crc32/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/klauspost/crc32/.travis.yml b/vendor/github.com/klauspost/crc32/.travis.yml new file mode 100644 index 000000000..c62e25f5a --- /dev/null +++ b/vendor/github.com/klauspost/crc32/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: + - go test -v . + - go test -v -race . diff --git a/vendor/github.com/klauspost/crc32/LICENSE b/vendor/github.com/klauspost/crc32/LICENSE new file mode 100644 index 000000000..4fd5963e3 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2015 Klaus Post + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/crc32/README.md b/vendor/github.com/klauspost/crc32/README.md new file mode 100644 index 000000000..440541c7f --- /dev/null +++ b/vendor/github.com/klauspost/crc32/README.md @@ -0,0 +1,84 @@ +# crc32 +CRC32 hash with x64 optimizations + +This package is a drop-in replacement for the standard library `hash/crc32` package, that features SSE 4.2 optimizations on x64 platforms, for a 10x speedup. + +[![Build Status](https://travis-ci.org/klauspost/crc32.svg?branch=master)](https://travis-ci.org/klauspost/crc32) + +# usage + +Install using `go get github.com/klauspost/crc32`. This library is based on Go 1.5 code and requires Go 1.3 or newer. + +Replace `import "hash/crc32"` with `import "github.com/klauspost/crc32"` and you are good to go. + +# changes + +* Dec 4, 2015: Uses the "slice-by-8" trick more extensively, which gives a 1.5 to 2.5x speedup if assembler is unavailable. + + +# performance + +For IEEE tables (the most common), there is approximately a factor 10 speedup with "CLMUL" (Carryless multiplication) instruction: +``` +benchmark old ns/op new ns/op delta +BenchmarkCrc32KB 99955 10258 -89.74% + +benchmark old MB/s new MB/s speedup +BenchmarkCrc32KB 327.83 3194.20 9.74x +``` + +For other tables and "CLMUL" capable machines the performance is the same as the standard library. + +Here are some detailed benchmarks, comparing to go 1.5 standard library with and without assembler enabled. + +``` +Std: Standard Go 1.5 library +Crc: Indicates IEEE type CRC. +40B: Size of each slice encoded. +NoAsm: Assembler was disabled (ie. not an AMD64 or SSE 4.2+ capable machine). +Castagnoli: Castagnoli CRC type. + +BenchmarkStdCrc40B-4 10000000 158 ns/op 252.88 MB/s +BenchmarkCrc40BNoAsm-4 20000000 105 ns/op 377.38 MB/s (slice8) +BenchmarkCrc40B-4 20000000 105 ns/op 378.77 MB/s (slice8) + +BenchmarkStdCrc1KB-4 500000 3604 ns/op 284.10 MB/s +BenchmarkCrc1KBNoAsm-4 1000000 1463 ns/op 699.79 MB/s (slice8) +BenchmarkCrc1KB-4 3000000 396 ns/op 2583.69 MB/s (asm) + +BenchmarkStdCrc8KB-4 200000 11417 ns/op 717.48 MB/s (slice8) +BenchmarkCrc8KBNoAsm-4 200000 11317 ns/op 723.85 MB/s (slice8) +BenchmarkCrc8KB-4 500000 2919 ns/op 2805.73 MB/s (asm) + +BenchmarkStdCrc32KB-4 30000 45749 ns/op 716.24 MB/s (slice8) +BenchmarkCrc32KBNoAsm-4 30000 45109 ns/op 726.42 MB/s (slice8) +BenchmarkCrc32KB-4 100000 11497 ns/op 2850.09 MB/s (asm) + +BenchmarkStdNoAsmCastagnol40B-4 10000000 161 ns/op 246.94 MB/s +BenchmarkStdCastagnoli40B-4 50000000 28.4 ns/op 1410.69 MB/s (asm) +BenchmarkCastagnoli40BNoAsm-4 20000000 100 ns/op 398.01 MB/s (slice8) +BenchmarkCastagnoli40B-4 50000000 28.2 ns/op 1419.54 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli1KB-4 500000 3622 ns/op 282.67 MB/s +BenchmarkStdCastagnoli1KB-4 10000000 144 ns/op 7099.78 MB/s (asm) +BenchmarkCastagnoli1KBNoAsm-4 1000000 1475 ns/op 694.14 MB/s (slice8) +BenchmarkCastagnoli1KB-4 10000000 146 ns/op 6993.35 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli8KB-4 50000 28781 ns/op 284.63 MB/s +BenchmarkStdCastagnoli8KB-4 1000000 1029 ns/op 7957.89 MB/s (asm) +BenchmarkCastagnoli8KBNoAsm-4 200000 11410 ns/op 717.94 MB/s (slice8) +BenchmarkCastagnoli8KB-4 1000000 1000 ns/op 8188.71 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli32KB-4 10000 115426 ns/op 283.89 MB/s +BenchmarkStdCastagnoli32KB-4 300000 4065 ns/op 8059.13 MB/s (asm) +BenchmarkCastagnoli32KBNoAsm-4 30000 45171 ns/op 725.41 MB/s (slice8) +BenchmarkCastagnoli32KB-4 500000 4077 ns/op 8035.89 MB/s (asm) +``` + +The IEEE assembler optimizations has been submitted and will be part of the Go 1.6 standard library. + +However, the improved use of slice-by-8 has not, but will probably be submitted for Go 1.7. + +# license + +Standard Go license. Changes are Copyright (c) 2015 Klaus Post under same conditions. diff --git a/vendor/github.com/klauspost/crc32/crc32.go b/vendor/github.com/klauspost/crc32/crc32.go new file mode 100644 index 000000000..b584e4103 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32.go @@ -0,0 +1,182 @@ +// 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. + +// Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32, +// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for +// information. +// +// Polynomials are represented in LSB-first form also known as reversed representation. +// +// See http://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials +// for information. +package crc32 + +import ( + "hash" + "sync" +) + +// The size of a CRC-32 checksum in bytes. +const Size = 4 + +// Predefined polynomials. +const ( + // IEEE is by far and away the most common CRC-32 polynomial. + // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ... + IEEE = 0xedb88320 + + // Castagnoli's polynomial, used in iSCSI. + // Has better error detection characteristics than IEEE. + // http://dx.doi.org/10.1109/26.231911 + Castagnoli = 0x82f63b78 + + // Koopman's polynomial. + // Also has better error detection characteristics than IEEE. + // http://dx.doi.org/10.1109/DSN.2002.1028931 + Koopman = 0xeb31d82e +) + +// Table is a 256-word table representing the polynomial for efficient processing. +type Table [256]uint32 + +// castagnoliTable points to a lazily initialized Table for the Castagnoli +// polynomial. MakeTable will always return this value when asked to make a +// Castagnoli table so we can compare against it to find when the caller is +// using this polynomial. +var castagnoliTable *Table +var castagnoliTable8 *slicing8Table +var castagnoliOnce sync.Once + +func castagnoliInit() { + castagnoliTable = makeTable(Castagnoli) + castagnoliTable8 = makeTable8(Castagnoli) +} + +// IEEETable is the table for the IEEE polynomial. +var IEEETable = makeTable(IEEE) + +// slicing8Table is array of 8 Tables +type slicing8Table [8]Table + +// iEEETable8 is the slicing8Table for IEEE +var iEEETable8 *slicing8Table +var iEEETable8Once sync.Once + +// MakeTable returns the Table constructed from the specified polynomial. +func MakeTable(poly uint32) *Table { + switch poly { + case IEEE: + return IEEETable + case Castagnoli: + castagnoliOnce.Do(castagnoliInit) + return castagnoliTable + } + return makeTable(poly) +} + +// makeTable returns the Table constructed from the specified polynomial. +func makeTable(poly uint32) *Table { + t := new(Table) + for i := 0; i < 256; i++ { + crc := uint32(i) + for j := 0; j < 8; j++ { + if crc&1 == 1 { + crc = (crc >> 1) ^ poly + } else { + crc >>= 1 + } + } + t[i] = crc + } + return t +} + +// makeTable8 returns slicing8Table constructed from the specified polynomial. +func makeTable8(poly uint32) *slicing8Table { + t := new(slicing8Table) + t[0] = *makeTable(poly) + for i := 0; i < 256; i++ { + crc := t[0][i] + for j := 1; j < 8; j++ { + crc = t[0][crc&0xFF] ^ (crc >> 8) + t[j][i] = crc + } + } + return t +} + +// digest represents the partial evaluation of a checksum. +type digest struct { + crc uint32 + tab *Table +} + +// New creates a new hash.Hash32 computing the CRC-32 checksum +// using the polynomial represented by the Table. +func New(tab *Table) hash.Hash32 { return &digest{0, tab} } + +// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum +// using the IEEE polynomial. +func NewIEEE() hash.Hash32 { return New(IEEETable) } + +func (d *digest) Size() int { return Size } + +func (d *digest) BlockSize() int { return 1 } + +func (d *digest) Reset() { d.crc = 0 } + +func update(crc uint32, tab *Table, p []byte) uint32 { + crc = ^crc + for _, v := range p { + crc = tab[byte(crc)^v] ^ (crc >> 8) + } + return ^crc +} + +// updateSlicingBy8 updates CRC using Slicing-by-8 +func updateSlicingBy8(crc uint32, tab *slicing8Table, p []byte) uint32 { + crc = ^crc + for len(p) > 8 { + crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 + crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^ + tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^ + tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF] + p = p[8:] + } + crc = ^crc + if len(p) == 0 { + return crc + } + return update(crc, &tab[0], p) +} + +// Update returns the result of adding the bytes in p to the crc. +func Update(crc uint32, tab *Table, p []byte) uint32 { + if tab == castagnoliTable { + return updateCastagnoli(crc, p) + } else if tab == IEEETable { + return updateIEEE(crc, p) + } + return update(crc, tab, p) +} + +func (d *digest) Write(p []byte) (n int, err error) { + d.crc = Update(d.crc, d.tab, p) + return len(p), nil +} + +func (d *digest) Sum32() uint32 { return d.crc } + +func (d *digest) Sum(in []byte) []byte { + s := d.Sum32() + return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) +} + +// Checksum returns the CRC-32 checksum of data +// using the polynomial represented by the Table. +func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) } + +// ChecksumIEEE returns the CRC-32 checksum of data +// using the IEEE polynomial. +func ChecksumIEEE(data []byte) uint32 { return updateIEEE(0, data) } diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64.go b/vendor/github.com/klauspost/crc32/crc32_amd64.go new file mode 100644 index 000000000..bf25550e7 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32_amd64.go @@ -0,0 +1,62 @@ +// Copyright 2011 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. + +// +build !appengine,!gccgo + +package crc32 + +// This file contains the code to call the SSE 4.2 version of the Castagnoli +// and IEEE CRC. + +// haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and uses +// CPUID to test for SSE 4.1, 4.2 and CLMUL support. +func haveSSE41() bool +func haveSSE42() bool +func haveCLMUL() bool + +// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32 +// instruction. +// go:noescape +func castagnoliSSE42(crc uint32, p []byte) uint32 + +// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ +// instruction as well as SSE 4.1. +// go:noescape +func ieeeCLMUL(crc uint32, p []byte) uint32 + +var sse42 = haveSSE42() +var useFastIEEE = haveCLMUL() && haveSSE41() + +func updateCastagnoli(crc uint32, p []byte) uint32 { + if sse42 { + return castagnoliSSE42(crc, p) + } + // only use slicing-by-8 when input is >= 16 Bytes + if len(p) >= 16 { + return updateSlicingBy8(crc, castagnoliTable8, p) + } + return update(crc, castagnoliTable, p) +} + +func updateIEEE(crc uint32, p []byte) uint32 { + if useFastIEEE && len(p) >= 64 { + left := len(p) & 15 + do := len(p) - left + crc := ^ieeeCLMUL(^crc, p[:do]) + if left > 0 { + crc = update(crc, IEEETable, p[do:]) + } + return crc + } + + // only use slicing-by-8 when input is >= 16 Bytes + if len(p) >= 16 { + iEEETable8Once.Do(func() { + iEEETable8 = makeTable8(IEEE) + }) + return updateSlicingBy8(crc, iEEETable8, p) + } + + return update(crc, IEEETable, p) +} diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64.s b/vendor/github.com/klauspost/crc32/crc32_amd64.s new file mode 100644 index 000000000..ca73c7325 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32_amd64.s @@ -0,0 +1,237 @@ +// Copyright 2011 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. + +// +build gc + +#define NOSPLIT 4 +#define RODATA 8 + +// func castagnoliSSE42(crc uint32, p []byte) uint32 +TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 + MOVL crc+0(FP), AX // CRC value + MOVQ p+8(FP), SI // data pointer + MOVQ p_len+16(FP), CX // len(p) + + NOTL AX + + // If there's less than 8 bytes to process, we do it byte-by-byte. + CMPQ CX, $8 + JL cleanup + + // Process individual bytes until the input is 8-byte aligned. +startup: + MOVQ SI, BX + ANDQ $7, BX + JZ aligned + + CRC32B (SI), AX + DECQ CX + INCQ SI + JMP startup + +aligned: + // The input is now 8-byte aligned and we can process 8-byte chunks. + CMPQ CX, $8 + JL cleanup + + CRC32Q (SI), AX + ADDQ $8, SI + SUBQ $8, CX + JMP aligned + +cleanup: + // We may have some bytes left over that we process one at a time. + CMPQ CX, $0 + JE done + + CRC32B (SI), AX + INCQ SI + DECQ CX + JMP cleanup + +done: + NOTL AX + MOVL AX, ret+32(FP) + RET + +// func haveSSE42() bool +TEXT ·haveSSE42(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $20, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// func haveCLMUL() bool +TEXT ·haveCLMUL(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $1, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// func haveSSE41() bool +TEXT ·haveSSE41(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $19, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +// CRC32 polynomial data +// +// These constants are lifted from the +// Linux kernel, since they avoid the costly +// PSHUFB 16 byte reversal proposed in the +// original Intel paper. +DATA r2r1kp<>+0(SB)/8, $0x154442bd4 +DATA r2r1kp<>+8(SB)/8, $0x1c6e41596 +DATA r4r3kp<>+0(SB)/8, $0x1751997d0 +DATA r4r3kp<>+8(SB)/8, $0x0ccaa009e +DATA rupolykp<>+0(SB)/8, $0x1db710641 +DATA rupolykp<>+8(SB)/8, $0x1f7011641 +DATA r5kp<>+0(SB)/8, $0x163cd6124 + +GLOBL r2r1kp<>(SB), RODATA, $16 +GLOBL r4r3kp<>(SB), RODATA, $16 +GLOBL rupolykp<>(SB), RODATA, $16 +GLOBL r5kp<>(SB), RODATA, $8 + +// Based on http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf +// len(p) must be at least 64, and must be a multiple of 16. + +// func ieeeCLMUL(crc uint32, p []byte) uint32 +TEXT ·ieeeCLMUL(SB), NOSPLIT, $0 + MOVL crc+0(FP), X0 // Initial CRC value + MOVQ p+8(FP), SI // data pointer + MOVQ p_len+16(FP), CX // len(p) + + MOVOU (SI), X1 + MOVOU 16(SI), X2 + MOVOU 32(SI), X3 + MOVOU 48(SI), X4 + PXOR X0, X1 + ADDQ $64, SI // buf+=64 + SUBQ $64, CX // len-=64 + CMPQ CX, $64 // Less than 64 bytes left + JB remain64 + + MOVOU r2r1kp<>+0(SB), X0 + +loopback64: + MOVOA X1, X5 + MOVOA X2, X6 + MOVOA X3, X7 + MOVOA X4, X8 + + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0, X0, X2 + PCLMULQDQ $0, X0, X3 + PCLMULQDQ $0, X0, X4 + + // Load next early + MOVOU (SI), X11 + MOVOU 16(SI), X12 + MOVOU 32(SI), X13 + MOVOU 48(SI), X14 + + PCLMULQDQ $0x11, X0, X5 + PCLMULQDQ $0x11, X0, X6 + PCLMULQDQ $0x11, X0, X7 + PCLMULQDQ $0x11, X0, X8 + + PXOR X5, X1 + PXOR X6, X2 + PXOR X7, X3 + PXOR X8, X4 + + PXOR X11, X1 + PXOR X12, X2 + PXOR X13, X3 + PXOR X14, X4 + + ADDQ $0x40, DI + ADDQ $64, SI // buf+=64 + SUBQ $64, CX // len-=64 + CMPQ CX, $64 // Less than 64 bytes left? + JGE loopback64 + + // Fold result into a single register (X1) +remain64: + MOVOU r4r3kp<>+0(SB), X0 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X2, X1 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X3, X1 + + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X4, X1 + + // More than 16 bytes left? + CMPQ CX, $16 + JB finish + + // Encode 16 bytes +remain16: + MOVOU (SI), X10 + MOVOA X1, X5 + PCLMULQDQ $0, X0, X1 + PCLMULQDQ $0x11, X0, X5 + PXOR X5, X1 + PXOR X10, X1 + SUBQ $16, CX + ADDQ $16, SI + CMPQ CX, $16 + JGE remain16 + +finish: + // Fold final result into 32 bits and return it + PCMPEQB X3, X3 + PCLMULQDQ $1, X1, X0 + PSRLDQ $8, X1 + PXOR X0, X1 + + MOVOA X1, X2 + MOVQ r5kp<>+0(SB), X0 + + // Creates 32 bit mask. Note that we don't care about upper half. + PSRLQ $32, X3 + + PSRLDQ $4, X2 + PAND X3, X1 + PCLMULQDQ $0, X0, X1 + PXOR X2, X1 + + MOVOU rupolykp<>+0(SB), X0 + + MOVOA X1, X2 + PAND X3, X1 + PCLMULQDQ $0x10, X0, X1 + PAND X3, X1 + PCLMULQDQ $0, X0, X1 + PXOR X2, X1 + + // PEXTRD $1, X1, AX (SSE 4.1) + BYTE $0x66; BYTE $0x0f; BYTE $0x3a + BYTE $0x16; BYTE $0xc8; BYTE $0x01 + MOVL AX, ret+32(FP) + + RET diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64p32.go b/vendor/github.com/klauspost/crc32/crc32_amd64p32.go new file mode 100644 index 000000000..f1d096e33 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32_amd64p32.go @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +// +build !appengine,!gccgo + +package crc32 + +// This file contains the code to call the SSE 4.2 version of the Castagnoli +// CRC. + +// haveSSE42 is defined in crc_amd64p32.s and uses CPUID to test for 4.2 +// support. +func haveSSE42() bool + +// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32 +// instruction. +func castagnoliSSE42(crc uint32, p []byte) uint32 + +var sse42 = haveSSE42() + +func updateCastagnoli(crc uint32, p []byte) uint32 { + if sse42 { + return castagnoliSSE42(crc, p) + } + return update(crc, castagnoliTable, p) +} + +func updateIEEE(crc uint32, p []byte) uint32 { + // only use slicing-by-8 when input is >= 4KB + if len(p) >= 4096 { + iEEETable8Once.Do(func() { + iEEETable8 = makeTable8(IEEE) + }) + return updateSlicingBy8(crc, iEEETable8, p) + } + + return update(crc, IEEETable, p) +} diff --git a/vendor/github.com/klauspost/crc32/crc32_amd64p32.s b/vendor/github.com/klauspost/crc32/crc32_amd64p32.s new file mode 100644 index 000000000..a578d685c --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32_amd64p32.s @@ -0,0 +1,67 @@ +// Copyright 2011 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. + +// +build gc + +#define NOSPLIT 4 +#define RODATA 8 + +// func castagnoliSSE42(crc uint32, p []byte) uint32 +TEXT ·castagnoliSSE42(SB), NOSPLIT, $0 + MOVL crc+0(FP), AX // CRC value + MOVL p+4(FP), SI // data pointer + MOVL p_len+8(FP), CX // len(p) + + NOTL AX + + // If there's less than 8 bytes to process, we do it byte-by-byte. + CMPQ CX, $8 + JL cleanup + + // Process individual bytes until the input is 8-byte aligned. +startup: + MOVQ SI, BX + ANDQ $7, BX + JZ aligned + + CRC32B (SI), AX + DECQ CX + INCQ SI + JMP startup + +aligned: + // The input is now 8-byte aligned and we can process 8-byte chunks. + CMPQ CX, $8 + JL cleanup + + CRC32Q (SI), AX + ADDQ $8, SI + SUBQ $8, CX + JMP aligned + +cleanup: + // We may have some bytes left over that we process one at a time. + CMPQ CX, $0 + JE done + + CRC32B (SI), AX + INCQ SI + DECQ CX + JMP cleanup + +done: + NOTL AX + MOVL AX, ret+16(FP) + RET + +// func haveSSE42() bool +TEXT ·haveSSE42(SB), NOSPLIT, $0 + XORQ AX, AX + INCL AX + CPUID + SHRQ $20, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + diff --git a/vendor/github.com/klauspost/crc32/crc32_generic.go b/vendor/github.com/klauspost/crc32/crc32_generic.go new file mode 100644 index 000000000..817058901 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/crc32_generic.go @@ -0,0 +1,28 @@ +// Copyright 2011 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. + +// +build !amd64,!amd64p32 appengine gccgo + +package crc32 + +// The file contains the generic version of updateCastagnoli which does +// slicing-by-8, or uses the fallback for very small sizes. +func updateCastagnoli(crc uint32, p []byte) uint32 { + // only use slicing-by-8 when input is >= 16 Bytes + if len(p) >= 16 { + return updateSlicingBy8(crc, castagnoliTable8, p) + } + return update(crc, castagnoliTable, p) +} + +func updateIEEE(crc uint32, p []byte) uint32 { + // only use slicing-by-8 when input is >= 16 Bytes + if len(p) >= 16 { + iEEETable8Once.Do(func() { + iEEETable8 = makeTable8(IEEE) + }) + return updateSlicingBy8(crc, iEEETable8, p) + } + return update(crc, IEEETable, p) +} diff --git a/vendor/github.com/klauspost/pgzip/.gitignore b/vendor/github.com/klauspost/pgzip/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/klauspost/pgzip/.travis.yml b/vendor/github.com/klauspost/pgzip/.travis.yml new file mode 100644 index 000000000..7c37376e6 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/.travis.yml @@ -0,0 +1,13 @@ +language: go + +sudo: false + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: + - go test -v -cpu=1,2,4 . + - go test -v -cpu=2 -race -short . diff --git a/vendor/github.com/klauspost/pgzip/GO_LICENSE b/vendor/github.com/klauspost/pgzip/GO_LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/GO_LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/pgzip/LICENSE b/vendor/github.com/klauspost/pgzip/LICENSE new file mode 100644 index 000000000..2bdc0d751 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Klaus Post + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/klauspost/pgzip/README.md b/vendor/github.com/klauspost/pgzip/README.md new file mode 100644 index 000000000..c312f53f7 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/README.md @@ -0,0 +1,115 @@ +pgzip +===== + +Go parallel gzip compression/decompression. This is a fully gzip compatible drop in replacement for "compress/gzip". + +This will split compression into blocks that are compressed in parallel. This can be useful for compressing big amounts of data. The output is a standard gzip file. + +The gzip decompression is modified so it decompresses ahead of the current reader. This means that reads will be non-blocking if the decompressor can keep ahead of your code reading from it. CRC calculation also takes place in a separate goroutine. + +You should only use this if you are (de)compressing big amounts of data, say **more than 1MB** at the time, otherwise you will not see any benefit, and it will likely be faster to use the internal gzip library. + +It is important to note that this library creates and reads *standard gzip files*. You do not have to match the compressor/decompressor to get the described speedups, and the gzip files are fully compatible with other gzip readers/writers. + +A golang variant of this is [bgzf](https://godoc.org/github.com/biogo/hts/bgzf), which has the same feature, as well as seeking in the resulting file. The only drawback is a slightly bigger overhead compared to this and pure gzip. See a comparison below. + +[![GoDoc][1]][2] [![Build Status][3]][4] + +[1]: https://godoc.org/github.com/klauspost/pgzip?status.svg +[2]: https://godoc.org/github.com/klauspost/pgzip +[3]: https://travis-ci.org/klauspost/pgzip.svg +[4]: https://travis-ci.org/klauspost/pgzip + +Installation +==== +```go get github.com/klauspost/pgzip``` + +Usage +==== +[Godoc Doumentation](https://godoc.org/github.com/klauspost/pgzip) + +To use as a replacement for gzip, exchange + +```import "compress/gzip"``` +with +```import gzip "github.com/klauspost/pgzip"```. + +# Changes + +* Dec 8, 2015: Decoder now supports the io.WriterTo interface, giving a speedup and less GC pressure. +* Oct 9, 2015: Reduced allocations by ~35 by using sync.Pool. ~15% overall speedup. + +Changes in [github.com/klauspost/compress](https://github.com/klauspost/compress#changelog) are also carried over, so see that for more changes. + +## Compression +The simplest way to use this is to simply do the same as you would when using [compress/gzip](http://golang.org/pkg/compress/gzip). + +To change the block size, use the added (*pgzip.Writer).SetConcurrency(blockSize, blocks int) function. With this you can control the approximate size of your blocks, as well as how many you want to be processing in parallel. Default values for this is SetConcurrency(250000, 16), meaning blocks are split at 250000 bytes and up to 16 blocks can be processing at once before the writer blocks. + + +Example: +``` +var b bytes.Buffer +w := gzip.NewWriter(&b) +w.SetConcurrency(100000, 10) +w.Write([]byte("hello, world\n")) +w.Close() +``` + +To get any performance gains, you should at least be compressing more than 1 megabyte of data at the time. + +You should at least have a block size of 100k and at least a number of blocks that match the number of cores your would like to utilize, but about twice the number of blocks would be the best. + +Another side effect of this is, that it is likely to speed up your other code, since writes to the compressor only blocks if the compressor is already compressing the number of blocks you have specified. This also means you don't have worry about buffering input to the compressor. + +## Decompression + +Decompression works similar to compression. That means that you simply call pgzip the same way as you would call [compress/gzip](http://golang.org/pkg/compress/gzip). + +The only difference is that if you want to specify your own readahead, you have to use `pgzip.NewReaderN(r io.Reader, blockSize, blocks int)` to get a reader with your custom blocksizes. The `blockSize` is the size of each block decoded, and `blocks` is the maximum number of blocks that is decoded ahead. + +See [Example on playground](http://play.golang.org/p/uHv1B5NbDh) + +Performance +==== +## Compression + +See my blog post in [Benchmarks of Golang Gzip](https://blog.klauspost.com/go-gzipdeflate-benchmarks/). + +Compression cost is usually about 0.2% with default settings with a block size of 250k. + +Example with GOMAXPROC set to 8 (quad core with 8 hyperthreads) + +Content is [Matt Mahoneys 10GB corpus](http://mattmahoney.net/dc/10gb.html). Compression level 6. + +Compressor | MB/sec | speedup | size | size overhead (lower=better) +------------|----------|---------|------|--------- +[gzip](http://golang.org/pkg/compress/gzip) (golang) | 7.21MB/s | 1.0x | 4786608902 | 0% +[gzip](http://github.com/klauspost/compress/gzip) (klauspost) | 10.98MB/s | 1.52x | 4781331645 | -0.11% +[pgzip](https://github.com/klauspost/pgzip) (klauspost) | 50.76MB/s|7.04x | 4784121440 | -0.052% +[bgzf](https://godoc.org/github.com/biogo/hts/bgzf) (biogo) | 38.65MB/s | 5.36x | 4924899484 | 2.889% +[pargzip](https://godoc.org/github.com/golang/build/pargzip) (builder) | 32.00MB/s | 4.44x | 4791226567 | 0.096% + +pgzip also contains a [linear time compression](https://github.com/klauspost/compress#linear-time-compression) mode, that will allow compression at ~150MB per core per second, independent of the content. + +See the [complete sheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing) for different content types and compression settings. + +## Decompression + +The decompression speedup is there because it allows you to do other work while the decompression is taking place. + +In the example above, the numbers are as follows on a 4 CPU machine: + +Decompressor | Time | Speedup +-------------|------|-------- +[gzip](http://golang.org/pkg/compress/gzip) (golang) | 1m28.85s | 0% +[pgzip](https://github.com/klauspost/pgzip) (golang) | 43.48s | 104% + +But wait, since gzip decompression is inherently singlethreaded (aside from CRC calculation) how can it be more than 100% faster? Because pgzip due to its design also acts as a buffer. When using ubuffered gzip, you are also waiting for io when you are decompressing. If the gzip decoder can keep up, it will always have data ready for your reader, and you will not be waiting for input to the gzip decompressor to complete. + +This is pretty much an optimal situation for pgzip, but it reflects most common usecases for CPU intensive gzip usage. + +I haven't included [bgzf](https://godoc.org/github.com/biogo/hts/bgzf) in this comparision, since it only can decompress files created by a compatible encoder, and therefore cannot be considered a generic gzip decompressor. But if you are able to compress your files with a bgzf compatible program, you can expect it to scale beyond 100%. + +#License +This contains large portions of code from the go repository - see GO_LICENSE for more information. The changes are released under MIT License. See LICENSE for more information. diff --git a/vendor/github.com/klauspost/pgzip/circle.yml b/vendor/github.com/klauspost/pgzip/circle.yml new file mode 100644 index 000000000..67b2b1628 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/circle.yml @@ -0,0 +1,7 @@ +test: + pre: + - go vet ./... + + override: + - go test -v -cpu=1,2,4 . + - go test -v -cpu=2 -race -short . \ No newline at end of file diff --git a/vendor/github.com/klauspost/pgzip/gunzip.go b/vendor/github.com/klauspost/pgzip/gunzip.go new file mode 100644 index 000000000..45b846e02 --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/gunzip.go @@ -0,0 +1,564 @@ +// 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. + +// Package pgzip implements reading and writing of gzip format compressed files, +// as specified in RFC 1952. +// +// This is a drop in replacement for "compress/gzip". +// This will split compression into blocks that are compressed in parallel. +// This can be useful for compressing big amounts of data. +// The gzip decompression has not been modified, but remains in the package, +// so you can use it as a complete replacement for "compress/gzip". +// +// See more at https://github.com/klauspost/pgzip +package pgzip + +import ( + "bufio" + "errors" + "hash" + "io" + "sync" + "time" + + "github.com/klauspost/compress/flate" + "github.com/klauspost/crc32" +) + +const ( + gzipID1 = 0x1f + gzipID2 = 0x8b + gzipDeflate = 8 + flagText = 1 << 0 + flagHdrCrc = 1 << 1 + flagExtra = 1 << 2 + flagName = 1 << 3 + flagComment = 1 << 4 +) + +func makeReader(r io.Reader) flate.Reader { + if rr, ok := r.(flate.Reader); ok { + return rr + } + return bufio.NewReader(r) +} + +var ( + // ErrChecksum is returned when reading GZIP data that has an invalid checksum. + ErrChecksum = errors.New("gzip: invalid checksum") + // ErrHeader is returned when reading GZIP data that has an invalid header. + ErrHeader = errors.New("gzip: invalid header") +) + +// The gzip file stores a header giving metadata about the compressed file. +// That header is exposed as the fields of the Writer and Reader structs. +type Header struct { + Comment string // comment + Extra []byte // "extra data" + ModTime time.Time // modification time + Name string // file name + OS byte // operating system type +} + +// A Reader is an io.Reader that can be read to retrieve +// uncompressed data from a gzip-format compressed file. +// +// In general, a gzip file can be a concatenation of gzip files, +// each with its own header. Reads from the Reader +// return the concatenation of the uncompressed data of each. +// Only the first header is recorded in the Reader fields. +// +// Gzip files store a length and checksum of the uncompressed data. +// The Reader will return a ErrChecksum when Read +// reaches the end of the uncompressed data if it does not +// have the expected length or checksum. Clients should treat data +// returned by Read as tentative until they receive the io.EOF +// marking the end of the data. +type Reader struct { + Header + r flate.Reader + decompressor io.ReadCloser + digest hash.Hash32 + size uint32 + flg byte + buf [512]byte + err error + closeErr chan error + multistream bool + + readAhead chan read + roff int // read offset + current []byte + closeReader chan struct{} + lastBlock bool + blockSize int + blocks int + + activeRA bool // Indication if readahead is active + mu sync.Mutex // Lock for above + + blockPool chan []byte +} + +type read struct { + b []byte + err error +} + +// NewReader creates a new Reader reading the given reader. +// The implementation buffers input and may read more data than necessary from r. +// It is the caller's responsibility to call Close on the Reader when done. +func NewReader(r io.Reader) (*Reader, error) { + z := new(Reader) + z.blocks = defaultBlocks + z.blockSize = defaultBlockSize + z.r = makeReader(r) + z.digest = crc32.NewIEEE() + z.multistream = true + z.blockPool = make(chan []byte, z.blocks) + for i := 0; i < z.blocks; i++ { + z.blockPool <- make([]byte, z.blockSize) + } + if err := z.readHeader(true); err != nil { + return nil, err + } + return z, nil +} + +// NewReaderN creates a new Reader reading the given reader. +// The implementation buffers input and may read more data than necessary from r. +// It is the caller's responsibility to call Close on the Reader when done. +// +// With this you can control the approximate size of your blocks, +// as well as how many blocks you want to have prefetched. +// +// Default values for this is blockSize = 250000, blocks = 16, +// meaning up to 16 blocks of maximum 250000 bytes will be +// prefetched. +func NewReaderN(r io.Reader, blockSize, blocks int) (*Reader, error) { + z := new(Reader) + z.blocks = blocks + z.blockSize = blockSize + z.r = makeReader(r) + z.digest = crc32.NewIEEE() + z.multistream = true + + // Account for too small values + if z.blocks <= 0 { + z.blocks = defaultBlocks + } + if z.blockSize <= 512 { + z.blockSize = defaultBlockSize + } + z.blockPool = make(chan []byte, z.blocks) + for i := 0; i < z.blocks; i++ { + z.blockPool <- make([]byte, z.blockSize) + } + if err := z.readHeader(true); err != nil { + return nil, err + } + return z, nil +} + +// Reset discards the Reader z's state and makes it equivalent to the +// result of its original state from NewReader, but reading from r instead. +// This permits reusing a Reader rather than allocating a new one. +func (z *Reader) Reset(r io.Reader) error { + z.killReadAhead() + z.r = makeReader(r) + z.digest = crc32.NewIEEE() + z.size = 0 + z.err = nil + z.multistream = true + + // Account for uninitialized values + if z.blocks <= 0 { + z.blocks = defaultBlocks + } + if z.blockSize <= 512 { + z.blockSize = defaultBlockSize + } + + if z.blockPool == nil { + z.blockPool = make(chan []byte, z.blocks) + for i := 0; i < z.blocks; i++ { + z.blockPool <- make([]byte, z.blockSize) + } + } + + return z.readHeader(true) +} + +// Multistream controls whether the reader supports multistream files. +// +// If enabled (the default), the Reader expects the input to be a sequence +// of individually gzipped data streams, each with its own header and +// trailer, ending at EOF. The effect is that the concatenation of a sequence +// of gzipped files is treated as equivalent to the gzip of the concatenation +// of the sequence. This is standard behavior for gzip readers. +// +// Calling Multistream(false) disables this behavior; disabling the behavior +// can be useful when reading file formats that distinguish individual gzip +// data streams or mix gzip data streams with other data streams. +// In this mode, when the Reader reaches the end of the data stream, +// Read returns io.EOF. If the underlying reader implements io.ByteReader, +// it will be left positioned just after the gzip stream. +// To start the next stream, call z.Reset(r) followed by z.Multistream(false). +// If there is no next stream, z.Reset(r) will return io.EOF. +func (z *Reader) Multistream(ok bool) { + z.multistream = ok +} + +// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950). +func get4(p []byte) uint32 { + return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 +} + +func (z *Reader) readString() (string, error) { + var err error + needconv := false + for i := 0; ; i++ { + if i >= len(z.buf) { + return "", ErrHeader + } + z.buf[i], err = z.r.ReadByte() + if err != nil { + return "", err + } + if z.buf[i] > 0x7f { + needconv = true + } + if z.buf[i] == 0 { + // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1). + if needconv { + s := make([]rune, 0, i) + for _, v := range z.buf[0:i] { + s = append(s, rune(v)) + } + return string(s), nil + } + return string(z.buf[0:i]), nil + } + } +} + +func (z *Reader) read2() (uint32, error) { + _, err := io.ReadFull(z.r, z.buf[0:2]) + if err != nil { + return 0, err + } + return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil +} + +func (z *Reader) readHeader(save bool) error { + z.killReadAhead() + + _, err := io.ReadFull(z.r, z.buf[0:10]) + if err != nil { + return err + } + if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate { + return ErrHeader + } + z.flg = z.buf[3] + if save { + z.ModTime = time.Unix(int64(get4(z.buf[4:8])), 0) + // z.buf[8] is xfl, ignored + z.OS = z.buf[9] + } + z.digest.Reset() + z.digest.Write(z.buf[0:10]) + + if z.flg&flagExtra != 0 { + n, err := z.read2() + if err != nil { + return err + } + data := make([]byte, n) + if _, err = io.ReadFull(z.r, data); err != nil { + return err + } + if save { + z.Extra = data + } + } + + var s string + if z.flg&flagName != 0 { + if s, err = z.readString(); err != nil { + return err + } + if save { + z.Name = s + } + } + + if z.flg&flagComment != 0 { + if s, err = z.readString(); err != nil { + return err + } + if save { + z.Comment = s + } + } + + if z.flg&flagHdrCrc != 0 { + n, err := z.read2() + if err != nil { + return err + } + sum := z.digest.Sum32() & 0xFFFF + if n != sum { + return ErrHeader + } + } + + z.digest.Reset() + z.decompressor = flate.NewReader(z.r) + z.doReadAhead() + return nil +} + +func (z *Reader) killReadAhead() error { + z.mu.Lock() + defer z.mu.Unlock() + if z.activeRA { + if z.closeReader != nil { + close(z.closeReader) + } + + // Wait for decompressor to be closed and return error, if any. + e, ok := <-z.closeErr + z.activeRA = false + if !ok { + // Channel is closed, so if there was any error it has already been returned. + return nil + } + return e + } + return nil +} + +// Starts readahead. +// Will return on error (including io.EOF) +// or when z.closeReader is closed. +func (z *Reader) doReadAhead() { + z.mu.Lock() + defer z.mu.Unlock() + z.activeRA = true + + if z.blocks <= 0 { + z.blocks = defaultBlocks + } + if z.blockSize <= 512 { + z.blockSize = defaultBlockSize + } + ra := make(chan read, z.blocks) + z.readAhead = ra + closeReader := make(chan struct{}, 0) + z.closeReader = closeReader + z.lastBlock = false + closeErr := make(chan error, 1) + z.closeErr = closeErr + z.size = 0 + z.roff = 0 + z.current = nil + decomp := z.decompressor + + go func() { + defer func() { + closeErr <- decomp.Close() + close(closeErr) + close(ra) + }() + + // We hold a local reference to digest, since + // it way be changed by reset. + digest := z.digest + var wg sync.WaitGroup + for { + var buf []byte + select { + case buf = <-z.blockPool: + case <-closeReader: + return + } + buf = buf[0:z.blockSize] + // Try to fill the buffer + n, err := io.ReadFull(decomp, buf) + if err == io.ErrUnexpectedEOF { + err = nil + } + if n < len(buf) { + buf = buf[0:n] + } + wg.Wait() + wg.Add(1) + go func() { + digest.Write(buf) + wg.Done() + }() + z.size += uint32(n) + + // If we return any error, out digest must be ready + if err != nil { + wg.Wait() + } + select { + case z.readAhead <- read{b: buf, err: err}: + case <-closeReader: + // Sent on close, we don't care about the next results + return + } + if err != nil { + return + } + } + }() +} + +func (z *Reader) Read(p []byte) (n int, err error) { + if z.err != nil { + return 0, z.err + } + if len(p) == 0 { + return 0, nil + } + + for { + if len(z.current) == 0 && !z.lastBlock { + read := <-z.readAhead + + if read.err != nil { + // If not nil, the reader will have exited + z.closeReader = nil + + if read.err != io.EOF { + z.err = read.err + return + } + if read.err == io.EOF { + z.lastBlock = true + err = nil + } + } + z.current = read.b + z.roff = 0 + } + avail := z.current[z.roff:] + if len(p) >= len(avail) { + // If len(p) >= len(current), return all content of current + n = copy(p, avail) + z.blockPool <- z.current + z.current = nil + if z.lastBlock { + err = io.EOF + break + } + } else { + // We copy as much as there is space for + n = copy(p, avail) + z.roff += n + } + return + } + + // Finished file; check checksum + size. + if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil { + z.err = err + return 0, err + } + crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8]) + sum := z.digest.Sum32() + if sum != crc32 || isize != z.size { + z.err = ErrChecksum + return 0, z.err + } + + // File is ok; should we attempt reading one more? + if !z.multistream { + return 0, io.EOF + } + + // Is there another? + if err = z.readHeader(false); err != nil { + z.err = err + return + } + + // Yes. Reset and read from it. + return z.Read(p) +} + +func (z *Reader) WriteTo(w io.Writer) (n int64, err error) { + total := int64(0) + for { + if z.err != nil { + return total, z.err + } + // We write both to output and digest. + for { + // Read from input + read := <-z.readAhead + if read.err != nil { + // If not nil, the reader will have exited + z.closeReader = nil + + if read.err != io.EOF { + z.err = read.err + return total, z.err + } + if read.err == io.EOF { + z.lastBlock = true + err = nil + } + } + // Write what we got + n, err := w.Write(read.b) + if n != len(read.b) { + return total, io.ErrShortWrite + } + total += int64(n) + if err != nil { + return total, err + } + // Put block back + z.blockPool <- read.b + if z.lastBlock { + break + } + } + + // Finished file; check checksum + size. + if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil { + z.err = err + return total, err + } + crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8]) + sum := z.digest.Sum32() + if sum != crc32 || isize != z.size { + z.err = ErrChecksum + return total, z.err + } + // File is ok; should we attempt reading one more? + if !z.multistream { + return total, nil + } + + // Is there another? + err = z.readHeader(false) + if err == io.EOF { + return total, nil + } + if err != nil { + z.err = err + return total, err + } + } +} + +// Close closes the Reader. It does not close the underlying io.Reader. +func (z *Reader) Close() error { + return z.killReadAhead() +} diff --git a/vendor/github.com/klauspost/pgzip/gzip.go b/vendor/github.com/klauspost/pgzip/gzip.go new file mode 100644 index 000000000..872afe7eb --- /dev/null +++ b/vendor/github.com/klauspost/pgzip/gzip.go @@ -0,0 +1,485 @@ +// Copyright 2010 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. + +package pgzip + +import ( + "bytes" + "errors" + "fmt" + "hash" + "io" + "sync" + + "github.com/klauspost/compress/flate" + "github.com/klauspost/crc32" +) + +const ( + defaultBlockSize = 250000 + tailSize = 16384 + defaultBlocks = 16 +) + +// These constants are copied from the flate package, so that code that imports +// "compress/gzip" does not also have to import "compress/flate". +const ( + NoCompression = flate.NoCompression + BestSpeed = flate.BestSpeed + BestCompression = flate.BestCompression + DefaultCompression = flate.DefaultCompression + ConstantCompression = flate.ConstantCompression +) + +// A Writer is an io.WriteCloser. +// Writes to a Writer are compressed and written to w. +type Writer struct { + Header + w io.Writer + level int + wroteHeader bool + blockSize int + blocks int + currentBuffer []byte + prevTail []byte + digest hash.Hash32 + size int + closed bool + buf [10]byte + err error + pushedErr chan error + results chan result + dictFlatePool *sync.Pool + dstPool *sync.Pool +} + +type result struct { + result chan []byte + notifyWritten chan struct{} +} + +// Use SetConcurrency to finetune the concurrency level if needed. +// +// With this you can control the approximate size of your blocks, +// as well as how many you want to be processing in parallel. +// +// Default values for this is SetConcurrency(250000, 16), +// meaning blocks are split at 250000 bytes and up to 16 blocks +// can be processing at once before the writer blocks. +func (z *Writer) SetConcurrency(blockSize, blocks int) error { + if blockSize <= tailSize { + return fmt.Errorf("gzip: block size cannot be less than or equal to %d", tailSize) + } + if blocks <= 0 { + return errors.New("gzip: blocks cannot be zero or less") + } + z.blockSize = blockSize + z.results = make(chan result, blocks) + z.blocks = blocks + return nil +} + +// NewWriter returns a new Writer. +// Writes to the returned writer are compressed and written to w. +// +// It is the caller's responsibility to call Close on the WriteCloser when done. +// Writes may be buffered and not flushed until Close. +// +// Callers that wish to set the fields in Writer.Header must do so before +// the first call to Write or Close. The Comment and Name header fields are +// UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO +// 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an +// error on Write. +func NewWriter(w io.Writer) *Writer { + z, _ := NewWriterLevel(w, DefaultCompression) + return z +} + +// NewWriterLevel is like NewWriter but specifies the compression level instead +// of assuming DefaultCompression. +// +// The compression level can be DefaultCompression, NoCompression, or any +// integer value between BestSpeed and BestCompression inclusive. The error +// returned will be nil if the level is valid. +func NewWriterLevel(w io.Writer, level int) (*Writer, error) { + if level < ConstantCompression || level > BestCompression { + return nil, fmt.Errorf("gzip: invalid compression level: %d", level) + } + z := new(Writer) + z.SetConcurrency(defaultBlockSize, defaultBlocks) + z.init(w, level) + return z, nil +} + +// This function must be used by goroutines to set an +// error condition, since z.err access is restricted +// to the callers goruotine. +func (z *Writer) pushError(err error) { + z.pushedErr <- err + close(z.pushedErr) +} + +func (z *Writer) init(w io.Writer, level int) { + digest := z.digest + if digest != nil { + digest.Reset() + } else { + digest = crc32.NewIEEE() + } + + *z = Writer{ + Header: Header{ + OS: 255, // unknown + }, + w: w, + level: level, + digest: digest, + pushedErr: make(chan error, 1), + results: make(chan result, z.blocks), + blockSize: z.blockSize, + blocks: z.blocks, + } + z.dictFlatePool = &sync.Pool{ + New: func() interface{} { + f, _ := flate.NewWriterDict(w, level, nil) + return f + }, + } + z.dstPool = &sync.Pool{New: func() interface{} { return make([]byte, 0, z.blockSize) }} + +} + +// Reset discards the Writer z's state and makes it equivalent to the +// result of its original state from NewWriter or NewWriterLevel, but +// writing to w instead. This permits reusing a Writer rather than +// allocating a new one. +func (z *Writer) Reset(w io.Writer) { + if z.results != nil && !z.closed { + close(z.results) + } + z.SetConcurrency(defaultBlockSize, defaultBlocks) + z.init(w, z.level) +} + +// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950). +func put2(p []byte, v uint16) { + p[0] = uint8(v >> 0) + p[1] = uint8(v >> 8) +} + +func put4(p []byte, v uint32) { + p[0] = uint8(v >> 0) + p[1] = uint8(v >> 8) + p[2] = uint8(v >> 16) + p[3] = uint8(v >> 24) +} + +// writeBytes writes a length-prefixed byte slice to z.w. +func (z *Writer) writeBytes(b []byte) error { + if len(b) > 0xffff { + return errors.New("gzip.Write: Extra data is too large") + } + put2(z.buf[0:2], uint16(len(b))) + _, err := z.w.Write(z.buf[0:2]) + if err != nil { + return err + } + _, err = z.w.Write(b) + return err +} + +// writeString writes a UTF-8 string s in GZIP's format to z.w. +// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1). +func (z *Writer) writeString(s string) (err error) { + // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII. + needconv := false + for _, v := range s { + if v == 0 || v > 0xff { + return errors.New("gzip.Write: non-Latin-1 header string") + } + if v > 0x7f { + needconv = true + } + } + if needconv { + b := make([]byte, 0, len(s)) + for _, v := range s { + b = append(b, byte(v)) + } + _, err = z.w.Write(b) + } else { + _, err = io.WriteString(z.w, s) + } + if err != nil { + return err + } + // GZIP strings are NUL-terminated. + z.buf[0] = 0 + _, err = z.w.Write(z.buf[0:1]) + return err +} + +// compressCurrent will compress the data currently buffered +// This should only be called from the main writer/flush/closer +func (z *Writer) compressCurrent(flush bool) { + r := result{} + r.result = make(chan []byte, 1) + r.notifyWritten = make(chan struct{}, 0) + z.results <- r + + // If block given is more than twice the block size, split it. + c := z.currentBuffer + if len(c) > z.blockSize*2 { + c = c[:z.blockSize] + go compressBlock(c, z.prevTail, *z, r) + z.prevTail = c[len(c)-tailSize:] + z.currentBuffer = z.currentBuffer[z.blockSize:] + z.compressCurrent(flush) + // Last one flushes if needed + return + } + + go compressBlock(c, z.prevTail, *z, r) + if len(c) > tailSize { + z.prevTail = c[len(c)-tailSize:] + } else { + z.prevTail = nil + } + z.currentBuffer = make([]byte, 0, z.blockSize+(z.blockSize/4)) + + // Wait if flushing + if flush { + _ = <-r.notifyWritten + } +} + +// Returns an error if it has been set. +// Cannot be used by functions that are from internal goroutines. +func (z *Writer) checkError() error { + if z.err != nil { + return z.err + } + select { + case err := <-z.pushedErr: + z.err = err + default: + } + return z.err +} + +// Write writes a compressed form of p to the underlying io.Writer. The +// compressed bytes are not necessarily flushed to output until +// the Writer is closed or Flush() is called. +// +// The function will return quickly, if there are unused buffers. +// The sent slice (p) is copied, and the caller is free to re-use the buffer +// when the function returns. +// +// Errors that occur during compression will be reported later, and a nil error +// does not signify that the compression succeeded (since it is most likely still running) +// That means that the call that returns an error may not be the call that caused it. +// Only Flush and Close functions are guaranteed to return any errors up to that point. +func (z *Writer) Write(p []byte) (int, error) { + if z.checkError() != nil { + return 0, z.err + } + // Write the GZIP header lazily. + if !z.wroteHeader { + z.wroteHeader = true + z.buf[0] = gzipID1 + z.buf[1] = gzipID2 + z.buf[2] = gzipDeflate + z.buf[3] = 0 + if z.Extra != nil { + z.buf[3] |= 0x04 + } + if z.Name != "" { + z.buf[3] |= 0x08 + } + if z.Comment != "" { + z.buf[3] |= 0x10 + } + put4(z.buf[4:8], uint32(z.ModTime.Unix())) + if z.level == BestCompression { + z.buf[8] = 2 + } else if z.level == BestSpeed { + z.buf[8] = 4 + } else { + z.buf[8] = 0 + } + z.buf[9] = z.OS + var n int + n, z.err = z.w.Write(z.buf[0:10]) + if z.err != nil { + return n, z.err + } + if z.Extra != nil { + z.err = z.writeBytes(z.Extra) + if z.err != nil { + return n, z.err + } + } + if z.Name != "" { + z.err = z.writeString(z.Name) + if z.err != nil { + return n, z.err + } + } + if z.Comment != "" { + z.err = z.writeString(z.Comment) + if z.err != nil { + return n, z.err + } + } + // Start receiving data from compressors + go func() { + listen := z.results + for { + r, ok := <-listen + // If closed, we are finished. + if !ok { + return + } + buf := <-r.result + n, err := z.w.Write(buf) + if err != nil { + z.pushError(err) + close(r.notifyWritten) + return + } + if n != len(buf) { + z.pushError(fmt.Errorf("gzip: short write %d should be %d", n, len(buf))) + close(r.notifyWritten) + return + } + z.dstPool.Put(buf) + close(r.notifyWritten) + } + }() + z.currentBuffer = make([]byte, 0, z.blockSize+(z.blockSize/4)) + } + // Handle very large writes in a loop + if len(p) > z.blockSize*z.blocks { + q := p + for len(q) > 0 { + length := len(q) + if length > z.blockSize { + length = z.blockSize + } + z.digest.Write(q[:length]) + z.currentBuffer = append(z.currentBuffer, q[:length]...) + if len(z.currentBuffer) >= z.blockSize { + z.compressCurrent(false) + if z.err != nil { + return len(p) - len(q) - length, z.err + } + } + z.size += length + q = q[length:] + } + return len(p), z.err + } else { + z.size += len(p) + z.digest.Write(p) + z.currentBuffer = append(z.currentBuffer, p...) + if len(z.currentBuffer) >= z.blockSize { + z.compressCurrent(false) + } + return len(p), z.err + } +} + +// Step 1: compresses buffer to buffer +// Step 2: send writer to channel +// Step 3: Close result channel to indicate we are done +func compressBlock(p, prevTail []byte, z Writer, r result) { + defer close(r.result) + buf := z.dstPool.Get().([]byte) + dest := bytes.NewBuffer(buf[:0]) + + compressor := z.dictFlatePool.Get().(*flate.Writer) + compressor.ResetDict(dest, prevTail) + compressor.Write(p) + + err := compressor.Flush() + if err != nil { + z.pushError(err) + return + } + if z.closed { + err = compressor.Close() + if err != nil { + z.pushError(err) + return + } + } + z.dictFlatePool.Put(compressor) + // Read back buffer + buf = dest.Bytes() + r.result <- buf +} + +// Flush flushes any pending compressed data to the underlying writer. +// +// It is useful mainly in compressed network protocols, to ensure that +// a remote reader has enough data to reconstruct a packet. Flush does +// not return until the data has been written. If the underlying +// writer returns an error, Flush returns that error. +// +// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. +func (z *Writer) Flush() error { + if z.checkError() != nil { + return z.err + } + if z.closed { + return nil + } + if !z.wroteHeader { + _, err := z.Write(nil) + if err != nil { + return err + } + } + // We send current block to compression + z.compressCurrent(true) + if z.checkError() != nil { + return z.err + } + + return nil +} + +// UncompressedSize will return the number of bytes written. +// pgzip only, not a function in the official gzip package. +func (z Writer) UncompressedSize() int { + return z.size +} + +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. +func (z *Writer) Close() error { + if z.checkError() != nil { + return z.err + } + if z.closed { + return nil + } + + z.closed = true + if !z.wroteHeader { + z.Write(nil) + if z.err != nil { + return z.err + } + } + z.compressCurrent(true) + if z.checkError() != nil { + return z.err + } + close(z.results) + put4(z.buf[0:4], z.digest.Sum32()) + put4(z.buf[4:8], uint32(z.size)) + _, z.err = z.w.Write(z.buf[0:8]) + return z.err +} diff --git a/vendor/github.com/kr/fs/LICENSE b/vendor/github.com/kr/fs/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/kr/fs/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/kr/fs/Readme b/vendor/github.com/kr/fs/Readme new file mode 100644 index 000000000..c95e13fc8 --- /dev/null +++ b/vendor/github.com/kr/fs/Readme @@ -0,0 +1,3 @@ +Filesystem Package + +http://godoc.org/github.com/kr/fs diff --git a/vendor/github.com/kr/fs/filesystem.go b/vendor/github.com/kr/fs/filesystem.go new file mode 100644 index 000000000..f1c4805fb --- /dev/null +++ b/vendor/github.com/kr/fs/filesystem.go @@ -0,0 +1,36 @@ +package fs + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +// FileSystem defines the methods of an abstract filesystem. +type FileSystem interface { + + // ReadDir reads the directory named by dirname and returns a + // list of directory entries. + ReadDir(dirname string) ([]os.FileInfo, error) + + // Lstat returns a FileInfo describing the named file. If the file is a + // symbolic link, the returned FileInfo describes the symbolic link. Lstat + // makes no attempt to follow the link. + Lstat(name string) (os.FileInfo, error) + + // Join joins any number of path elements into a single path, adding a + // separator if necessary. The result is Cleaned; in particular, all + // empty strings are ignored. + // + // The separator is FileSystem specific. + Join(elem ...string) string +} + +// fs represents a FileSystem provided by the os package. +type fs struct{} + +func (f *fs) ReadDir(dirname string) ([]os.FileInfo, error) { return ioutil.ReadDir(dirname) } + +func (f *fs) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } + +func (f *fs) Join(elem ...string) string { return filepath.Join(elem...) } diff --git a/vendor/github.com/kr/fs/walk.go b/vendor/github.com/kr/fs/walk.go new file mode 100644 index 000000000..6ffa1e0b2 --- /dev/null +++ b/vendor/github.com/kr/fs/walk.go @@ -0,0 +1,95 @@ +// Package fs provides filesystem-related functions. +package fs + +import ( + "os" +) + +// Walker provides a convenient interface for iterating over the +// descendants of a filesystem path. +// Successive calls to the Step method will step through each +// file or directory in the tree, including the root. The files +// are walked in lexical order, which makes the output deterministic +// but means that for very large directories Walker can be inefficient. +// Walker does not follow symbolic links. +type Walker struct { + fs FileSystem + cur item + stack []item + descend bool +} + +type item struct { + path string + info os.FileInfo + err error +} + +// Walk returns a new Walker rooted at root. +func Walk(root string) *Walker { + return WalkFS(root, new(fs)) +} + +// WalkFS returns a new Walker rooted at root on the FileSystem fs. +func WalkFS(root string, fs FileSystem) *Walker { + info, err := fs.Lstat(root) + return &Walker{ + fs: fs, + stack: []item{{root, info, err}}, + } +} + +// Step advances the Walker to the next file or directory, +// which will then be available through the Path, Stat, +// and Err methods. +// It returns false when the walk stops at the end of the tree. +func (w *Walker) Step() bool { + if w.descend && w.cur.err == nil && w.cur.info.IsDir() { + list, err := w.fs.ReadDir(w.cur.path) + if err != nil { + w.cur.err = err + w.stack = append(w.stack, w.cur) + } else { + for i := len(list) - 1; i >= 0; i-- { + path := w.fs.Join(w.cur.path, list[i].Name()) + w.stack = append(w.stack, item{path, list[i], nil}) + } + } + } + + if len(w.stack) == 0 { + return false + } + i := len(w.stack) - 1 + w.cur = w.stack[i] + w.stack = w.stack[:i] + w.descend = true + return true +} + +// Path returns the path to the most recent file or directory +// visited by a call to Step. It contains the argument to Walk +// as a prefix; that is, if Walk is called with "dir", which is +// a directory containing the file "a", Path will return "dir/a". +func (w *Walker) Path() string { + return w.cur.path +} + +// Stat returns info for the most recent file or directory +// visited by a call to Step. +func (w *Walker) Stat() os.FileInfo { + return w.cur.info +} + +// Err returns the error, if any, for the most recent attempt +// by Step to visit a file or directory. If a directory has +// an error, w will not descend into that directory. +func (w *Walker) Err() error { + return w.cur.err +} + +// SkipDir causes the currently visited directory to be skipped. +// If w is not on a directory, SkipDir has no effect. +func (w *Walker) SkipDir() { + w.descend = false +} diff --git a/vendor/github.com/masterzen/simplexml/LICENSE b/vendor/github.com/masterzen/simplexml/LICENSE new file mode 100644 index 000000000..ef51da2b0 --- /dev/null +++ b/vendor/github.com/masterzen/simplexml/LICENSE @@ -0,0 +1,202 @@ + + 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. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/masterzen/simplexml/dom/document.go b/vendor/github.com/masterzen/simplexml/dom/document.go new file mode 100644 index 000000000..d73693c3f --- /dev/null +++ b/vendor/github.com/masterzen/simplexml/dom/document.go @@ -0,0 +1,35 @@ +package dom + +import ( + "bytes" + "fmt" +) + +type Document struct { + root *Element + PrettyPrint bool + Indentation string + DocType bool +} + +func CreateDocument() *Document { + return &Document{ PrettyPrint: false, Indentation: " ", DocType: true } +} + +func (doc *Document) SetRoot(node *Element) { + node.parent = nil + doc.root = node +} + +func (doc *Document) String() string { + var b bytes.Buffer + if doc.DocType { + fmt.Fprintln(&b, ``) + } + + if doc.root != nil { + doc.root.Bytes(&b, doc.PrettyPrint, doc.Indentation, 0) + } + + return string(b.Bytes()) +} diff --git a/vendor/github.com/masterzen/simplexml/dom/element.go b/vendor/github.com/masterzen/simplexml/dom/element.go new file mode 100644 index 000000000..8e2795960 --- /dev/null +++ b/vendor/github.com/masterzen/simplexml/dom/element.go @@ -0,0 +1,200 @@ +package dom + +import ( + "encoding/xml" + "fmt" + "bytes" +) + +type Attr struct { + Name xml.Name // Attribute namespace and name. + Value string // Attribute value. +} + +type Element struct { + name xml.Name + children []*Element + parent *Element + content string + attributes []*Attr + namespaces []*Namespace + document *Document +} + +func CreateElement(n string) *Element { + element := &Element { name: xml.Name { Local: n } } + element.children = make([]*Element, 0, 5) + element.attributes = make([]*Attr, 0, 10) + element.namespaces = make([]*Namespace, 0, 10) + return element +} + +func (node *Element) AddChild(child *Element) *Element { + if child.parent != nil { + child.parent.RemoveChild(child) + } + child.SetParent(node) + node.children = append(node.children, child) + return node +} + +func (node *Element) RemoveChild(child *Element) *Element { + p := -1 + for i, v := range node.children { + if v == child { + p = i + break + } + } + + if p == -1 { + return node + } + + copy(node.children[p:], node.children[p+1:]) + node.children = node.children[0 : len(node.children)-1] + child.parent = nil + return node +} + +func (node *Element) SetAttr(name string, value string) *Element { + // namespaces? + attr := &Attr{ Name: xml.Name { Local: name }, Value: value } + node.attributes = append(node.attributes, attr) + return node +} + +func (node *Element) SetParent(parent *Element) *Element { + node.parent = parent + return node +} + +func (node *Element) SetContent(content string) *Element { + node.content = content + return node +} + +// Add a namespace declaration to this node +func (node *Element) DeclareNamespace(ns Namespace) *Element { + // check if we already have it + prefix := node.namespacePrefix(ns.Uri) + if prefix == ns.Prefix { + return node + } + // add it + node.namespaces = append(node.namespaces, &ns) + return node +} + +func (node *Element) DeclaredNamespaces() []*Namespace { + return node.namespaces +} + +func (node *Element) SetNamespace(prefix string, uri string) { + resolved := node.namespacePrefix(uri) + if resolved == "" { + // we couldn't find the namespace, let's declare it at this node + node.namespaces = append(node.namespaces, &Namespace { Prefix: prefix, Uri: uri }) + } + node.name.Space = uri +} + +func (node *Element) Bytes(out *bytes.Buffer, indent bool, indentType string, level int) { + empty := len(node.children) == 0 && node.content == "" + content := node.content != "" +// children := len(node.children) > 0 +// ns := len(node.namespaces) > 0 +// attrs := len(node.attributes) > 0 + + indentStr := "" + nextLine := "" + if indent { + nextLine = "\n" + for i := 0; i < level; i++ { + indentStr += indentType + } + } + + if node.name.Local != "" { + if len(node.name.Space) > 0 { + // first find if ns has been declared, otherwise + prefix := node.namespacePrefix(node.name.Space) + fmt.Fprintf(out, "%s<%s:%s", indentStr, prefix, node.name.Local) + } else { + fmt.Fprintf(out, "%s<%s", indentStr, node.name.Local) + } + } + + // declared namespaces + for _, v := range node.namespaces { + prefix := node.namespacePrefix(v.Uri) + fmt.Fprintf(out, ` xmlns:%s="%s"`, prefix, v.Uri) + } + + // attributes + for _, v := range node.attributes { + if len(v.Name.Space) > 0 { + prefix := node.namespacePrefix(v.Name.Space) + fmt.Fprintf(out, ` %s:%s="%s"`, prefix, v.Name.Local, v.Value) + } else { + fmt.Fprintf(out, ` %s="%s"`, v.Name.Local, v.Value) + } + } + + // close tag + if empty { + fmt.Fprintf(out, "/>%s", nextLine) + } else { + if content { + out.WriteRune('>') + } else { + fmt.Fprintf(out, ">%s", nextLine) + } + } + + if len(node.children) > 0 { + for _, child := range node.children { + child.Bytes(out, indent, indentType, level + 1) + } + } else if node.content != "" { + //val := []byte(node.content) + //xml.EscapeText(out, val) + out.WriteString(node.content) + } + + if !empty && len(node.name.Local) > 0 { + var indentation string + if content { + indentation = "" + } else { + indentation = indentStr + } + if len(node.name.Space) > 0 { + prefix := node.namespacePrefix(node.name.Space) + fmt.Fprintf(out, "%s\n", indentation, prefix, node.name.Local) + } else { + fmt.Fprintf(out, "%s\n", indentation, node.name.Local) + } + } +} + +// Finds the prefix of the given namespace if it has been declared +// in this node or in one of its parent +func (node *Element) namespacePrefix(uri string) string { + for _, ns := range node.namespaces { + if ns.Uri == uri { + return ns.Prefix + } + } + if node.parent == nil { + return "" + } + return node.parent.namespacePrefix(uri) +} + + +func (node *Element) String() string { + var b bytes.Buffer + node.Bytes(&b, false, "", 0) + return string(b.Bytes()) +} diff --git a/vendor/github.com/masterzen/simplexml/dom/namespace.go b/vendor/github.com/masterzen/simplexml/dom/namespace.go new file mode 100644 index 000000000..3961e654d --- /dev/null +++ b/vendor/github.com/masterzen/simplexml/dom/namespace.go @@ -0,0 +1,10 @@ +package dom + +type Namespace struct { + Prefix string + Uri string +} + +func (ns *Namespace) SetTo(node *Element) { + node.SetNamespace(ns.Prefix, ns.Uri) +} diff --git a/vendor/github.com/masterzen/winrm/LICENSE b/vendor/github.com/masterzen/winrm/LICENSE new file mode 100644 index 000000000..ef51da2b0 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/LICENSE @@ -0,0 +1,202 @@ + + 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. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/masterzen/winrm/soap/header.go b/vendor/github.com/masterzen/winrm/soap/header.go new file mode 100644 index 000000000..1a2ac0881 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/soap/header.go @@ -0,0 +1,181 @@ +package soap + +import ( + "github.com/masterzen/simplexml/dom" + "strconv" +) + +type HeaderOption struct { + key string + value string +} + +func NewHeaderOption(name string, value string) *HeaderOption { + return &HeaderOption{key: name, value: value} +} + +type SoapHeader struct { + to string + replyTo string + maxEnvelopeSize string + timeout string + locale string + id string + action string + shellId string + resourceURI string + options []HeaderOption + message *SoapMessage +} + +type HeaderBuilder interface { + To(string) *SoapHeader + ReplyTo(string) *SoapHeader + MaxEnvelopeSize(int) *SoapHeader + Timeout(string) *SoapHeader + Locale(string) *SoapHeader + Id(string) *SoapHeader + Action(string) *SoapHeader + ShellId(string) *SoapHeader + resourceURI(string) *SoapHeader + AddOption(*HeaderOption) *SoapHeader + Options([]HeaderOption) *SoapHeader + Build(*SoapMessage) *SoapMessage +} + +func (self *SoapHeader) To(uri string) *SoapHeader { + self.to = uri + return self +} + +func (self *SoapHeader) ReplyTo(uri string) *SoapHeader { + self.replyTo = uri + return self +} + +func (self *SoapHeader) MaxEnvelopeSize(size int) *SoapHeader { + self.maxEnvelopeSize = strconv.Itoa(size) + return self +} + +func (self *SoapHeader) Timeout(timeout string) *SoapHeader { + self.timeout = timeout + return self +} + +func (self *SoapHeader) Id(id string) *SoapHeader { + self.id = id + return self +} + +func (self *SoapHeader) Action(action string) *SoapHeader { + self.action = action + return self +} + +func (self *SoapHeader) Locale(locale string) *SoapHeader { + self.locale = locale + return self +} + +func (self *SoapHeader) ShellId(shellId string) *SoapHeader { + self.shellId = shellId + return self +} + +func (self *SoapHeader) ResourceURI(resourceURI string) *SoapHeader { + self.resourceURI = resourceURI + return self +} + +func (self *SoapHeader) AddOption(option *HeaderOption) *SoapHeader { + self.options = append(self.options, *option) + return self +} + +func (self *SoapHeader) Options(options []HeaderOption) *SoapHeader { + self.options = options + return self +} + +func (self *SoapHeader) Build() *SoapMessage { + header := self.createElement(self.message.envelope, "Header", NS_SOAP_ENV) + + if self.to != "" { + to := self.createElement(header, "To", NS_ADDRESSING) + to.SetContent(self.to) + } + + if self.replyTo != "" { + replyTo := self.createElement(header, "ReplyTo", NS_ADDRESSING) + a := self.createMUElement(replyTo, "Address", NS_ADDRESSING, true) + a.SetContent(self.replyTo) + } + + if self.maxEnvelopeSize != "" { + envelope := self.createMUElement(header, "MaxEnvelopeSize", NS_WSMAN_DMTF, true) + envelope.SetContent(self.maxEnvelopeSize) + } + + if self.timeout != "" { + timeout := self.createElement(header, "OperationTimeout", NS_WSMAN_DMTF) + timeout.SetContent(self.timeout) + } + + if self.id != "" { + id := self.createElement(header, "MessageID", NS_ADDRESSING) + id.SetContent(self.id) + } + + if self.locale != "" { + locale := self.createMUElement(header, "Locale", NS_WSMAN_DMTF, false) + locale.SetAttr("xml:lang", self.locale) + datalocale := self.createMUElement(header, "DataLocale", NS_WSMAN_MSFT, false) + datalocale.SetAttr("xml:lang", self.locale) + } + + if self.action != "" { + action := self.createMUElement(header, "Action", NS_ADDRESSING, true) + action.SetContent(self.action) + } + + if self.shellId != "" { + selectorSet := self.createElement(header, "SelectorSet", NS_WSMAN_DMTF) + selector := self.createElement(selectorSet, "Selector", NS_WSMAN_DMTF) + selector.SetAttr("Name", "ShellId") + selector.SetContent(self.shellId) + } + + if self.resourceURI != "" { + resource := self.createMUElement(header, "ResourceURI", NS_WSMAN_DMTF, true) + resource.SetContent(self.resourceURI) + } + + if len(self.options) > 0 { + set := self.createElement(header, "OptionSet", NS_WSMAN_DMTF) + for _, option := range self.options { + e := self.createElement(set, "Option", NS_WSMAN_DMTF) + e.SetAttr("Name", option.key) + e.SetContent(option.value) + } + } + + return self.message +} + +func (self *SoapHeader) createElement(parent *dom.Element, name string, ns dom.Namespace) (element *dom.Element) { + element = dom.CreateElement(name) + parent.AddChild(element) + ns.SetTo(element) + return +} + +func (self *SoapHeader) createMUElement(parent *dom.Element, name string, ns dom.Namespace, mustUnderstand bool) (element *dom.Element) { + element = self.createElement(parent, name, ns) + value := "false" + if mustUnderstand { + value = "true" + } + element.SetAttr("mustUnderstand", value) + return +} diff --git a/vendor/github.com/masterzen/winrm/soap/message.go b/vendor/github.com/masterzen/winrm/soap/message.go new file mode 100644 index 000000000..d06c3085f --- /dev/null +++ b/vendor/github.com/masterzen/winrm/soap/message.go @@ -0,0 +1,74 @@ +package soap + +import ( + "github.com/masterzen/simplexml/dom" +) + +type SoapMessage struct { + document *dom.Document + envelope *dom.Element + header *SoapHeader + body *dom.Element +} + +type MessageBuilder interface { + SetBody(*dom.Element) + NewBody() *dom.Element + CreateElement(*dom.Element, string, dom.Namespace) *dom.Element + CreateBodyElement(string, dom.Namespace) *dom.Element + Header() *SoapHeader + Doc() *dom.Document + Free() + + String() string +} + +func NewMessage() (message *SoapMessage) { + doc := dom.CreateDocument() + e := dom.CreateElement("Envelope") + doc.SetRoot(e) + AddUsualNamespaces(e) + NS_SOAP_ENV.SetTo(e) + + message = &SoapMessage{document: doc, envelope: e} + return +} + +func (message *SoapMessage) NewBody() (body *dom.Element) { + body = dom.CreateElement("Body") + message.envelope.AddChild(body) + NS_SOAP_ENV.SetTo(body) + return +} + +func (message *SoapMessage) String() string { + return message.document.String() +} + +func (message *SoapMessage) Doc() *dom.Document { + return message.document +} + +func (message *SoapMessage) Free() { +} + +func (message *SoapMessage) CreateElement(parent *dom.Element, name string, ns dom.Namespace) (element *dom.Element) { + element = dom.CreateElement(name) + parent.AddChild(element) + ns.SetTo(element) + return +} + +func (message *SoapMessage) CreateBodyElement(name string, ns dom.Namespace) (element *dom.Element) { + if message.body == nil { + message.body = message.NewBody() + } + return message.CreateElement(message.body, name, ns) +} + +func (message *SoapMessage) Header() *SoapHeader { + if message.header == nil { + message.header = &SoapHeader{message: message} + } + return message.header +} diff --git a/vendor/github.com/masterzen/winrm/soap/namespaces.go b/vendor/github.com/masterzen/winrm/soap/namespaces.go new file mode 100644 index 000000000..fda49f49e --- /dev/null +++ b/vendor/github.com/masterzen/winrm/soap/namespaces.go @@ -0,0 +1,37 @@ +package soap + +import ( + "github.com/masterzen/simplexml/dom" + "github.com/masterzen/xmlpath" +) + +var ( + NS_SOAP_ENV = dom.Namespace{"env", "http://www.w3.org/2003/05/soap-envelope"} + NS_ADDRESSING = dom.Namespace{"a", "http://schemas.xmlsoap.org/ws/2004/08/addressing"} + NS_CIMBINDING = dom.Namespace{"b", "http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"} + NS_ENUM = dom.Namespace{"n", "http://schemas.xmlsoap.org/ws/2004/09/enumeration"} + NS_TRANSFER = dom.Namespace{"x", "http://schemas.xmlsoap.org/ws/2004/09/transfer"} + NS_WSMAN_DMTF = dom.Namespace{"w", "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"} + NS_WSMAN_MSFT = dom.Namespace{"p", "http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd"} + NS_SCHEMA_INST = dom.Namespace{"xsi", "http://www.w3.org/2001/XMLSchema-instance"} + NS_WIN_SHELL = dom.Namespace{"rsp", "http://schemas.microsoft.com/wbem/wsman/1/windows/shell"} + NS_WSMAN_FAULT = dom.Namespace{"f", "http://schemas.microsoft.com/wbem/wsman/1/wsmanfault"} +) + +var MostUsed = [...]dom.Namespace{NS_SOAP_ENV, NS_ADDRESSING, NS_WIN_SHELL, NS_WSMAN_DMTF, NS_WSMAN_MSFT} + +func AddUsualNamespaces(node *dom.Element) { + for _, ns := range MostUsed { + node.DeclareNamespace(ns) + } +} + +func GetAllNamespaces() []xmlpath.Namespace { + var ns = []dom.Namespace{NS_WIN_SHELL, NS_ADDRESSING, NS_WSMAN_DMTF, NS_WSMAN_MSFT, NS_SOAP_ENV} + + var xmlpathNs = make([]xmlpath.Namespace, 0, 4) + for _, namespace := range ns { + xmlpathNs = append(xmlpathNs, xmlpath.Namespace{Prefix: namespace.Prefix, Uri: namespace.Uri}) + } + return xmlpathNs +} diff --git a/vendor/github.com/masterzen/winrm/winrm/client.go b/vendor/github.com/masterzen/winrm/winrm/client.go new file mode 100644 index 000000000..a195b6ea6 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/client.go @@ -0,0 +1,166 @@ +package winrm + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "fmt" + "io" + "net/http" + + "github.com/masterzen/winrm/soap" +) + +type Client struct { + Parameters + username string + password string + useHTTPS bool + url string + http HttpPost + transport http.RoundTripper +} + +// NewClient will create a new remote client on url, connecting with user and password +// This function doesn't connect (connection happens only when CreateShell is called) +func NewClient(endpoint *Endpoint, user, password string) (client *Client, err error) { + params := DefaultParameters() + client, err = NewClientWithParameters(endpoint, user, password, params) + return +} + +// NewClient will create a new remote client on url, connecting with user and password +// This function doesn't connect (connection happens only when CreateShell is called) +func NewClientWithParameters(endpoint *Endpoint, user, password string, params *Parameters) (client *Client, err error) { + transport, err := newTransport(endpoint) + + client = &Client{ + Parameters: *params, + username: user, + password: password, + url: endpoint.url(), + http: Http_post, + useHTTPS: endpoint.HTTPS, + transport: transport, + } + + if params.TransportDecorator != nil { + client.transport = params.TransportDecorator(transport) + } + return +} + +// newTransport will create a new HTTP Transport, with options specified within the endpoint configuration +func newTransport(endpoint *Endpoint) (*http.Transport, error) { + transport := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: endpoint.Insecure, + }, + } + + if endpoint.CACert != nil && len(*endpoint.CACert) > 0 { + certPool, err := readCACerts(endpoint.CACert) + if err != nil { + return nil, err + } + + transport.TLSClientConfig.RootCAs = certPool + } + + return transport, nil +} + +func readCACerts(certs *[]byte) (*x509.CertPool, error) { + certPool := x509.NewCertPool() + + if !certPool.AppendCertsFromPEM(*certs) { + return nil, fmt.Errorf("Unable to read certificates") + } + + return certPool, nil +} + +// CreateShell will create a WinRM Shell, which is the prealable for running +// commands. +func (client *Client) CreateShell() (shell *Shell, err error) { + request := NewOpenShellRequest(client.url, &client.Parameters) + defer request.Free() + + response, err := client.sendRequest(request) + if err == nil { + var shellId string + if shellId, err = ParseOpenShellResponse(response); err == nil { + shell = &Shell{client: client, ShellId: shellId} + } + } + return +} + +func (client *Client) sendRequest(request *soap.SoapMessage) (response string, err error) { + return client.http(client, request) +} + +// Run will run command on the the remote host, writing the process stdout and stderr to +// the given writers. Note with this method it isn't possible to inject stdin. +func (client *Client) Run(command string, stdout io.Writer, stderr io.Writer) (exitCode int, err error) { + shell, err := client.CreateShell() + if err != nil { + return 0, err + } + var cmd *Command + cmd, err = shell.Execute(command) + if err != nil { + return 0, err + } + go io.Copy(stdout, cmd.Stdout) + go io.Copy(stderr, cmd.Stderr) + cmd.Wait() + shell.Close() + return cmd.ExitCode(), cmd.err +} + +// Run will run command on the the remote host, returning the process stdout and stderr +// as strings, and using the input stdin string as the process input +func (client *Client) RunWithString(command string, stdin string) (stdout string, stderr string, exitCode int, err error) { + shell, err := client.CreateShell() + if err != nil { + return "", "", 0, err + } + defer shell.Close() + var cmd *Command + cmd, err = shell.Execute(command) + if err != nil { + return "", "", 0, err + } + if len(stdin) > 0 { + cmd.Stdin.Write([]byte(stdin)) + } + var outWriter, errWriter bytes.Buffer + go io.Copy(&outWriter, cmd.Stdout) + go io.Copy(&errWriter, cmd.Stderr) + cmd.Wait() + return outWriter.String(), errWriter.String(), cmd.ExitCode(), cmd.err +} + +// Run will run command on the the remote host, writing the process stdout and stderr to +// the given writers, and injecting the process stdin with the stdin reader. +// Warning stdin (not stdout/stderr) are bufferized, which means reading only one byte in stdin will +// send a winrm http packet to the remote host. If stdin is a pipe, it might be better for +// performance reasons to buffer it. +func (client *Client) RunWithInput(command string, stdout io.Writer, stderr io.Writer, stdin io.Reader) (exitCode int, err error) { + shell, err := client.CreateShell() + if err != nil { + return 0, err + } + defer shell.Close() + var cmd *Command + cmd, err = shell.Execute(command) + if err != nil { + return 0, err + } + go io.Copy(cmd.Stdin, stdin) + go io.Copy(stdout, cmd.Stdout) + go io.Copy(stderr, cmd.Stderr) + cmd.Wait() + return cmd.ExitCode(), cmd.err +} diff --git a/vendor/github.com/masterzen/winrm/winrm/command.go b/vendor/github.com/masterzen/winrm/winrm/command.go new file mode 100644 index 000000000..d8c4a7d31 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/command.go @@ -0,0 +1,210 @@ +package winrm + +import ( + "bytes" + "errors" + "io" + "strings" +) + +type commandWriter struct { + *Command + eof bool +} + +type commandReader struct { + *Command + write *io.PipeWriter + read *io.PipeReader + stream string +} + +// Command represents a given command running on a Shell. This structure allows to get access +// to the various stdout, stderr and stdin pipes. +type Command struct { + client *Client + shell *Shell + commandId string + exitCode int + finished bool + err error + + Stdin *commandWriter + Stdout *commandReader + Stderr *commandReader + + done chan struct{} + cancel chan struct{} +} + +func newCommand(shell *Shell, commandId string) *Command { + command := &Command{shell: shell, client: shell.client, commandId: commandId, exitCode: 1, err: nil, done: make(chan struct{}), cancel: make(chan struct{})} + command.Stdin = &commandWriter{Command: command, eof: false} + command.Stdout = newCommandReader("stdout", command) + command.Stderr = newCommandReader("stderr", command) + + go fetchOutput(command) + + return command +} + +func newCommandReader(stream string, command *Command) *commandReader { + read, write := io.Pipe() + return &commandReader{Command: command, stream: stream, write: write, read: read} +} + +func fetchOutput(command *Command) { + for { + select { + case <-command.cancel: + close(command.done) + return + default: + finished, err := command.slurpAllOutput() + if finished { + command.err = err + close(command.done) + return + } + } + } +} + +func (command *Command) check() (err error) { + if command.commandId == "" { + return errors.New("Command has already been closed") + } + if command.shell == nil { + return errors.New("Command has no associated shell") + } + if command.client == nil { + return errors.New("Command has no associated client") + } + return +} + +// Close will terminate the running command +func (command *Command) Close() (err error) { + if err = command.check(); err != nil { + return err + } + + select { // close cancel channel if it's still open + case <-command.cancel: + default: + close(command.cancel) + } + + request := NewSignalRequest(command.client.url, command.shell.ShellId, command.commandId, &command.client.Parameters) + defer request.Free() + + _, err = command.client.sendRequest(request) + return err +} + +func (command *Command) slurpAllOutput() (finished bool, err error) { + if err = command.check(); err != nil { + command.Stderr.write.CloseWithError(err) + command.Stdout.write.CloseWithError(err) + return true, err + } + + request := NewGetOutputRequest(command.client.url, command.shell.ShellId, command.commandId, "stdout stderr", &command.client.Parameters) + defer request.Free() + + response, err := command.client.sendRequest(request) + if err != nil { + if strings.Contains(err.Error(), "OperationTimeout") { + // Operation timeout because there was no command output + return + } + + command.Stderr.write.CloseWithError(err) + command.Stdout.write.CloseWithError(err) + return true, err + } + + var exitCode int + var stdout, stderr bytes.Buffer + finished, exitCode, err = ParseSlurpOutputErrResponse(response, &stdout, &stderr) + if err != nil { + command.Stderr.write.CloseWithError(err) + command.Stdout.write.CloseWithError(err) + return true, err + } + if stdout.Len() > 0 { + command.Stdout.write.Write(stdout.Bytes()) + } + if stderr.Len() > 0 { + command.Stderr.write.Write(stderr.Bytes()) + } + if finished { + command.exitCode = exitCode + command.Stderr.write.Close() + command.Stdout.write.Close() + } + + return +} + +func (command *Command) sendInput(data []byte) (err error) { + if err = command.check(); err != nil { + return err + } + + request := NewSendInputRequest(command.client.url, command.shell.ShellId, command.commandId, data, &command.client.Parameters) + defer request.Free() + + _, err = command.client.sendRequest(request) + return +} + +// ExitCode returns command exit code when it is finished. Before that the result is always 0. +func (command *Command) ExitCode() int { + return command.exitCode +} + +// Calling this function will block the current goroutine until the remote command terminates. +func (command *Command) Wait() { + // block until finished + <-command.done +} + +// Write data to this Pipe +func (w *commandWriter) Write(data []byte) (written int, err error) { + for len(data) > 0 { + if w.eof { + err = io.EOF + return + } + // never send more data than our EnvelopeSize. + n := min(w.client.Parameters.EnvelopeSize-1000, len(data)) + if err = w.sendInput(data[:n]); err != nil { + break + } + data = data[n:] + written += int(n) + } + return +} + +func min(a int, b int) int { + if a < b { + return a + } + return b +} + +func (w *commandWriter) Close() error { + w.eof = true + return w.Close() +} + +// Read data from this Pipe +func (r *commandReader) Read(buf []byte) (int, error) { + n, err := r.read.Read(buf) + if err != nil && err != io.EOF { + return 0, err + } + return n, err +} diff --git a/vendor/github.com/masterzen/winrm/winrm/endpoint.go b/vendor/github.com/masterzen/winrm/winrm/endpoint.go new file mode 100644 index 000000000..93e255d5e --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/endpoint.go @@ -0,0 +1,22 @@ +package winrm + +import "fmt" + +type Endpoint struct { + Host string + Port int + HTTPS bool + Insecure bool + CACert *[]byte +} + +func (ep *Endpoint) url() string { + var scheme string + if ep.HTTPS { + scheme = "https" + } else { + scheme = "http" + } + + return fmt.Sprintf("%s://%s:%d/wsman", scheme, ep.Host, ep.Port) +} diff --git a/vendor/github.com/masterzen/winrm/winrm/http.go b/vendor/github.com/masterzen/winrm/winrm/http.go new file mode 100644 index 000000000..7e191e364 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/http.go @@ -0,0 +1,60 @@ +package winrm + +import ( + "fmt" + "io/ioutil" + "net/http" + "strings" + + "github.com/masterzen/winrm/soap" +) + +var soapXML string = "application/soap+xml" + +type HttpPost func(*Client, *soap.SoapMessage) (string, error) + +func body(response *http.Response) (content string, err error) { + contentType := response.Header.Get("Content-Type") + if strings.HasPrefix(contentType, soapXML) { + var body []byte + body, err = ioutil.ReadAll(response.Body) + response.Body.Close() + if err != nil { + err = fmt.Errorf("error while reading request body %s", err) + return + } + + content = string(body) + return + } else { + err = fmt.Errorf("invalid content-type: %s", contentType) + return + } + return +} + +func Http_post(client *Client, request *soap.SoapMessage) (response string, err error) { + httpClient := &http.Client{Transport: client.transport} + + req, err := http.NewRequest("POST", client.url, strings.NewReader(request.String())) + if err != nil { + err = fmt.Errorf("impossible to create http request %s", err) + return + } + req.Header.Set("Content-Type", soapXML+";charset=UTF-8") + req.SetBasicAuth(client.username, client.password) + resp, err := httpClient.Do(req) + if err != nil { + err = fmt.Errorf("unknown error %s", err) + return + } + + if resp.StatusCode == 200 { + response, err = body(resp) + } else { + body, _ := ioutil.ReadAll(resp.Body) + err = fmt.Errorf("http error: %d - %s", resp.StatusCode, body) + } + + return +} diff --git a/vendor/github.com/masterzen/winrm/winrm/parameters.go b/vendor/github.com/masterzen/winrm/winrm/parameters.go new file mode 100644 index 000000000..099863b40 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/parameters.go @@ -0,0 +1,20 @@ +package winrm + +import ( + "net/http" +) + +type Parameters struct { + Timeout string + Locale string + EnvelopeSize int + TransportDecorator func(*http.Transport) http.RoundTripper +} + +func DefaultParameters() *Parameters { + return NewParameters("PT60S", "en-US", 153600) +} + +func NewParameters(timeout string, locale string, envelopeSize int) *Parameters { + return &Parameters{Timeout: timeout, Locale: locale, EnvelopeSize: envelopeSize} +} diff --git a/vendor/github.com/masterzen/winrm/winrm/powershell.go b/vendor/github.com/masterzen/winrm/winrm/powershell.go new file mode 100644 index 000000000..5544bc69d --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/powershell.go @@ -0,0 +1,22 @@ +package winrm + +import ( + "encoding/base64" + "fmt" +) + +// Wraps a PowerShell script and prepares it for execution by the winrm client +func Powershell(psCmd string) string { + // 2 byte chars to make PowerShell happy + wideCmd := "" + for _, b := range []byte(psCmd) { + wideCmd += string(b) + "\x00" + } + + // Base64 encode the command + input := []uint8(wideCmd) + encodedCmd := base64.StdEncoding.EncodeToString(input) + + // Create the powershell.exe command line to execute the script + return fmt.Sprintf("powershell.exe -EncodedCommand %s", encodedCmd) +} diff --git a/vendor/github.com/masterzen/winrm/winrm/request.go b/vendor/github.com/masterzen/winrm/winrm/request.go new file mode 100644 index 000000000..f9ad8285b --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/request.go @@ -0,0 +1,116 @@ +package winrm + +import ( + "encoding/base64" + + "github.com/masterzen/winrm/soap" + "github.com/nu7hatch/gouuid" +) + +func genUUID() string { + uuid, _ := uuid.NewV4() + return "uuid:" + uuid.String() +} + +func defaultHeaders(message *soap.SoapMessage, url string, params *Parameters) (h *soap.SoapHeader) { + h = message.Header() + h.To(url).ReplyTo("http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous").MaxEnvelopeSize(params.EnvelopeSize).Id(genUUID()).Locale(params.Locale).Timeout(params.Timeout) + return +} + +func NewOpenShellRequest(uri string, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + defaultHeaders(message, uri, params).Action("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create").ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").AddOption(soap.NewHeaderOption("WINRS_NOPROFILE", "FALSE")).AddOption(soap.NewHeaderOption("WINRS_CODEPAGE", "65001")).Build() + + body := message.CreateBodyElement("Shell", soap.NS_WIN_SHELL) + input := message.CreateElement(body, "InputStreams", soap.NS_WIN_SHELL) + input.SetContent("stdin") + output := message.CreateElement(body, "OutputStreams", soap.NS_WIN_SHELL) + output.SetContent("stdout stderr") + return +} + +func NewDeleteShellRequest(uri string, shellId string, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + defaultHeaders(message, uri, params).Action("http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete").ShellId(shellId).ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").Build() + + message.NewBody() + + return +} + +func NewExecuteCommandRequest(uri, shellId, command string, arguments []string, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + defaultHeaders(message, uri, params).Action("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command").ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").ShellId(shellId).AddOption(soap.NewHeaderOption("WINRS_CONSOLEMODE_STDIN", "TRUE")).AddOption(soap.NewHeaderOption("WINRS_SKIP_CMD_SHELL", "FALSE")).Build() + body := message.CreateBodyElement("CommandLine", soap.NS_WIN_SHELL) + + // ensure special characters like & don't mangle the request XML + command = "" + commandElement := message.CreateElement(body, "Command", soap.NS_WIN_SHELL) + commandElement.SetContent(command) + + for _, arg := range arguments { + arg = "" + argumentsElement := message.CreateElement(body, "Arguments", soap.NS_WIN_SHELL) + argumentsElement.SetContent(arg) + } + + return +} + +func NewGetOutputRequest(uri string, shellId string, commandId string, streams string, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + defaultHeaders(message, uri, params).Action("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive").ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").ShellId(shellId).Build() + + receive := message.CreateBodyElement("Receive", soap.NS_WIN_SHELL) + desiredStreams := message.CreateElement(receive, "DesiredStream", soap.NS_WIN_SHELL) + desiredStreams.SetAttr("CommandId", commandId) + desiredStreams.SetContent(streams) + return +} + +func NewSendInputRequest(uri string, shellId string, commandId string, input []byte, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + + defaultHeaders(message, uri, params).Action("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send").ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").ShellId(shellId).Build() + + content := base64.StdEncoding.EncodeToString(input) + + send := message.CreateBodyElement("Send", soap.NS_WIN_SHELL) + streams := message.CreateElement(send, "Stream", soap.NS_WIN_SHELL) + streams.SetAttr("Name", "stdin") + streams.SetAttr("CommandId", commandId) + streams.SetContent(content) + return +} + +func NewSignalRequest(uri string, shellId string, commandId string, params *Parameters) (message *soap.SoapMessage) { + if params == nil { + params = DefaultParameters() + } + message = soap.NewMessage() + + defaultHeaders(message, uri, params).Action("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal").ResourceURI("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd").ShellId(shellId).Build() + + signal := message.CreateBodyElement("Signal", soap.NS_WIN_SHELL) + signal.SetAttr("CommandId", commandId) + code := message.CreateElement(signal, "Code", soap.NS_WIN_SHELL) + code.SetContent("http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate") + + return +} diff --git a/vendor/github.com/masterzen/winrm/winrm/response.go b/vendor/github.com/masterzen/winrm/winrm/response.go new file mode 100644 index 000000000..ea02a87ae --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/response.go @@ -0,0 +1,111 @@ +package winrm + +import ( + "encoding/base64" + "fmt" + "github.com/masterzen/winrm/soap" + "github.com/masterzen/xmlpath" + "io" + "strconv" + "strings" +) + +func first(node *xmlpath.Node, xpath string) (content string, err error) { + path, err := xmlpath.CompileWithNamespace(xpath, soap.GetAllNamespaces()) + if err != nil { + return + } + content, _ = path.String(node) + return +} + +func any(node *xmlpath.Node, xpath string) (found bool, err error) { + path, err := xmlpath.CompileWithNamespace(xpath, soap.GetAllNamespaces()) + if err != nil { + return + } + + found = path.Exists(node) + return +} + +func xpath(node *xmlpath.Node, xpath string) (nodes []xmlpath.Node, err error) { + path, err := xmlpath.CompileWithNamespace(xpath, soap.GetAllNamespaces()) + if err != nil { + return + } + + nodes = make([]xmlpath.Node, 0, 1) + iter := path.Iter(node) + for iter.Next() { + nodes = append(nodes, *(iter.Node())) + } + return +} + +func ParseOpenShellResponse(response string) (shellId string, err error) { + doc, err := xmlpath.Parse(strings.NewReader(response)) + + shellId, err = first(doc, "//w:Selector[@Name='ShellId']") + return +} + +func ParseExecuteCommandResponse(response string) (commandId string, err error) { + doc, err := xmlpath.Parse(strings.NewReader(response)) + + commandId, err = first(doc, "//rsp:CommandId") + return +} + +func ParseSlurpOutputErrResponse(response string, stdout io.Writer, stderr io.Writer) (finished bool, exitCode int, err error) { + doc, err := xmlpath.Parse(strings.NewReader(response)) + + stdouts, _ := xpath(doc, "//rsp:Stream[@Name='stdout']") + for _, node := range stdouts { + content, _ := base64.StdEncoding.DecodeString(node.String()) + stdout.Write(content) + } + stderrs, _ := xpath(doc, "//rsp:Stream[@Name='stderr']") + for _, node := range stderrs { + content, _ := base64.StdEncoding.DecodeString(node.String()) + stderr.Write(content) + } + + ended, _ := any(doc, "//*[@State='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done']") + + if ended { + finished = ended + if exitBool, _ := any(doc, "//rsp:ExitCode"); exitBool { + exit, _ := first(doc, "//rsp:ExitCode") + exitCode, _ = strconv.Atoi(exit) + } + } else { + finished = false + } + + return +} + +func ParseSlurpOutputResponse(response string, stream io.Writer, streamType string) (finished bool, exitCode int, err error) { + doc, err := xmlpath.Parse(strings.NewReader(response)) + + nodes, _ := xpath(doc, fmt.Sprintf("//rsp:Stream[@Name='%s']", streamType)) + for _, node := range nodes { + content, _ := base64.StdEncoding.DecodeString(node.String()) + stream.Write(content) + } + + ended, _ := any(doc, "//*[@State='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done']") + + if ended { + finished = ended + if exitBool, _ := any(doc, "//rsp:ExitCode"); exitBool { + exit, _ := first(doc, "//rsp:ExitCode") + exitCode, _ = strconv.Atoi(exit) + } + } else { + finished = false + } + + return +} diff --git a/vendor/github.com/masterzen/winrm/winrm/shell.go b/vendor/github.com/masterzen/winrm/winrm/shell.go new file mode 100644 index 000000000..a14518280 --- /dev/null +++ b/vendor/github.com/masterzen/winrm/winrm/shell.go @@ -0,0 +1,31 @@ +package winrm + +// Shell is the local view of a WinRM Shell of a given Client +type Shell struct { + client *Client + ShellId string +} + +// Execute command on the given Shell, returning either an error or a Command +func (shell *Shell) Execute(command string, arguments ...string) (cmd *Command, err error) { + request := NewExecuteCommandRequest(shell.client.url, shell.ShellId, command, arguments, &shell.client.Parameters) + defer request.Free() + + response, err := shell.client.sendRequest(request) + if err == nil { + var commandId string + if commandId, err = ParseExecuteCommandResponse(response); err == nil { + cmd = newCommand(shell, commandId) + } + } + return +} + +// Close will terminate this shell. No commands can be issued once the shell is closed. +func (shell *Shell) Close() (err error) { + request := NewDeleteShellRequest(shell.client.url, shell.ShellId, &shell.client.Parameters) + defer request.Free() + + _, err = shell.client.sendRequest(request) + return +} diff --git a/vendor/github.com/masterzen/xmlpath/LICENSE b/vendor/github.com/masterzen/xmlpath/LICENSE new file mode 100644 index 000000000..53320c352 --- /dev/null +++ b/vendor/github.com/masterzen/xmlpath/LICENSE @@ -0,0 +1,185 @@ +This software is licensed under the LGPLv3, included below. + +As a special exception to the GNU Lesser General Public License version 3 +("LGPL3"), the copyright holders of this Library give you permission to +convey to a third party a Combined Work that links statically or dynamically +to this Library without providing any Minimal Corresponding Source or +Minimal Application Code as set out in 4d or providing the installation +information set out in section 4e, provided that you comply with the other +provisions of LGPL3 and provided that you meet, for the Application the +terms and conditions of the license(s) which apply to the Application. + +Except as stated in this special exception, the provisions of LGPL3 will +continue to comply in full to this Library. If you modify this Library, you +may apply this exception to your version of this Library, but you are not +obliged to do so. If you do not wish to do so, delete this exception +statement from your version. This exception does not (and cannot) modify any +license terms which apply to the Application, with which you must still +comply. + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/github.com/masterzen/xmlpath/doc.go b/vendor/github.com/masterzen/xmlpath/doc.go new file mode 100644 index 000000000..d1acf6c07 --- /dev/null +++ b/vendor/github.com/masterzen/xmlpath/doc.go @@ -0,0 +1,95 @@ +// Package xmlpath implements a strict subset of the XPath specification for the Go language. +// +// The XPath specification is available at: +// +// http://www.w3.org/TR/xpath +// +// Path expressions supported by this package are in the following format, +// with all components being optional: +// +// /axis-name::node-test[predicate]/axis-name::node-test[predicate] +// +// At the moment, xmlpath is compatible with the XPath specification +// to the following extent: +// +// - All axes are supported ("child", "following-sibling", etc) +// - All abbreviated forms are supported (".", "//", etc) +// - All node types except for namespace are supported +// - Predicates are restricted to [N], [path], and [path=literal] forms +// - Only a single predicate is supported per path step +// - Namespaces are experimentally supported +// - Richer expressions +// +// For example, assuming the following document: +// +// +// +// +// 0836217462 +// Being a Dog Is a Full-Time Job +// I'd dog paddle the deepest ocean. +// +// +// Charles M Schulz +// 1922-11-26 +// 2000-02-12 +// +// +// Peppermint Patty +// 1966-08-22 +// bold, brash and tomboyish +// +// +// Snoopy +// 1950-10-04 +// extroverted beagle +// +// +// +// +// The following examples are valid path expressions, and the first +// match has the indicated value: +// +// /library/book/isbn => "0836217462" +// library/*/isbn => "0836217462" +// /library/book/../book/./isbn => "0836217462" +// /library/book/character[2]/name => "Snoopy" +// /library/book/character[born='1950-10-04']/name => "Snoopy" +// /library/book//node()[@id='PP']/name => "Peppermint Patty" +// //book[author/@id='CMS']/title => "Being a Dog Is a Full-Time Job"}, +// /library/book/preceding::comment() => " Great book. " +// +// To run an expression, compile it, and then apply the compiled path to any +// number of context nodes, from one or more parsed xml documents: +// +// path := xmlpath.MustCompile("/library/book/isbn") +// root, err := xmlpath.Parse(file) +// if err != nil { +// log.Fatal(err) +// } +// if value, ok := path.String(root); ok { +// fmt.Println("Found:", value) +// } +// +// To use xmlpath with namespaces, it is required to give the supported set of namespace +// when compiling: +// +// +// var namespaces = []xmlpath.Namespace { +// { "s", "http://www.w3.org/2003/05/soap-envelope" }, +// { "a", "http://schemas.xmlsoap.org/ws/2004/08/addressing" }, +// } +// path, err := xmlpath.CompileWithNamespace("/s:Header/a:To", namespaces) +// if err != nil { +// log.Fatal(err) +// } +// root, err := xmlpath.Parse(file) +// if err != nil { +// log.Fatal(err) +// } +// if value, ok := path.String(root); ok { +// fmt.Println("Found:", value) +// } +// + +package xmlpath diff --git a/vendor/github.com/masterzen/xmlpath/parser.go b/vendor/github.com/masterzen/xmlpath/parser.go new file mode 100644 index 000000000..88c1523a3 --- /dev/null +++ b/vendor/github.com/masterzen/xmlpath/parser.go @@ -0,0 +1,233 @@ +package xmlpath + +import ( + "encoding/xml" + "io" +) + +// Node is an item in an xml tree that was compiled to +// be processed via xml paths. A node may represent: +// +// - An element in the xml document () +// - An attribute of an element in the xml document (href="...") +// - A comment in the xml document () +// - A processing instruction in the xml document () +// - Some text within the xml document +// +type Node struct { + kind nodeKind + name xml.Name + attr string + text []byte + + nodes []Node + pos int + end int + + up *Node + down []*Node +} + +type nodeKind int + +const ( + anyNode nodeKind = iota + startNode + endNode + attrNode + textNode + commentNode + procInstNode +) + +// String returns the string value of node. +// +// The string value of a node is: +// +// - For element nodes, the concatenation of all text nodes within the element. +// - For text nodes, the text itself. +// - For attribute nodes, the attribute value. +// - For comment nodes, the text within the comment delimiters. +// - For processing instruction nodes, the content of the instruction. +// +func (node *Node) String() string { + if node.kind == attrNode { + return node.attr + } + return string(node.Bytes()) +} + +// Bytes returns the string value of node as a byte slice. +// See Node.String for a description of what the string value of a node is. +func (node *Node) Bytes() []byte { + if node.kind == attrNode { + return []byte(node.attr) + } + if node.kind != startNode { + return node.text + } + var text []byte + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + text = append(text, node.nodes[i].text...) + } + } + return text +} + +// equals returns whether the string value of node is equal to s, +// without allocating memory. +func (node *Node) equals(s string) bool { + if node.kind == attrNode { + return s == node.attr + } + if node.kind != startNode { + if len(s) != len(node.text) { + return false + } + for i := range s { + if s[i] != node.text[i] { + return false + } + } + return true + } + si := 0 + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + for _, c := range node.nodes[i].text { + if si > len(s) { + return false + } + if s[si] != c { + return false + } + si++ + } + } + } + return si == len(s) +} + +// Parse reads an xml document from r, parses it, and returns its root node. +func Parse(r io.Reader) (*Node, error) { + return ParseDecoder(xml.NewDecoder(r)) +} + +// ParseHTML reads an HTML-like document from r, parses it, and returns +// its root node. +func ParseHTML(r io.Reader) (*Node, error) { + d := xml.NewDecoder(r) + d.Strict = false + d.AutoClose = xml.HTMLAutoClose + d.Entity = xml.HTMLEntity + return ParseDecoder(d) +} + +// ParseDecoder parses the xml document being decoded by d and returns +// its root node. +func ParseDecoder(d *xml.Decoder) (*Node, error) { + var nodes []Node + var text []byte + + // The root node. + nodes = append(nodes, Node{kind: startNode}) + + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + switch t := t.(type) { + case xml.EndElement: + nodes = append(nodes, Node{ + kind: endNode, + }) + case xml.StartElement: + nodes = append(nodes, Node{ + kind: startNode, + name: t.Name, + }) + for _, attr := range t.Attr { + nodes = append(nodes, Node{ + kind: attrNode, + name: attr.Name, + attr: attr.Value, + }) + } + case xml.CharData: + texti := len(text) + text = append(text, t...) + nodes = append(nodes, Node{ + kind: textNode, + text: text[texti : texti+len(t)], + }) + case xml.Comment: + texti := len(text) + text = append(text, t...) + nodes = append(nodes, Node{ + kind: commentNode, + text: text[texti : texti+len(t)], + }) + case xml.ProcInst: + texti := len(text) + text = append(text, t.Inst...) + nodes = append(nodes, Node{ + kind: procInstNode, + name: xml.Name{Local: t.Target}, + text: text[texti : texti+len(t.Inst)], + }) + } + } + + // Close the root node. + nodes = append(nodes, Node{kind: endNode}) + + stack := make([]*Node, 0, len(nodes)) + downs := make([]*Node, len(nodes)) + downCount := 0 + + for pos := range nodes { + + switch nodes[pos].kind { + + case startNode, attrNode, textNode, commentNode, procInstNode: + node := &nodes[pos] + node.nodes = nodes + node.pos = pos + if len(stack) > 0 { + node.up = stack[len(stack)-1] + } + if node.kind == startNode { + stack = append(stack, node) + } else { + node.end = pos + 1 + } + + case endNode: + node := stack[len(stack)-1] + node.end = pos + stack = stack[:len(stack)-1] + + // Compute downs. Doing that here is what enables the + // use of a slice of a contiguous pre-allocated block. + node.down = downs[downCount:downCount] + for i := node.pos + 1; i < node.end; i++ { + if nodes[i].up == node { + switch nodes[i].kind { + case startNode, textNode, commentNode, procInstNode: + node.down = append(node.down, &nodes[i]) + downCount++ + } + } + } + if len(stack) == 0 { + return node, nil + } + } + } + return nil, io.EOF +} diff --git a/vendor/github.com/masterzen/xmlpath/path.go b/vendor/github.com/masterzen/xmlpath/path.go new file mode 100644 index 000000000..f35af70ae --- /dev/null +++ b/vendor/github.com/masterzen/xmlpath/path.go @@ -0,0 +1,642 @@ +package xmlpath + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +// Namespace represents a given XML Namespace +type Namespace struct { + Prefix string + Uri string +} + +// Path is a compiled path that can be applied to a context +// node to obtain a matching node set. +// A single Path can be applied concurrently to any number +// of context nodes. +type Path struct { + path string + steps []pathStep +} + +// Iter returns an iterator that goes over the list of nodes +// that p matches on the given context. +func (p *Path) Iter(context *Node) *Iter { + iter := Iter{ + make([]pathStepState, len(p.steps)), + make([]bool, len(context.nodes)), + } + for i := range p.steps { + iter.state[i].step = &p.steps[i] + } + iter.state[0].init(context) + return &iter +} + +// Exists returns whether any nodes match p on the given context. +func (p *Path) Exists(context *Node) bool { + return p.Iter(context).Next() +} + +// String returns the string value of the first node matched +// by p on the given context. +// +// See the documentation of Node.String. +func (p *Path) String(context *Node) (s string, ok bool) { + iter := p.Iter(context) + if iter.Next() { + return iter.Node().String(), true + } + return "", false +} + +// Bytes returns as a byte slice the string value of the first +// node matched by p on the given context. +// +// See the documentation of Node.String. +func (p *Path) Bytes(node *Node) (b []byte, ok bool) { + iter := p.Iter(node) + if iter.Next() { + return iter.Node().Bytes(), true + } + return nil, false +} + +// Iter iterates over node sets. +type Iter struct { + state []pathStepState + seen []bool +} + +// Node returns the current node. +// Must only be called after Iter.Next returns true. +func (iter *Iter) Node() *Node { + state := iter.state[len(iter.state)-1] + if state.pos == 0 { + panic("Iter.Node called before Iter.Next") + } + if state.node == nil { + panic("Iter.Node called after Iter.Next false") + } + return state.node +} + +// Next iterates to the next node in the set, if any, and +// returns whether there is a node available. +func (iter *Iter) Next() bool { + tip := len(iter.state) - 1 +outer: + for { + for !iter.state[tip].next() { + tip-- + if tip == -1 { + return false + } + } + for tip < len(iter.state)-1 { + tip++ + iter.state[tip].init(iter.state[tip-1].node) + if !iter.state[tip].next() { + tip-- + continue outer + } + } + if iter.seen[iter.state[tip].node.pos] { + continue + } + iter.seen[iter.state[tip].node.pos] = true + return true + } + panic("unreachable") +} + +type pathStepState struct { + step *pathStep + node *Node + pos int + idx int + aux int +} + +func (s *pathStepState) init(node *Node) { + s.node = node + s.pos = 0 + s.idx = 0 + s.aux = 0 +} + +func (s *pathStepState) next() bool { + for s._next() { + s.pos++ + if s.step.pred == nil { + return true + } + if s.step.pred.bval { + if s.step.pred.path.Exists(s.node) { + return true + } + } else if s.step.pred.path != nil { + iter := s.step.pred.path.Iter(s.node) + for iter.Next() { + if iter.Node().equals(s.step.pred.sval) { + return true + } + } + } else { + if s.step.pred.ival == s.pos { + return true + } + } + } + return false +} + +func (s *pathStepState) _next() bool { + if s.node == nil { + return false + } + if s.step.root && s.idx == 0 { + for s.node.up != nil { + s.node = s.node.up + } + } + + switch s.step.axis { + + case "self": + if s.idx == 0 && s.step.match(s.node) { + s.idx++ + return true + } + + case "parent": + if s.idx == 0 && s.node.up != nil && s.step.match(s.node.up) { + s.idx++ + s.node = s.node.up + return true + } + + case "ancestor", "ancestor-or-self": + if s.idx == 0 && s.step.axis == "ancestor-or-self" { + s.idx++ + if s.step.match(s.node) { + return true + } + } + for s.node.up != nil { + s.node = s.node.up + s.idx++ + if s.step.match(s.node) { + return true + } + } + + case "child": + var down []*Node + if s.idx == 0 { + down = s.node.down + } else { + down = s.node.up.down + } + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if s.step.match(node) { + s.node = node + return true + } + } + + case "descendant", "descendant-or-self": + if s.idx == 0 { + s.idx = s.node.pos + s.aux = s.node.end + if s.step.axis == "descendant" { + s.idx++ + } + } + for s.idx < s.aux { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind == attrNode { + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "following": + if s.idx == 0 { + s.idx = s.node.end + } + for s.idx < len(s.node.nodes) { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind == attrNode { + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "following-sibling": + var down []*Node + if s.node.up != nil { + down = s.node.up.down + if s.idx == 0 { + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if node == s.node { + break + } + } + } + } + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if s.step.match(node) { + s.node = node + return true + } + } + + case "preceding": + if s.idx == 0 { + s.aux = s.node.pos // Detect ancestors. + s.idx = s.node.pos - 1 + } + for s.idx >= 0 { + node := &s.node.nodes[s.idx] + s.idx-- + if node.kind == attrNode { + continue + } + if node == s.node.nodes[s.aux].up { + s.aux = s.node.nodes[s.aux].up.pos + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "preceding-sibling": + var down []*Node + if s.node.up != nil { + down = s.node.up.down + if s.aux == 0 { + s.aux = 1 + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if node == s.node { + s.idx-- + break + } + } + } + } + for s.idx >= 0 { + node := down[s.idx] + s.idx-- + if s.step.match(node) { + s.node = node + return true + } + } + + case "attribute": + if s.idx == 0 { + s.idx = s.node.pos + 1 + s.aux = s.node.end + } + for s.idx < s.aux { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind != attrNode { + break + } + if s.step.match(node) { + s.node = node + return true + } + } + + } + + s.node = nil + return false +} + +type pathPredicate struct { + path *Path + sval string + ival int + bval bool +} + +type pathStep struct { + root bool + axis string + name string + prefix string + uri string + kind nodeKind + pred *pathPredicate +} + +func (step *pathStep) match(node *Node) bool { + return node.kind != endNode && + (step.kind == anyNode || step.kind == node.kind) && + (step.name == "*" || (node.name.Local == step.name && (node.name.Space != "" && node.name.Space == step.uri || node.name.Space == ""))) +} + +// MustCompile returns the compiled path, and panics if +// there are any errors. +func MustCompile(path string) *Path { + e, err := Compile(path) + if err != nil { + panic(err) + } + return e +} + +// Compile returns the compiled path. +func Compile(path string) (*Path, error) { + c := pathCompiler{path, 0, []Namespace{} } + if path == "" { + return nil, c.errorf("empty path") + } + p, err := c.parsePath() + if err != nil { + return nil, err + } + return p, nil +} + +// Compile the path with the knowledge of the given namespaces +func CompileWithNamespace(path string, ns []Namespace) (*Path, error) { + c := pathCompiler{path, 0, ns} + if path == "" { + return nil, c.errorf("empty path") + } + p, err := c.parsePath() + if err != nil { + return nil, err + } + return p, nil +} + +type pathCompiler struct { + path string + i int + ns []Namespace +} + +func (c *pathCompiler) errorf(format string, args ...interface{}) error { + return fmt.Errorf("compiling xml path %q:%d: %s", c.path, c.i, fmt.Sprintf(format, args...)) +} + +func (c *pathCompiler) parsePath() (path *Path, err error) { + var steps []pathStep + var start = c.i + for { + step := pathStep{axis: "child"} + + if c.i == 0 && c.skipByte('/') { + step.root = true + if len(c.path) == 1 { + step.name = "*" + } + } + if c.peekByte('/') { + step.axis = "descendant-or-self" + step.name = "*" + } else if c.skipByte('@') { + mark := c.i + if !c.skipName() { + return nil, c.errorf("missing name after @") + } + step.axis = "attribute" + step.name = c.path[mark:c.i] + step.kind = attrNode + } else { + mark := c.i + if c.skipName() { + step.name = c.path[mark:c.i] + } + if step.name == "" { + return nil, c.errorf("missing name") + } else if step.name == "*" { + step.kind = startNode + } else if step.name == "." { + step.axis = "self" + step.name = "*" + } else if step.name == ".." { + step.axis = "parent" + step.name = "*" + } else { + if c.skipByte(':') { + if !c.skipByte(':') { + mark = c.i + if c.skipName() { + step.prefix = step.name + step.name = c.path[mark:c.i] + // check prefix + found := false + for _, ns := range c.ns { + if ns.Prefix == step.prefix { + step.uri = ns.Uri + found = true + break + } + } + if !found { + return nil, c.errorf("unknown namespace prefix: %s", step.prefix) + } + } else { + return nil, c.errorf("missing name after namespace prefix") + } + } else { + switch step.name { + case "attribute": + step.kind = attrNode + case "self", "child", "parent": + case "descendant", "descendant-or-self": + case "ancestor", "ancestor-or-self": + case "following", "following-sibling": + case "preceding", "preceding-sibling": + default: + return nil, c.errorf("unsupported axis: %q", step.name) + } + step.axis = step.name + + mark = c.i + if !c.skipName() { + return nil, c.errorf("missing name") + } + step.name = c.path[mark:c.i] + } + } + if c.skipByte('(') { + conflict := step.kind != anyNode + switch step.name { + case "node": + // must be anyNode + case "text": + step.kind = textNode + case "comment": + step.kind = commentNode + case "processing-instruction": + step.kind = procInstNode + default: + return nil, c.errorf("unsupported expression: %s()", step.name) + } + if conflict { + return nil, c.errorf("%s() cannot succeed on axis %q", step.name, step.axis) + } + + literal, err := c.parseLiteral() + if err == errNoLiteral { + step.name = "*" + } else if err != nil { + return nil, c.errorf("%v", err) + } else if step.kind == procInstNode { + step.name = literal + } else { + return nil, c.errorf("%s() has no arguments", step.name) + } + if !c.skipByte(')') { + return nil, c.errorf("missing )") + } + } else if step.name == "*" && step.kind == anyNode { + step.kind = startNode + } + } + } + if c.skipByte('[') { + step.pred = &pathPredicate{} + if ival, ok := c.parseInt(); ok { + if ival == 0 { + return nil, c.errorf("positions start at 1") + } + step.pred.ival = ival + } else { + path, err := c.parsePath() + if err != nil { + return nil, err + } + if path.path[0] == '-' { + if _, err = strconv.Atoi(path.path); err == nil { + return nil, c.errorf("positions must be positive") + } + } + step.pred.path = path + if c.skipByte('=') { + sval, err := c.parseLiteral() + if err != nil { + return nil, c.errorf("%v", err) + } + step.pred.sval = sval + } else { + step.pred.bval = true + } + } + if !c.skipByte(']') { + return nil, c.errorf("expected ']'") + } + } + steps = append(steps, step) + //fmt.Printf("step: %#v\n", step) + if !c.skipByte('/') { + if (start == 0 || start == c.i) && c.i < len(c.path) { + return nil, c.errorf("unexpected %q", c.path[c.i]) + } + return &Path{steps: steps, path: c.path[start:c.i]}, nil + } + } + panic("unreachable") +} + +var errNoLiteral = fmt.Errorf("expected a literal string") + +func (c *pathCompiler) parseLiteral() (string, error) { + if c.skipByte('"') { + mark := c.i + if !c.skipByteFind('"') { + return "", fmt.Errorf(`missing '"'`) + } + return c.path[mark:c.i-1], nil + } + if c.skipByte('\'') { + mark := c.i + if !c.skipByteFind('\'') { + return "", fmt.Errorf(`missing "'"`) + } + return c.path[mark:c.i-1], nil + } + return "", errNoLiteral +} + +func (c *pathCompiler) parseInt() (v int, ok bool) { + mark := c.i + for c.i < len(c.path) && c.path[c.i] >= '0' && c.path[c.i] <= '9' { + v *= 10 + v += int(c.path[c.i]) - '0' + c.i++ + } + if c.i == mark { + return 0, false + } + return v, true +} + +func (c *pathCompiler) skipByte(b byte) bool { + if c.i < len(c.path) && c.path[c.i] == b { + c.i++ + return true + } + return false +} + +func (c *pathCompiler) skipByteFind(b byte) bool { + for i := c.i; i < len(c.path); i++ { + if c.path[i] == b { + c.i = i+1 + return true + } + } + return false +} + +func (c *pathCompiler) peekByte(b byte) bool { + return c.i < len(c.path) && c.path[c.i] == b +} + +func (c *pathCompiler) skipName() bool { + if c.i >= len(c.path) { + return false + } + if c.path[c.i] == '*' { + c.i++ + return true + } + start := c.i + for c.i < len(c.path) && (c.path[c.i] >= utf8.RuneSelf || isNameByte(c.path[c.i])) { + c.i++ + } + return c.i > start +} + +func isNameByte(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '.' || c == '-' +} diff --git a/vendor/github.com/mattn/go-isatty/LICENSE b/vendor/github.com/mattn/go-isatty/LICENSE new file mode 100644 index 000000000..65dc692b6 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) Yasuhiro MATSUMOTO + +MIT License (Expat) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md new file mode 100644 index 000000000..74845de4a --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -0,0 +1,37 @@ +# go-isatty + +isatty for golang + +## Usage + +```go +package main + +import ( + "fmt" + "github.com/mattn/go-isatty" + "os" +) + +func main() { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println("Is Terminal") + } else { + fmt.Println("Is Not Terminal") + } +} +``` + +## Installation + +``` +$ go get github.com/mattn/go-isatty +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-isatty/doc.go b/vendor/github.com/mattn/go-isatty/doc.go new file mode 100644 index 000000000..17d4f90eb --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/doc.go @@ -0,0 +1,2 @@ +// Package isatty implements interface to isatty +package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_appengine.go b/vendor/github.com/mattn/go-isatty/isatty_appengine.go new file mode 100644 index 000000000..83c588773 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_appengine.go @@ -0,0 +1,9 @@ +// +build appengine + +package isatty + +// IsTerminal returns true if the file descriptor is terminal which +// is always false on on appengine classic which is a sandboxed PaaS. +func IsTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go new file mode 100644 index 000000000..98ffe86a4 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -0,0 +1,18 @@ +// +build darwin freebsd openbsd netbsd +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TIOCGETA + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_linux.go b/vendor/github.com/mattn/go-isatty/isatty_linux.go new file mode 100644 index 000000000..9d24bac1d --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_linux.go @@ -0,0 +1,18 @@ +// +build linux +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TCGETS + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go new file mode 100644 index 000000000..1f0c6bf53 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -0,0 +1,16 @@ +// +build solaris +// +build !appengine + +package isatty + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +func IsTerminal(fd uintptr) bool { + var termio unix.Termio + err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + return err == nil +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go new file mode 100644 index 000000000..83c398b16 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -0,0 +1,19 @@ +// +build windows +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +var kernel32 = syscall.NewLazyDLL("kernel32.dll") +var procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 +} diff --git a/vendor/github.com/mitchellh/cli/.travis.yml b/vendor/github.com/mitchellh/cli/.travis.yml new file mode 100644 index 000000000..c2f4ab263 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/.travis.yml @@ -0,0 +1,14 @@ +sudo: false + +language: go + +go: + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - tip + +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/mitchellh/cli/LICENSE b/vendor/github.com/mitchellh/cli/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor†+ + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version†+ + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution†+ + means Covered Software of a particular Contributor. + +1.4. “Covered Software†+ + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses†+ means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form†+ + means any form of the work other than Source Code Form. + +1.7. “Larger Work†+ + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License†+ + means this document. + +1.9. “Licensable†+ + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications†+ + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims†of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License†+ + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form†+ + means the form of the work preferred for making modifications. + +1.14. “You†(or “Yourâ€) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You†includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control†means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is†basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses†Notice + + This Source Code Form is “Incompatible + With Secondary Licensesâ€, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/mitchellh/cli/README.md b/vendor/github.com/mitchellh/cli/README.md new file mode 100644 index 000000000..287ecb246 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/README.md @@ -0,0 +1,61 @@ +# Go CLI Library [![GoDoc](https://godoc.org/github.com/mitchellh/cli?status.png)](https://godoc.org/github.com/mitchellh/cli) + +cli is a library for implementing powerful command-line interfaces in Go. +cli is the library that powers the CLI for +[Packer](https://github.com/mitchellh/packer), +[Serf](https://github.com/hashicorp/serf), and +[Consul](https://github.com/hashicorp/consul). + +## Features + +* Easy sub-command based CLIs: `cli foo`, `cli bar`, etc. + +* Support for nested subcommands such as `cli foo bar`. + +* Optional support for default subcommands so `cli` does something + other than error. + +* Automatic help generation for listing subcommands + +* Automatic help flag recognition of `-h`, `--help`, etc. + +* Automatic version flag recognition of `-v`, `--version`. + +* Helpers for interacting with the terminal, such as outputting information, + asking for input, etc. These are optional, you can always interact with the + terminal however you choose. + +* Use of Go interfaces/types makes augmenting various parts of the library a + piece of cake. + +## Example + +Below is a simple example of creating and running a CLI + +```go +package main + +import ( + "log" + "os" + + "github.com/mitchellh/cli" +) + +func main() { + c := cli.NewCLI("app", "1.0.0") + c.Args = os.Args[1:] + c.Commands = map[string]cli.CommandFactory{ + "foo": fooCommandFactory, + "bar": barCommandFactory, + } + + exitStatus, err := c.Run() + if err != nil { + log.Println(err) + } + + os.Exit(exitStatus) +} +``` + diff --git a/vendor/github.com/mitchellh/cli/cli.go b/vendor/github.com/mitchellh/cli/cli.go new file mode 100644 index 000000000..81b14f1fc --- /dev/null +++ b/vendor/github.com/mitchellh/cli/cli.go @@ -0,0 +1,440 @@ +package cli + +import ( + "fmt" + "io" + "os" + "sort" + "strings" + "sync" + "text/template" + + "github.com/armon/go-radix" +) + +// CLI contains the state necessary to run subcommands and parse the +// command line arguments. +// +// CLI also supports nested subcommands, such as "cli foo bar". To use +// nested subcommands, the key in the Commands mapping below contains the +// full subcommand. In this example, it would be "foo bar". +// +// If you use a CLI with nested subcommands, some semantics change due to +// ambiguities: +// +// * We use longest prefix matching to find a matching subcommand. This +// means if you register "foo bar" and the user executes "cli foo qux", +// the "foo" commmand will be executed with the arg "qux". It is up to +// you to handle these args. One option is to just return the special +// help return code `RunResultHelp` to display help and exit. +// +// * The help flag "-h" or "-help" will look at all args to determine +// the help function. For example: "otto apps list -h" will show the +// help for "apps list" but "otto apps -h" will show it for "apps". +// In the normal CLI, only the first subcommand is used. +// +// * The help flag will list any subcommands that a command takes +// as well as the command's help itself. If there are no subcommands, +// it will note this. If the CLI itself has no subcommands, this entire +// section is omitted. +// +// * Any parent commands that don't exist are automatically created as +// no-op commands that just show help for other subcommands. For example, +// if you only register "foo bar", then "foo" is automatically created. +// +type CLI struct { + // Args is the list of command-line arguments received excluding + // the name of the app. For example, if the command "./cli foo bar" + // was invoked, then Args should be []string{"foo", "bar"}. + Args []string + + // Commands is a mapping of subcommand names to a factory function + // for creating that Command implementation. If there is a command + // with a blank string "", then it will be used as the default command + // if no subcommand is specified. + // + // If the key has a space in it, this will create a nested subcommand. + // For example, if the key is "foo bar", then to access it our CLI + // must be accessed with "./cli foo bar". See the docs for CLI for + // notes on how this changes some other behavior of the CLI as well. + Commands map[string]CommandFactory + + // Name defines the name of the CLI. + Name string + + // Version of the CLI. + Version string + + // HelpFunc and HelpWriter are used to output help information, if + // requested. + // + // HelpFunc is the function called to generate the generic help + // text that is shown if help must be shown for the CLI that doesn't + // pertain to a specific command. + // + // HelpWriter is the Writer where the help text is outputted to. If + // not specified, it will default to Stderr. + HelpFunc HelpFunc + HelpWriter io.Writer + + once sync.Once + commandTree *radix.Tree + commandNested bool + isHelp bool + subcommand string + subcommandArgs []string + topFlags []string + + isVersion bool +} + +// NewClI returns a new CLI instance with sensible defaults. +func NewCLI(app, version string) *CLI { + return &CLI{ + Name: app, + Version: version, + HelpFunc: BasicHelpFunc(app), + } + +} + +// IsHelp returns whether or not the help flag is present within the +// arguments. +func (c *CLI) IsHelp() bool { + c.once.Do(c.init) + return c.isHelp +} + +// IsVersion returns whether or not the version flag is present within the +// arguments. +func (c *CLI) IsVersion() bool { + c.once.Do(c.init) + return c.isVersion +} + +// Run runs the actual CLI based on the arguments given. +func (c *CLI) Run() (int, error) { + c.once.Do(c.init) + + // Just show the version and exit if instructed. + if c.IsVersion() && c.Version != "" { + c.HelpWriter.Write([]byte(c.Version + "\n")) + return 1, nil + } + + // Attempt to get the factory function for creating the command + // implementation. If the command is invalid or blank, it is an error. + raw, ok := c.commandTree.Get(c.Subcommand()) + if !ok { + c.HelpWriter.Write([]byte(c.HelpFunc(c.helpCommands(c.subcommandParent())) + "\n")) + return 1, nil + } + + command, err := raw.(CommandFactory)() + if err != nil { + return 0, err + } + + // If we've been instructed to just print the help, then print it + if c.IsHelp() { + c.commandHelp(command) + return 1, nil + } + + // If there is an invalid flag, then error + if len(c.topFlags) > 0 { + c.HelpWriter.Write([]byte( + "Invalid flags before the subcommand. If these flags are for\n" + + "the subcommand, please put them after the subcommand.\n\n")) + c.commandHelp(command) + return 1, nil + } + + code := command.Run(c.SubcommandArgs()) + if code == RunResultHelp { + // Requesting help + c.commandHelp(command) + return 1, nil + } + + return code, nil +} + +// Subcommand returns the subcommand that the CLI would execute. For +// example, a CLI from "--version version --help" would return a Subcommand +// of "version" +func (c *CLI) Subcommand() string { + c.once.Do(c.init) + return c.subcommand +} + +// SubcommandArgs returns the arguments that will be passed to the +// subcommand. +func (c *CLI) SubcommandArgs() []string { + c.once.Do(c.init) + return c.subcommandArgs +} + +// subcommandParent returns the parent of this subcommand, if there is one. +// If there isn't on, "" is returned. +func (c *CLI) subcommandParent() string { + // Get the subcommand, if it is "" alread just return + sub := c.Subcommand() + if sub == "" { + return sub + } + + // Clear any trailing spaces and find the last space + sub = strings.TrimRight(sub, " ") + idx := strings.LastIndex(sub, " ") + + if idx == -1 { + // No space means our parent is root + return "" + } + + return sub[:idx] +} + +func (c *CLI) init() { + if c.HelpFunc == nil { + c.HelpFunc = BasicHelpFunc("app") + + if c.Name != "" { + c.HelpFunc = BasicHelpFunc(c.Name) + } + } + + if c.HelpWriter == nil { + c.HelpWriter = os.Stderr + } + + // Build our command tree + c.commandTree = radix.New() + c.commandNested = false + for k, v := range c.Commands { + k = strings.TrimSpace(k) + c.commandTree.Insert(k, v) + if strings.ContainsRune(k, ' ') { + c.commandNested = true + } + } + + // Go through the key and fill in any missing parent commands + if c.commandNested { + var walkFn radix.WalkFn + toInsert := make(map[string]struct{}) + walkFn = func(k string, raw interface{}) bool { + idx := strings.LastIndex(k, " ") + if idx == -1 { + // If there is no space, just ignore top level commands + return false + } + + // Trim up to that space so we can get the expected parent + k = k[:idx] + if _, ok := c.commandTree.Get(k); ok { + // Yay we have the parent! + return false + } + + // We're missing the parent, so let's insert this + toInsert[k] = struct{}{} + + // Call the walk function recursively so we check this one too + return walkFn(k, nil) + } + + // Walk! + c.commandTree.Walk(walkFn) + + // Insert any that we're missing + for k, _ := range toInsert { + var f CommandFactory = func() (Command, error) { + return &MockCommand{ + HelpText: "This command is accessed by using one of the subcommands below.", + RunResult: RunResultHelp, + }, nil + } + + c.commandTree.Insert(k, f) + } + } + + // Process the args + c.processArgs() +} + +func (c *CLI) commandHelp(command Command) { + // Get the template to use + tpl := strings.TrimSpace(defaultHelpTemplate) + if t, ok := command.(CommandHelpTemplate); ok { + tpl = t.HelpTemplate() + } + if !strings.HasSuffix(tpl, "\n") { + tpl += "\n" + } + + // Parse it + t, err := template.New("root").Parse(tpl) + if err != nil { + t = template.Must(template.New("root").Parse(fmt.Sprintf( + "Internal error! Failed to parse command help template: %s\n", err))) + } + + // Template data + data := map[string]interface{}{ + "Name": c.Name, + "Help": command.Help(), + } + + // Build subcommand list if we have it + var subcommandsTpl []map[string]interface{} + if c.commandNested { + // Get the matching keys + subcommands := c.helpCommands(c.Subcommand()) + keys := make([]string, 0, len(subcommands)) + for k, _ := range subcommands { + keys = append(keys, k) + } + + // Sort the keys + sort.Strings(keys) + + // Figure out the padding length + var longest int + for _, k := range keys { + if v := len(k); v > longest { + longest = v + } + } + + // Go through and create their structures + subcommandsTpl = make([]map[string]interface{}, 0, len(subcommands)) + for k, raw := range subcommands { + // Get the command + sub, err := raw() + if err != nil { + c.HelpWriter.Write([]byte(fmt.Sprintf( + "Error instantiating %q: %s", k, err))) + } + + // Find the last space and make sure we only include that last part + name := k + if idx := strings.LastIndex(k, " "); idx > -1 { + name = name[idx+1:] + } + + subcommandsTpl = append(subcommandsTpl, map[string]interface{}{ + "Name": name, + "NameAligned": name + strings.Repeat(" ", longest-len(k)), + "Help": sub.Help(), + "Synopsis": sub.Synopsis(), + }) + } + } + data["Subcommands"] = subcommandsTpl + + // Write + err = t.Execute(c.HelpWriter, data) + if err == nil { + return + } + + // An error, just output... + c.HelpWriter.Write([]byte(fmt.Sprintf( + "Internal error rendering help: %s", err))) +} + +// helpCommands returns the subcommands for the HelpFunc argument. +// This will only contain immediate subcommands. +func (c *CLI) helpCommands(prefix string) map[string]CommandFactory { + // If our prefix isn't empty, make sure it ends in ' ' + if prefix != "" && prefix[len(prefix)-1] != ' ' { + prefix += " " + } + + // Get all the subkeys of this command + var keys []string + c.commandTree.WalkPrefix(prefix, func(k string, raw interface{}) bool { + // Ignore any sub-sub keys, i.e. "foo bar baz" when we want "foo bar" + if !strings.Contains(k[len(prefix):], " ") { + keys = append(keys, k) + } + + return false + }) + + // For each of the keys return that in the map + result := make(map[string]CommandFactory, len(keys)) + for _, k := range keys { + raw, ok := c.commandTree.Get(k) + if !ok { + // We just got it via WalkPrefix above, so we just panic + panic("not found: " + k) + } + + result[k] = raw.(CommandFactory) + } + + return result +} + +func (c *CLI) processArgs() { + for i, arg := range c.Args { + if c.subcommand == "" { + // Check for version and help flags if not in a subcommand + if arg == "-v" || arg == "-version" || arg == "--version" { + c.isVersion = true + continue + } + if arg == "-h" || arg == "-help" || arg == "--help" { + c.isHelp = true + continue + } + + if arg != "" && arg[0] == '-' { + // Record the arg... + c.topFlags = append(c.topFlags, arg) + } + } + + // If we didn't find a subcommand yet and this is the first non-flag + // argument, then this is our subcommand. j + if c.subcommand == "" && arg != "" && arg[0] != '-' { + c.subcommand = arg + if c.commandNested { + // Nested CLI, the subcommand is actually the entire + // arg list up to a flag that is still a valid subcommand. + k, _, ok := c.commandTree.LongestPrefix(strings.Join(c.Args[i:], " ")) + if ok { + c.subcommand = k + i += strings.Count(k, " ") + } + } + + // The remaining args the subcommand arguments + c.subcommandArgs = c.Args[i+1:] + } + } + + // If we never found a subcommand and support a default command, then + // switch to using that. + if c.subcommand == "" { + if _, ok := c.Commands[""]; ok { + args := c.topFlags + args = append(args, c.subcommandArgs...) + c.topFlags = nil + c.subcommandArgs = args + } + } +} + +const defaultHelpTemplate = ` +{{.Help}}{{if gt (len .Subcommands) 0}} + +Subcommands: +{{ range $value := .Subcommands }} + {{ $value.NameAligned }} {{ $value.Synopsis }}{{ end }} +{{ end }} +` diff --git a/vendor/github.com/mitchellh/cli/command.go b/vendor/github.com/mitchellh/cli/command.go new file mode 100644 index 000000000..b4924eb00 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/command.go @@ -0,0 +1,47 @@ +package cli + +const ( + // RunResultHelp is a value that can be returned from Run to signal + // to the CLI to render the help output. + RunResultHelp = -18511 +) + +// A command is a runnable sub-command of a CLI. +type Command interface { + // Help should return long-form help text that includes the command-line + // usage, a brief few sentences explaining the function of the command, + // and the complete list of flags the command accepts. + Help() string + + // Run should run the actual command with the given CLI instance and + // command-line arguments. It should return the exit status when it is + // finished. + // + // There are a handful of special exit codes this can return documented + // above that change behavior. + Run(args []string) int + + // Synopsis should return a one-line, short synopsis of the command. + // This should be less than 50 characters ideally. + Synopsis() string +} + +// CommandHelpTemplate is an extension of Command that also has a function +// for returning a template for the help rather than the help itself. In +// this scenario, both Help and HelpTemplate should be implemented. +// +// If CommandHelpTemplate isn't implemented, the Help is output as-is. +type CommandHelpTemplate interface { + // HelpTemplate is the template in text/template format to use for + // displaying the Help. The keys available are: + // + // * ".Help" - The help text itself + // * ".Subcommands" + // + HelpTemplate() string +} + +// CommandFactory is a type of function that is a factory for commands. +// We need a factory because we may need to setup some state on the +// struct that implements the command itself. +type CommandFactory func() (Command, error) diff --git a/vendor/github.com/mitchellh/cli/command_mock.go b/vendor/github.com/mitchellh/cli/command_mock.go new file mode 100644 index 000000000..6371e573b --- /dev/null +++ b/vendor/github.com/mitchellh/cli/command_mock.go @@ -0,0 +1,42 @@ +package cli + +// MockCommand is an implementation of Command that can be used for tests. +// It is publicly exported from this package in case you want to use it +// externally. +type MockCommand struct { + // Settable + HelpText string + RunResult int + SynopsisText string + + // Set by the command + RunCalled bool + RunArgs []string +} + +func (c *MockCommand) Help() string { + return c.HelpText +} + +func (c *MockCommand) Run(args []string) int { + c.RunCalled = true + c.RunArgs = args + + return c.RunResult +} + +func (c *MockCommand) Synopsis() string { + return c.SynopsisText +} + +// MockCommandHelpTemplate is an implementation of CommandHelpTemplate. +type MockCommandHelpTemplate struct { + MockCommand + + // Settable + HelpTemplateText string +} + +func (c *MockCommandHelpTemplate) HelpTemplate() string { + return c.HelpTemplateText +} diff --git a/vendor/github.com/mitchellh/cli/help.go b/vendor/github.com/mitchellh/cli/help.go new file mode 100644 index 000000000..67ea8c824 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/help.go @@ -0,0 +1,79 @@ +package cli + +import ( + "bytes" + "fmt" + "log" + "sort" + "strings" +) + +// HelpFunc is the type of the function that is responsible for generating +// the help output when the CLI must show the general help text. +type HelpFunc func(map[string]CommandFactory) string + +// BasicHelpFunc generates some basic help output that is usually good enough +// for most CLI applications. +func BasicHelpFunc(app string) HelpFunc { + return func(commands map[string]CommandFactory) string { + var buf bytes.Buffer + buf.WriteString(fmt.Sprintf( + "usage: %s [--version] [--help] []\n\n", + app)) + buf.WriteString("Available commands are:\n") + + // Get the list of keys so we can sort them, and also get the maximum + // key length so they can be aligned properly. + keys := make([]string, 0, len(commands)) + maxKeyLen := 0 + for key, _ := range commands { + if len(key) > maxKeyLen { + maxKeyLen = len(key) + } + + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + commandFunc, ok := commands[key] + if !ok { + // This should never happen since we JUST built the list of + // keys. + panic("command not found: " + key) + } + + command, err := commandFunc() + if err != nil { + log.Printf("[ERR] cli: Command '%s' failed to load: %s", + key, err) + continue + } + + key = fmt.Sprintf("%s%s", key, strings.Repeat(" ", maxKeyLen-len(key))) + buf.WriteString(fmt.Sprintf(" %s %s\n", key, command.Synopsis())) + } + + return buf.String() + } +} + +// FilteredHelpFunc will filter the commands to only include the keys +// in the include parameter. +func FilteredHelpFunc(include []string, f HelpFunc) HelpFunc { + return func(commands map[string]CommandFactory) string { + set := make(map[string]struct{}) + for _, k := range include { + set[k] = struct{}{} + } + + filtered := make(map[string]CommandFactory) + for k, f := range commands { + if _, ok := set[k]; ok { + filtered[k] = f + } + } + + return f(filtered) + } +} diff --git a/vendor/github.com/mitchellh/cli/ui.go b/vendor/github.com/mitchellh/cli/ui.go new file mode 100644 index 000000000..a2d6f94f4 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/ui.go @@ -0,0 +1,187 @@ +package cli + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "os/signal" + "strings" + + "github.com/bgentry/speakeasy" + "github.com/mattn/go-isatty" +) + +// Ui is an interface for interacting with the terminal, or "interface" +// of a CLI. This abstraction doesn't have to be used, but helps provide +// a simple, layerable way to manage user interactions. +type Ui interface { + // Ask asks the user for input using the given query. The response is + // returned as the given string, or an error. + Ask(string) (string, error) + + // AskSecret asks the user for input using the given query, but does not echo + // the keystrokes to the terminal. + AskSecret(string) (string, error) + + // Output is called for normal standard output. + Output(string) + + // Info is called for information related to the previous output. + // In general this may be the exact same as Output, but this gives + // Ui implementors some flexibility with output formats. + Info(string) + + // Error is used for any error messages that might appear on standard + // error. + Error(string) + + // Warn is used for any warning messages that might appear on standard + // error. + Warn(string) +} + +// BasicUi is an implementation of Ui that just outputs to the given +// writer. This UI is not threadsafe by default, but you can wrap it +// in a ConcurrentUi to make it safe. +type BasicUi struct { + Reader io.Reader + Writer io.Writer + ErrorWriter io.Writer +} + +func (u *BasicUi) Ask(query string) (string, error) { + return u.ask(query, false) +} + +func (u *BasicUi) AskSecret(query string) (string, error) { + return u.ask(query, true) +} + +func (u *BasicUi) ask(query string, secret bool) (string, error) { + if _, err := fmt.Fprint(u.Writer, query+" "); err != nil { + return "", err + } + + // Register for interrupts so that we can catch it and immediately + // return... + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt) + defer signal.Stop(sigCh) + + // Ask for input in a go-routine so that we can ignore it. + errCh := make(chan error, 1) + lineCh := make(chan string, 1) + go func() { + var line string + var err error + if secret && isatty.IsTerminal(os.Stdin.Fd()) { + line, err = speakeasy.Ask("") + } else { + r := bufio.NewReader(u.Reader) + line, err = r.ReadString('\n') + } + if err != nil { + errCh <- err + return + } + + lineCh <- strings.TrimRight(line, "\r\n") + }() + + select { + case err := <-errCh: + return "", err + case line := <-lineCh: + return line, nil + case <-sigCh: + // Print a newline so that any further output starts properly + // on a new line. + fmt.Fprintln(u.Writer) + + return "", errors.New("interrupted") + } +} + +func (u *BasicUi) Error(message string) { + w := u.Writer + if u.ErrorWriter != nil { + w = u.ErrorWriter + } + + fmt.Fprint(w, message) + fmt.Fprint(w, "\n") +} + +func (u *BasicUi) Info(message string) { + u.Output(message) +} + +func (u *BasicUi) Output(message string) { + fmt.Fprint(u.Writer, message) + fmt.Fprint(u.Writer, "\n") +} + +func (u *BasicUi) Warn(message string) { + u.Error(message) +} + +// PrefixedUi is an implementation of Ui that prefixes messages. +type PrefixedUi struct { + AskPrefix string + AskSecretPrefix string + OutputPrefix string + InfoPrefix string + ErrorPrefix string + WarnPrefix string + Ui Ui +} + +func (u *PrefixedUi) Ask(query string) (string, error) { + if query != "" { + query = fmt.Sprintf("%s%s", u.AskPrefix, query) + } + + return u.Ui.Ask(query) +} + +func (u *PrefixedUi) AskSecret(query string) (string, error) { + if query != "" { + query = fmt.Sprintf("%s%s", u.AskSecretPrefix, query) + } + + return u.Ui.AskSecret(query) +} + +func (u *PrefixedUi) Error(message string) { + if message != "" { + message = fmt.Sprintf("%s%s", u.ErrorPrefix, message) + } + + u.Ui.Error(message) +} + +func (u *PrefixedUi) Info(message string) { + if message != "" { + message = fmt.Sprintf("%s%s", u.InfoPrefix, message) + } + + u.Ui.Info(message) +} + +func (u *PrefixedUi) Output(message string) { + if message != "" { + message = fmt.Sprintf("%s%s", u.OutputPrefix, message) + } + + u.Ui.Output(message) +} + +func (u *PrefixedUi) Warn(message string) { + if message != "" { + message = fmt.Sprintf("%s%s", u.WarnPrefix, message) + } + + u.Ui.Warn(message) +} diff --git a/vendor/github.com/mitchellh/cli/ui_colored.go b/vendor/github.com/mitchellh/cli/ui_colored.go new file mode 100644 index 000000000..e3d5131d1 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/ui_colored.go @@ -0,0 +1,69 @@ +package cli + +import ( + "fmt" +) + +// UiColor is a posix shell color code to use. +type UiColor struct { + Code int + Bold bool +} + +// A list of colors that are useful. These are all non-bolded by default. +var ( + UiColorNone UiColor = UiColor{-1, false} + UiColorRed = UiColor{31, false} + UiColorGreen = UiColor{32, false} + UiColorYellow = UiColor{33, false} + UiColorBlue = UiColor{34, false} + UiColorMagenta = UiColor{35, false} + UiColorCyan = UiColor{36, false} +) + +// ColoredUi is a Ui implementation that colors its output according +// to the given color schemes for the given type of output. +type ColoredUi struct { + OutputColor UiColor + InfoColor UiColor + ErrorColor UiColor + WarnColor UiColor + Ui Ui +} + +func (u *ColoredUi) Ask(query string) (string, error) { + return u.Ui.Ask(u.colorize(query, u.OutputColor)) +} + +func (u *ColoredUi) AskSecret(query string) (string, error) { + return u.Ui.AskSecret(u.colorize(query, u.OutputColor)) +} + +func (u *ColoredUi) Output(message string) { + u.Ui.Output(u.colorize(message, u.OutputColor)) +} + +func (u *ColoredUi) Info(message string) { + u.Ui.Info(u.colorize(message, u.InfoColor)) +} + +func (u *ColoredUi) Error(message string) { + u.Ui.Error(u.colorize(message, u.ErrorColor)) +} + +func (u *ColoredUi) Warn(message string) { + u.Ui.Warn(u.colorize(message, u.WarnColor)) +} + +func (u *ColoredUi) colorize(message string, color UiColor) string { + if color.Code == -1 { + return message + } + + attr := 0 + if color.Bold { + attr = 1 + } + + return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color.Code, message) +} diff --git a/vendor/github.com/mitchellh/cli/ui_concurrent.go b/vendor/github.com/mitchellh/cli/ui_concurrent.go new file mode 100644 index 000000000..b4f4dbfaa --- /dev/null +++ b/vendor/github.com/mitchellh/cli/ui_concurrent.go @@ -0,0 +1,54 @@ +package cli + +import ( + "sync" +) + +// ConcurrentUi is a wrapper around a Ui interface (and implements that +// interface) making the underlying Ui concurrency safe. +type ConcurrentUi struct { + Ui Ui + l sync.Mutex +} + +func (u *ConcurrentUi) Ask(query string) (string, error) { + u.l.Lock() + defer u.l.Unlock() + + return u.Ui.Ask(query) +} + +func (u *ConcurrentUi) AskSecret(query string) (string, error) { + u.l.Lock() + defer u.l.Unlock() + + return u.Ui.AskSecret(query) +} + +func (u *ConcurrentUi) Error(message string) { + u.l.Lock() + defer u.l.Unlock() + + u.Ui.Error(message) +} + +func (u *ConcurrentUi) Info(message string) { + u.l.Lock() + defer u.l.Unlock() + + u.Ui.Info(message) +} + +func (u *ConcurrentUi) Output(message string) { + u.l.Lock() + defer u.l.Unlock() + + u.Ui.Output(message) +} + +func (u *ConcurrentUi) Warn(message string) { + u.l.Lock() + defer u.l.Unlock() + + u.Ui.Warn(message) +} diff --git a/vendor/github.com/mitchellh/cli/ui_mock.go b/vendor/github.com/mitchellh/cli/ui_mock.go new file mode 100644 index 000000000..c46772855 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/ui_mock.go @@ -0,0 +1,64 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "sync" +) + +// MockUi is a mock UI that is used for tests and is exported publicly for +// use in external tests if needed as well. +type MockUi struct { + InputReader io.Reader + ErrorWriter *bytes.Buffer + OutputWriter *bytes.Buffer + + once sync.Once +} + +func (u *MockUi) Ask(query string) (string, error) { + u.once.Do(u.init) + + var result string + fmt.Fprint(u.OutputWriter, query) + if _, err := fmt.Fscanln(u.InputReader, &result); err != nil { + return "", err + } + + return result, nil +} + +func (u *MockUi) AskSecret(query string) (string, error) { + return u.Ask(query) +} + +func (u *MockUi) Error(message string) { + u.once.Do(u.init) + + fmt.Fprint(u.ErrorWriter, message) + fmt.Fprint(u.ErrorWriter, "\n") +} + +func (u *MockUi) Info(message string) { + u.Output(message) +} + +func (u *MockUi) Output(message string) { + u.once.Do(u.init) + + fmt.Fprint(u.OutputWriter, message) + fmt.Fprint(u.OutputWriter, "\n") +} + +func (u *MockUi) Warn(message string) { + u.once.Do(u.init) + + fmt.Fprint(u.ErrorWriter, message) + fmt.Fprint(u.ErrorWriter, "\n") +} + +func (u *MockUi) init() { + u.ErrorWriter = new(bytes.Buffer) + u.OutputWriter = new(bytes.Buffer) +} diff --git a/vendor/github.com/mitchellh/cli/ui_writer.go b/vendor/github.com/mitchellh/cli/ui_writer.go new file mode 100644 index 000000000..1e1db3cf6 --- /dev/null +++ b/vendor/github.com/mitchellh/cli/ui_writer.go @@ -0,0 +1,18 @@ +package cli + +// UiWriter is an io.Writer implementation that can be used with +// loggers that writes every line of log output data to a Ui at the +// Info level. +type UiWriter struct { + Ui Ui +} + +func (w *UiWriter) Write(p []byte) (n int, err error) { + n = len(p) + if n > 0 && p[n-1] == '\n' { + p = p[:n-1] + } + + w.Ui.Info(string(p)) + return n, nil +} diff --git a/vendor/github.com/mitchellh/go-fs/LICENSE b/vendor/github.com/mitchellh/go-fs/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-fs/README.md b/vendor/github.com/mitchellh/go-fs/README.md new file mode 100644 index 000000000..3cfaafa2f --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/README.md @@ -0,0 +1,90 @@ +# FAT Filesystem Library for Go + +This library implements the ability to create, read, and write +FAT filesystems using pure Go. + +**WARNING:** While the implementation works (to some degree, see the +limitations section below), I highly recommend you **don't** use this +library, since it has many limitations and is generally a terrible +implementation of FAT. For educational purposes, however, this library +may be interesting. + +In this library's current state, it is very good for _reading_ FAT +filesystems, and minimally useful for _creating_ FAT filesystems. See +the features and limitations below. + +## Features & Limitations + +Features: + +* Format a brand new FAT filesystem on a file backed device +* Create files and directories +* Traverse filesystem + +Limitations: + +This library has several limitations. They're easily able to be overcome, +but because I didn't need them for my use case, I didn't bother: + +* Files/directories cannot be deleted or renamed. +* Files never shrink in size. +* Deleted file/directory entries are never reclaimed, so fragmentation + grows towards infinity. Eventually, your "disk" will become full even + if you just create and delete a single file. +* There are some serious corruption possibilities in error cases. Cleanup + is not good. +* Incomplete FAT32 implementation (although FAT12 and FAT16 are complete). + +## Usage + +Here is some example usage where an existing disk image is read and +a file is created in the root directory: + +```go +// Assume this file was created already with a FAT filesystem +f, err := os.OpenFile("FLOPPY.dmg", os.O_RDWR|os.O_CREATE, 0666) +if err != nil { + panic(err) +} +defer f.Close() + +// BlockDevice backed by a file +device, err := fs.NewFileDisk(f) +if err != nil { + panic(err) +} + +filesys, err := fat.New(device) +if err != nil { + panic(err) +} + +rootDir, err := filesys.RootDir() +if err != nil { + panic(err) +} + +subEntry, err := rootDir.AddFile("HELLO_WORLD") +if err != nil { + panic(err) +} + +file, err := subEntry.File() +if err != nil { + panic(err) +} + +_, err = io.WriteString(file, "I am the contents of this file.") +if err != nil { + panic(err) +} +``` + +## Thanks + +Thanks to the following resources which helped in the creation of this +library: + +* [fat32-lib](https://code.google.com/p/fat32-lib/) +* [File Allocation Table on Wikipedia](http://en.wikipedia.org/wiki/File_Allocation_Table) +* Microsoft FAT filesystem specification diff --git a/vendor/github.com/mitchellh/go-fs/block_device.go b/vendor/github.com/mitchellh/go-fs/block_device.go new file mode 100644 index 000000000..2a82a43c2 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/block_device.go @@ -0,0 +1,22 @@ +package fs + +// A BlockDevice is the raw device that is meant to store a filesystem. +type BlockDevice interface { + // Closes this block device. No more methods may be called on a + // closed device. + Close() error + + // Len returns the number of bytes in this block device. + Len() int64 + + // SectorSize returns the size of a single sector on this device. + SectorSize() int + + // ReadAt reads data from the block device from the given + // offset. See io.ReaderAt for more information on this function. + ReadAt(p []byte, off int64) (n int, err error) + + // WriteAt writes data to the block device at the given offset. + // See io.WriterAt for more information on this function. + WriteAt(p []byte, off int64) (n int, err error) +} diff --git a/vendor/github.com/mitchellh/go-fs/directory.go b/vendor/github.com/mitchellh/go-fs/directory.go new file mode 100644 index 000000000..274764307 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/directory.go @@ -0,0 +1,18 @@ +package fs + +// Directory is an entry in a filesystem that stores files. +type Directory interface { + Entry(name string) DirectoryEntry + Entries() []DirectoryEntry + AddDirectory(name string) (DirectoryEntry, error) + AddFile(name string) (DirectoryEntry, error) +} + +// DirectoryEntry represents a single entry within a directory, +// which can be either another Directory or a File. +type DirectoryEntry interface { + Name() string + IsDir() bool + Dir() (Directory, error) + File() (File, error) +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/boot_sector.go b/vendor/github.com/mitchellh/go-fs/fat/boot_sector.go new file mode 100644 index 000000000..689a6b75c --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/boot_sector.go @@ -0,0 +1,347 @@ +package fat + +import ( + "encoding/binary" + "errors" + "fmt" + "github.com/mitchellh/go-fs" + "unicode" +) + +type MediaType uint8 + +// The standard value for "fixed", non-removable media, directly +// from the FAT specification. +const MediaFixed MediaType = 0xF8 + +type BootSectorCommon struct { + OEMName string + BytesPerSector uint16 + SectorsPerCluster uint8 + ReservedSectorCount uint16 + NumFATs uint8 + RootEntryCount uint16 + TotalSectors uint32 + Media MediaType + SectorsPerFat uint32 + SectorsPerTrack uint16 + NumHeads uint16 +} + +// DecodeBootSector takes a BlockDevice and decodes the FAT boot sector +// from it. +func DecodeBootSector(device fs.BlockDevice) (*BootSectorCommon, error) { + var sector [512]byte + if _, err := device.ReadAt(sector[:], 0); err != nil { + return nil, err + } + + if sector[510] != 0x55 || sector[511] != 0xAA { + return nil, errors.New("corrupt boot sector signature") + } + + result := new(BootSectorCommon) + + // BS_OEMName + result.OEMName = string(sector[3:11]) + + // BPB_BytsPerSec + result.BytesPerSector = binary.LittleEndian.Uint16(sector[11:13]) + + // BPB_SecPerClus + result.SectorsPerCluster = sector[13] + + // BPB_RsvdSecCnt + result.ReservedSectorCount = binary.LittleEndian.Uint16(sector[14:16]) + + // BPB_NumFATs + result.NumFATs = sector[16] + + // BPB_RootEntCnt + result.RootEntryCount = binary.LittleEndian.Uint16(sector[17:19]) + + // BPB_Media + result.Media = MediaType(sector[21]) + + // BPB_SecPerTrk + result.SectorsPerTrack = binary.LittleEndian.Uint16(sector[24:26]) + + // BPB_NumHeads + result.NumHeads = binary.LittleEndian.Uint16(sector[26:28]) + + // BPB_TotSec16 / BPB_TotSec32 + result.TotalSectors = uint32(binary.LittleEndian.Uint16(sector[19:21])) + if result.TotalSectors == 0 { + result.TotalSectors = binary.LittleEndian.Uint32(sector[32:36]) + } + + // BPB_FATSz16 / BPB_FATSz32 + result.SectorsPerFat = uint32(binary.LittleEndian.Uint16(sector[22:24])) + if result.SectorsPerFat == 0 { + result.SectorsPerFat = binary.LittleEndian.Uint32(sector[36:40]) + } + + return result, nil +} + +func (b *BootSectorCommon) Bytes() ([]byte, error) { + var sector [512]byte + + // BS_jmpBoot + sector[0] = 0xEB + sector[1] = 0x3C + sector[2] = 0x90 + + // BS_OEMName + if len(b.OEMName) > 8 { + return nil, errors.New("OEMName must be 8 bytes or less") + } + + for i, r := range b.OEMName { + if r > unicode.MaxASCII { + return nil, fmt.Errorf("'%s' in OEM name not a valid ASCII char. Must be ASCII.", r) + } + + sector[0x3+i] = byte(r) + } + + // BPB_BytsPerSec + binary.LittleEndian.PutUint16(sector[11:13], b.BytesPerSector) + + // BPB_SecPerClus + sector[13] = uint8(b.SectorsPerCluster) + + // BPB_RsvdSecCnt + binary.LittleEndian.PutUint16(sector[14:16], b.ReservedSectorCount) + + // BPB_NumFATs + sector[16] = b.NumFATs + + // BPB_RootEntCnt + binary.LittleEndian.PutUint16(sector[17:19], b.RootEntryCount) + + // BPB_Media + sector[21] = byte(b.Media) + + // BPB_SecPerTrk + binary.LittleEndian.PutUint16(sector[24:26], b.SectorsPerTrack) + + // BPB_Numheads + binary.LittleEndian.PutUint16(sector[26:28], b.NumHeads) + + // BPB_Hiddsec + // sector[28:32] - it is always set to 0 because we don't partition drives yet. + + // Important signature of every FAT boot sector + sector[510] = 0x55 + sector[511] = 0xAA + + return sector[:], nil +} + +// BytesPerCluster returns the number of bytes per cluster. +func (b *BootSectorCommon) BytesPerCluster() uint32 { + return uint32(b.SectorsPerCluster) * uint32(b.BytesPerSector) +} + +// ClusterOffset returns the offset of the data section of a particular +// cluster. +func (b *BootSectorCommon) ClusterOffset(n int) uint32 { + offset := b.DataOffset() + offset += (uint32(n) - FirstCluster) * b.BytesPerCluster() + return offset +} + +// DataOffset returns the offset of the data section of the disk. +func (b *BootSectorCommon) DataOffset() uint32 { + offset := uint32(b.RootDirOffset()) + offset += uint32(b.RootEntryCount * DirectoryEntrySize) + return offset +} + +// FATOffset returns the offset in bytes for the given index of the FAT +func (b *BootSectorCommon) FATOffset(n int) int { + offset := uint32(b.ReservedSectorCount * b.BytesPerSector) + offset += b.SectorsPerFat * uint32(b.BytesPerSector) * uint32(n) + return int(offset) +} + +// Calculates the FAT type that this boot sector represents. +func (b *BootSectorCommon) FATType() FATType { + var rootDirSectors uint32 + rootDirSectors = (uint32(b.RootEntryCount) * 32) + (uint32(b.BytesPerSector) - 1) + rootDirSectors /= uint32(b.BytesPerSector) + dataSectors := b.SectorsPerFat * uint32(b.NumFATs) + dataSectors += uint32(b.ReservedSectorCount) + dataSectors += rootDirSectors + dataSectors = b.TotalSectors - dataSectors + countClusters := dataSectors / uint32(b.SectorsPerCluster) + + switch { + case countClusters < 4085: + return FAT12 + case countClusters < 65525: + return FAT16 + default: + return FAT32 + } +} + +// RootDirOffset returns the byte offset when the root directory +// entries for FAT12/16 filesystems start. NOTE: This is absolutely useless +// for FAT32 because the root directory is just the beginning of the data +// region. +func (b *BootSectorCommon) RootDirOffset() int { + offset := b.FATOffset(0) + offset += int(uint32(b.NumFATs) * b.SectorsPerFat * uint32(b.BytesPerSector)) + return offset +} + +// BootSectorFat16 is the BootSector for FAT12 and FAT16 filesystems. +// It contains the common fields to all FAT filesystems and also some +// unique. +type BootSectorFat16 struct { + BootSectorCommon + + DriveNumber uint8 + VolumeID uint32 + VolumeLabel string + FileSystemTypeLabel string +} + +func (b *BootSectorFat16) Bytes() ([]byte, error) { + sector, err := b.BootSectorCommon.Bytes() + if err != nil { + return nil, err + } + + // BPB_TotSec16 AND BPB_TotSec32 + if b.TotalSectors < 0x10000 { + binary.LittleEndian.PutUint16(sector[19:21], uint16(b.TotalSectors)) + } else { + binary.LittleEndian.PutUint32(sector[32:36], b.TotalSectors) + } + + // BPB_FATSz16 + if b.SectorsPerFat > 0x10000 { + return nil, fmt.Errorf("SectorsPerFat value too big for non-FAT32: %d", b.SectorsPerFat) + } + + binary.LittleEndian.PutUint16(sector[22:24], uint16(b.SectorsPerFat)) + + // BS_DrvNum + sector[36] = b.DriveNumber + + // BS_BootSig + sector[38] = 0x29 + + // BS_VolID + binary.LittleEndian.PutUint32(sector[39:43], b.VolumeID) + + // BS_VolLab + if len(b.VolumeLabel) > 11 { + return nil, errors.New("VolumeLabel must be 11 bytes or less") + } + + for i, r := range b.VolumeLabel { + if r > unicode.MaxASCII { + return nil, fmt.Errorf("'%s' in VolumeLabel not a valid ASCII char. Must be ASCII.", r) + } + + sector[43+i] = byte(r) + } + + // BS_FilSysType + if len(b.FileSystemTypeLabel) > 8 { + return nil, errors.New("FileSystemTypeLabel must be 8 bytes or less") + } + + for i, r := range b.FileSystemTypeLabel { + if r > unicode.MaxASCII { + return nil, fmt.Errorf("'%s' in FileSystemTypeLabel not a valid ASCII char. Must be ASCII.", r) + } + + sector[54+i] = byte(r) + } + + return sector, nil +} + +type BootSectorFat32 struct { + BootSectorCommon + + RootCluster uint32 + FSInfoSector uint16 + BackupBootSector uint16 + DriveNumber uint8 + VolumeID uint32 + VolumeLabel string + FileSystemTypeLabel string +} + +func (b *BootSectorFat32) Bytes() ([]byte, error) { + sector, err := b.BootSectorCommon.Bytes() + if err != nil { + return nil, err + } + + // BPB_RootEntCount - must be 0 + sector[17] = 0 + sector[18] = 0 + + // BPB_FATSz32 + binary.LittleEndian.PutUint32(sector[36:40], b.SectorsPerFat) + + // BPB_ExtFlags - Unused? + + // BPB_FSVer. Explicitly set to 0 because that is really important + // to get correct. + sector[42] = 0 + sector[43] = 0 + + // BPB_RootClus + binary.LittleEndian.PutUint32(sector[44:48], b.RootCluster) + + // BPB_FSInfo + binary.LittleEndian.PutUint16(sector[48:50], b.FSInfoSector) + + // BPB_BkBootSec + binary.LittleEndian.PutUint16(sector[50:52], b.BackupBootSector) + + // BS_DrvNum + sector[64] = b.DriveNumber + + // BS_BootSig + sector[66] = 0x29 + + // BS_VolID + binary.LittleEndian.PutUint32(sector[67:71], b.VolumeID) + + // BS_VolLab + if len(b.VolumeLabel) > 11 { + return nil, errors.New("VolumeLabel must be 11 bytes or less") + } + + for i, r := range b.VolumeLabel { + if r > unicode.MaxASCII { + return nil, fmt.Errorf("'%s' in VolumeLabel not a valid ASCII char. Must be ASCII.", r) + } + + sector[71+i] = byte(r) + } + + // BS_FilSysType + if len(b.FileSystemTypeLabel) > 8 { + return nil, errors.New("FileSystemTypeLabel must be 8 bytes or less") + } + + for i, r := range b.FileSystemTypeLabel { + if r > unicode.MaxASCII { + return nil, fmt.Errorf("'%s' in FileSystemTypeLabel not a valid ASCII char. Must be ASCII.", r) + } + + sector[82+i] = byte(r) + } + + return sector, nil +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/cluster_chain.go b/vendor/github.com/mitchellh/go-fs/fat/cluster_chain.go new file mode 100644 index 000000000..a1f9161d7 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/cluster_chain.go @@ -0,0 +1,91 @@ +package fat + +import ( + "github.com/mitchellh/go-fs" + "io" + "math" +) + +type ClusterChain struct { + device fs.BlockDevice + fat *FAT + startCluster uint32 + readOffset uint32 + writeOffset uint32 +} + +func (c *ClusterChain) Read(p []byte) (n int, err error) { + bpc := c.fat.bs.BytesPerCluster() + chain := c.fat.Chain(c.startCluster) + + dataOffset := uint32(0) + for dataOffset < uint32(len(p)) { + chainIdx := c.readOffset / bpc + if int(chainIdx) >= len(chain) { + err = io.EOF + return + } + + clusterOffset := c.fat.bs.ClusterOffset(int(chain[chainIdx])) + clusterOffset += c.readOffset % bpc + dataOffsetEnd := dataOffset + bpc + dataOffsetEnd -= c.readOffset % bpc + dataOffsetEnd = uint32(math.Min(float64(dataOffsetEnd), float64(len(p)))) + + var nw int + nw, err = c.device.ReadAt(p[dataOffset:dataOffsetEnd], int64(clusterOffset)) + if err != nil { + return + } + + c.readOffset += uint32(nw) + dataOffset += uint32(nw) + n += nw + } + + return +} + +// Write will write to the cluster chain, expanding it if necessary. +func (c *ClusterChain) Write(p []byte) (n int, err error) { + bpc := c.fat.bs.BytesPerCluster() + chain := c.fat.Chain(c.startCluster) + chainLength := uint32(len(chain)) * bpc + + if chainLength < c.writeOffset+uint32(len(p)) { + // We need to grow the chain + bytesNeeded := (c.writeOffset + uint32(len(p))) - chainLength + clustersNeeded := int(math.Ceil(float64(bytesNeeded) / float64(bpc))) + chain, err = c.fat.ResizeChain(c.startCluster, len(chain)+clustersNeeded) + if err != nil { + return + } + + // Write the FAT out + if err = c.fat.WriteToDevice(c.device); err != nil { + return + } + } + + dataOffset := uint32(0) + for dataOffset < uint32(len(p)) { + chainIdx := c.writeOffset / bpc + clusterOffset := c.fat.bs.ClusterOffset(int(chain[chainIdx])) + clusterOffset += c.writeOffset % bpc + dataOffsetEnd := dataOffset + bpc + dataOffsetEnd -= c.writeOffset % bpc + dataOffsetEnd = uint32(math.Min(float64(dataOffsetEnd), float64(len(p)))) + + var nw int + nw, err = c.device.WriteAt(p[dataOffset:dataOffsetEnd], int64(clusterOffset)) + if err != nil { + return + } + + c.writeOffset += uint32(nw) + dataOffset += uint32(nw) + n += nw + } + + return +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/directory.go b/vendor/github.com/mitchellh/go-fs/fat/directory.go new file mode 100644 index 000000000..ff62319fd --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/directory.go @@ -0,0 +1,278 @@ +package fat + +import ( + "fmt" + "github.com/mitchellh/go-fs" + "strings" + "time" +) + +// Directory implements fs.Directory and is used to interface with +// a directory on a FAT filesystem. +type Directory struct { + device fs.BlockDevice + dirCluster *DirectoryCluster + fat *FAT +} + +// DirectoryEntry implements fs.DirectoryEntry and represents a single +// file/folder within a directory in a FAT filesystem. Note that the +// underlying directory entry data structures on the disk may be more +// than one to accomodate for long filenames. +type DirectoryEntry struct { + dir *Directory + lfnEntries []*DirectoryClusterEntry + entry *DirectoryClusterEntry + + name string +} + +// DecodeDirectoryEntry takes a list of entries, decodes the next full +// DirectoryEntry, and returns the newly created entry, the remaining +// entries, and an error, if there was one. +func DecodeDirectoryEntry(d *Directory, entries []*DirectoryClusterEntry) (*DirectoryEntry, []*DirectoryClusterEntry, error) { + var lfnEntries []*DirectoryClusterEntry + var entry *DirectoryClusterEntry + var name string + + // Skip all the deleted entries + for len(entries) > 0 && entries[0].deleted { + entries = entries[1:] + } + + // Skip the volume ID + if len(entries) > 0 && entries[0].IsVolumeId() { + entries = entries[1:] + } + + if len(entries) == 0 { + return nil, entries, nil + } + + // We have a long entry, so we have to traverse to the point where + // we're done. Also, calculate out the name and such. + if entries[0].IsLong() { + lfnEntries := make([]*DirectoryClusterEntry, 0, 3) + for entries[0].IsLong() { + lfnEntries = append(lfnEntries, entries[0]) + entries = entries[1:] + } + + var nameBytes []rune + nameBytes = make([]rune, 13*len(lfnEntries)) + for i := len(lfnEntries) - 1; i >= 0; i-- { + for _, char := range lfnEntries[i].longName { + nameBytes = append(nameBytes, char) + } + } + + name = string(nameBytes) + } + + // Get the short entry + entry = entries[0] + entries = entries[1:] + + // If the short entry is deleted, ignore everything + if entry.deleted { + return nil, entries, nil + } + + if name == "" { + name = strings.TrimSpace(entry.name) + ext := strings.TrimSpace(entry.ext) + if ext != "" { + name = fmt.Sprintf("%s.%s", name, ext) + } + } + + result := &DirectoryEntry{ + dir: d, + lfnEntries: lfnEntries, + entry: entry, + name: name, + } + + return result, entries, nil +} + +func (d *DirectoryEntry) Dir() (fs.Directory, error) { + if !d.IsDir() { + panic("not a directory") + } + + dirCluster, err := DecodeDirectoryCluster( + d.entry.cluster, d.dir.device, d.dir.fat) + if err != nil { + return nil, err + } + + result := &Directory{ + device: d.dir.device, + dirCluster: dirCluster, + fat: d.dir.fat, + } + + return result, nil +} + +func (d *DirectoryEntry) File() (fs.File, error) { + if d.IsDir() { + panic("not a file") + } + + result := &File{ + chain: &ClusterChain{ + device: d.dir.device, + fat: d.dir.fat, + startCluster: d.entry.cluster, + }, + dir: d.dir, + entry: d.entry, + } + + return result, nil +} + +func (d *DirectoryEntry) IsDir() bool { + return (d.entry.attr & AttrDirectory) == AttrDirectory +} + +func (d *DirectoryEntry) Name() string { + return d.name +} + +func (d *DirectoryEntry) ShortName() string { + if d.entry.name == "." || d.entry.name == ".." { + return d.entry.name + } + + return fmt.Sprintf("%s.%s", d.entry.name, d.entry.ext) +} + +func (d *Directory) AddDirectory(name string) (fs.DirectoryEntry, error) { + entry, err := d.addEntry(name, AttrDirectory) + if err != nil { + return nil, err + } + + // Create the new directory cluster + newDirCluster := NewDirectoryCluster( + entry.entry.cluster, d.dirCluster.startCluster, entry.entry.createTime) + + if err := newDirCluster.WriteToDevice(d.device, d.fat); err != nil { + return nil, err + } + + return entry, nil +} + +func (d *Directory) AddFile(name string) (fs.DirectoryEntry, error) { + entry, err := d.addEntry(name, DirectoryAttr(0)) + if err != nil { + return nil, err + } + + return entry, nil +} + +func (d *Directory) Entries() []fs.DirectoryEntry { + entries := d.dirCluster.entries + result := make([]fs.DirectoryEntry, 0, len(entries)/2) + for len(entries) > 0 { + var entry *DirectoryEntry + entry, entries, _ = DecodeDirectoryEntry(d, entries) + if entry != nil { + result = append(result, entry) + } + } + + return result +} + +func (d *Directory) Entry(name string) fs.DirectoryEntry { + name = strings.ToUpper(name) + + for _, entry := range d.Entries() { + if strings.ToUpper(entry.Name()) == name { + return entry + } + } + + return nil +} + +func (d *Directory) addEntry(name string, attr DirectoryAttr) (*DirectoryEntry, error) { + name = strings.TrimSpace(name) + + entries := d.Entries() + usedNames := make([]string, 0, len(entries)) + for _, entry := range entries { + if strings.ToUpper(entry.Name()) == strings.ToUpper(name) { + return nil, fmt.Errorf("name already exists: %s", name) + } + + // Add it to the list of used names + dirEntry := entry.(*DirectoryEntry) + usedNames = append(usedNames, dirEntry.ShortName()) + } + + shortName, err := generateShortName(name, usedNames) + if err != nil { + return nil, err + } + + var lfnEntries []*DirectoryClusterEntry + if shortName != strings.ToUpper(name) { + lfnEntries, err = NewLongDirectoryClusterEntry(name, shortName) + if err != nil { + return nil, err + } + } + + // Allocate space for a cluster + startCluster, err := d.fat.AllocChain() + if err != nil { + return nil, err + } + + createTime := time.Now() + + // Create the entry for the short name + shortParts := strings.Split(shortName, ".") + if len(shortParts) == 1 { + shortParts = append(shortParts, "") + } + + shortEntry := new(DirectoryClusterEntry) + shortEntry.attr = attr + shortEntry.name = shortParts[0] + shortEntry.ext = shortParts[1] + shortEntry.cluster = startCluster + shortEntry.accessTime = createTime + shortEntry.createTime = createTime + shortEntry.writeTime = createTime + + // Write the new FAT out + if err := d.fat.WriteToDevice(d.device); err != nil { + return nil, err + } + + // Write the entries out in this directory + if lfnEntries != nil { + d.dirCluster.entries = append(d.dirCluster.entries, lfnEntries...) + } + d.dirCluster.entries = append(d.dirCluster.entries, shortEntry) + + if err := d.dirCluster.WriteToDevice(d.device, d.fat); err != nil { + return nil, err + } + + newEntry := &DirectoryEntry{ + dir: d, + lfnEntries: lfnEntries, + entry: shortEntry, + } + + return newEntry, nil +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go b/vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go new file mode 100644 index 000000000..6d490d9e4 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go @@ -0,0 +1,438 @@ +package fat + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "github.com/mitchellh/go-fs" + "math" + "time" + "unicode/utf16" +) + +type DirectoryAttr uint8 + +const ( + AttrReadOnly DirectoryAttr = 0x01 + AttrHidden = 0x02 + AttrSystem = 0x04 + AttrVolumeId = 0x08 + AttrDirectory = 0x10 + AttrArchive = 0x20 + AttrLongName = AttrReadOnly | AttrHidden | AttrSystem | AttrVolumeId +) + +// The size in bytes of a single directory entry. +const DirectoryEntrySize = 32 + +// Mask applied to the ord of the last long entry. +const LastLongEntryMask = 0x40 + +// DirectoryCluster represents a cluster on the disk that contains +// entries/contents. +type DirectoryCluster struct { + entries []*DirectoryClusterEntry + fat16Root bool + startCluster uint32 +} + +// DirectoryClusterEntry is a single 32-byte entry that is part of the +// chain of entries in a directory cluster. +type DirectoryClusterEntry struct { + name string + ext string + attr DirectoryAttr + createTime time.Time + accessTime time.Time + writeTime time.Time + cluster uint32 + fileSize uint32 + deleted bool + + longOrd uint8 + longName string + longChecksum uint8 +} + +func DecodeDirectoryCluster(startCluster uint32, device fs.BlockDevice, fat *FAT) (*DirectoryCluster, error) { + bs := fat.bs + chain := fat.Chain(startCluster) + data := make([]byte, uint32(len(chain))*bs.BytesPerCluster()) + for i, clusterNumber := range chain { + dataOffset := uint32(i) * bs.BytesPerCluster() + devOffset := int64(bs.ClusterOffset(int(clusterNumber))) + chainData := data[dataOffset : dataOffset+bs.BytesPerCluster()] + + if _, err := device.ReadAt(chainData, devOffset); err != nil { + return nil, err + } + } + + result, err := decodeDirectoryCluster(data, bs) + if err != nil { + return nil, err + } + + result.startCluster = startCluster + return result, nil +} + +// DecodeFAT16RootDirectory decodes the FAT16 root directory structure +// from the device. +func DecodeFAT16RootDirectoryCluster(device fs.BlockDevice, bs *BootSectorCommon) (*DirectoryCluster, error) { + data := make([]byte, DirectoryEntrySize*bs.RootEntryCount) + if _, err := device.ReadAt(data, int64(bs.RootDirOffset())); err != nil { + return nil, err + } + + result, err := decodeDirectoryCluster(data, bs) + if err != nil { + return nil, err + } + + result.fat16Root = true + return result, nil +} + +func decodeDirectoryCluster(data []byte, bs *BootSectorCommon) (*DirectoryCluster, error) { + entries := make([]*DirectoryClusterEntry, 0, bs.RootEntryCount) + for i := uint16(0); i < uint16(len(data)/DirectoryEntrySize); i++ { + offset := i * DirectoryEntrySize + entryData := data[offset : offset+DirectoryEntrySize] + if entryData[0] == 0 { + break + } + + entry, err := DecodeDirectoryClusterEntry(entryData) + if err != nil { + return nil, err + } + + entries = append(entries, entry) + } + + result := &DirectoryCluster{ + entries: entries, + } + + return result, nil +} + +func NewDirectoryCluster(start uint32, parent uint32, t time.Time) *DirectoryCluster { + cluster := new(DirectoryCluster) + cluster.startCluster = start + + // Create the "." and ".." entries + cluster.entries = []*DirectoryClusterEntry{ + &DirectoryClusterEntry{ + accessTime: t, + attr: AttrDirectory, + cluster: start, + createTime: t, + name: ".", + writeTime: t, + }, + &DirectoryClusterEntry{ + accessTime: t, + attr: AttrDirectory, + cluster: parent, + createTime: t, + name: "..", + writeTime: t, + }, + } + + return cluster +} + +// NewFat16RootDirectory creates a new DirectoryCluster that is meant only +// to be the root directory of a FAT12/FAT16 filesystem. +func NewFat16RootDirectoryCluster(bs *BootSectorCommon, label string) (*DirectoryCluster, error) { + if bs.RootEntryCount == 0 { + return nil, errors.New("root entry count is 0 in boot sector") + } + + result := &DirectoryCluster{ + entries: make([]*DirectoryClusterEntry, 1, bs.RootEntryCount), + } + + // Create the volume ID entry + result.entries[0] = &DirectoryClusterEntry{ + attr: AttrVolumeId, + name: label, + cluster: 0, + } + + return result, nil +} + +// Bytes returns the on-disk byte data for this directory structure. +func (d *DirectoryCluster) Bytes() []byte { + result := make([]byte, cap(d.entries)*DirectoryEntrySize) + + for i, entry := range d.entries { + offset := i * DirectoryEntrySize + entryBytes := entry.Bytes() + copy(result[offset:offset+DirectoryEntrySize], entryBytes) + } + + return result +} + +// WriteToDevice writes the cluster to the device. +func (d *DirectoryCluster) WriteToDevice(device fs.BlockDevice, fat *FAT) error { + if d.fat16Root { + // Write the cluster to the FAT16 root directory location + offset := int64(fat.bs.RootDirOffset()) + if _, err := device.WriteAt(d.Bytes(), offset); err != nil { + return err + } + } else { + chain := &ClusterChain{ + device: device, + fat: fat, + startCluster: d.startCluster, + } + + if _, err := chain.Write(d.Bytes()); err != nil { + return err + } + } + + return nil +} + +// Bytes returns the on-disk byte data for this directory entry. +func (d *DirectoryClusterEntry) Bytes() []byte { + var result [DirectoryEntrySize]byte + + if d.longName != "" { + runes := bytes.Runes([]byte(d.longName)) + + // The name must be zero-terminated then padded with 0xFF + // up to 13 characters + if len(runes) < 13 { + runes = append(runes, 0) + for len(runes) < 13 { + runes = append(runes, 0xFFFF) + } + } + + // LDIR_Ord + result[0] = d.longOrd + + // LDIR_Name1 + for i := 0; i < int(math.Min(float64(len(runes)), 5)); i++ { + offset := 1 + (i * 2) + data := result[offset : offset+2] + binary.LittleEndian.PutUint16(data, uint16(runes[i])) + } + + // LDIR_Attr + result[11] = byte(AttrLongName) + + // LDIR_Type + result[12] = 0 + + // LDIR_Chksum + result[13] = d.longChecksum + + // LDIR_Name2 + for i := 0; i < 6; i++ { + offset := 14 + (i * 2) + data := result[offset : offset+2] + binary.LittleEndian.PutUint16(data, uint16(runes[i+5])) + } + + // LDIR_FstClusLO + result[26] = 0 + result[27] = 0 + + // LDIR_Name3 + for i := 0; i < 2; i++ { + offset := 28 + (i * 2) + data := result[offset : offset+2] + binary.LittleEndian.PutUint16(data, uint16(runes[i+11])) + } + } else { + // DIR_Name + var simpleName string + if d.name == "." || d.name == ".." { + simpleName = d.name + } else { + simpleName = fmt.Sprintf("%s.%s", d.name, d.ext) + } + copy(result[0:11], shortNameEntryValue(simpleName)) + + // DIR_Attr + result[11] = byte(d.attr) + + // DIR_CrtTime + crtDate, crtTime, crtTenths := encodeDOSTime(d.createTime) + result[13] = crtTenths + binary.LittleEndian.PutUint16(result[14:16], crtTime) + binary.LittleEndian.PutUint16(result[16:18], crtDate) + + // DIR_LstAccDate + accDate, _, _ := encodeDOSTime(d.accessTime) + binary.LittleEndian.PutUint16(result[18:20], accDate) + + // DIR_FstClusHI + binary.LittleEndian.PutUint16(result[20:22], uint16(d.cluster>>16)) + + // DIR_WrtTime and DIR_WrtDate + wrtDate, wrtTime, _ := encodeDOSTime(d.writeTime) + binary.LittleEndian.PutUint16(result[22:24], wrtTime) + binary.LittleEndian.PutUint16(result[24:26], wrtDate) + + // DIR_FstClusLO + binary.LittleEndian.PutUint16(result[26:28], uint16(d.cluster&0xFFFF)) + + // DIR_FileSize + binary.LittleEndian.PutUint32(result[28:32], d.fileSize) + } + + return result[:] +} + +// IsLong returns true if this is a long entry. +func (d *DirectoryClusterEntry) IsLong() bool { + return (d.attr & AttrLongName) == AttrLongName +} + +func (d *DirectoryClusterEntry) IsVolumeId() bool { + return (d.attr & AttrVolumeId) == AttrVolumeId +} + +// DecodeDirectoryClusterEntry decodes a single directory entry in the +// Directory structure. +func DecodeDirectoryClusterEntry(data []byte) (*DirectoryClusterEntry, error) { + var result DirectoryClusterEntry + + // Do the attributes so we can determine if we're dealing with long names + result.attr = DirectoryAttr(data[11]) + if (result.attr & AttrLongName) == AttrLongName { + result.longOrd = data[0] + + chars := make([]uint16, 13) + for i := 0; i < 5; i++ { + offset := 1 + (i * 2) + chars[i] = binary.LittleEndian.Uint16(data[offset : offset+2]) + } + + for i := 0; i < 6; i++ { + offset := 14 + (i * 2) + chars[i+5] = binary.LittleEndian.Uint16(data[offset : offset+2]) + } + + for i := 0; i < 2; i++ { + offset := 28 + (i * 2) + chars[i+11] = binary.LittleEndian.Uint16(data[offset : offset+2]) + } + + result.longName = string(utf16.Decode(chars)) + result.longChecksum = data[13] + } else { + result.deleted = data[0] == 0xE5 + + // Basic attributes + if data[0] == 0x05 { + data[0] = 0xE5 + } + + result.name = string(data[0:8]) + result.ext = string(data[8:11]) + + // Creation time + createTimeTenths := data[13] + createTimeWord := binary.LittleEndian.Uint16(data[14:16]) + createDateWord := binary.LittleEndian.Uint16(data[16:18]) + result.createTime = decodeDOSTime(createDateWord, createTimeWord, createTimeTenths) + + // Access time + accessDateWord := binary.LittleEndian.Uint16(data[18:20]) + result.accessTime = decodeDOSTime(accessDateWord, 0, 0) + + // Write time + writeTimeWord := binary.LittleEndian.Uint16(data[22:24]) + writeDateWord := binary.LittleEndian.Uint16(data[24:26]) + result.writeTime = decodeDOSTime(writeDateWord, writeTimeWord, 0) + + // Cluster + result.cluster = uint32(binary.LittleEndian.Uint16(data[20:22])) + result.cluster <<= 4 + result.cluster |= uint32(binary.LittleEndian.Uint16(data[26:28])) + + // File size + result.fileSize = binary.LittleEndian.Uint32(data[28:32]) + } + + return &result, nil +} + +// NewLongDirectoryClusterEntry returns the series of directory cluster +// entries that need to be written for a long directory entry. This list +// of entries does NOT contain the short name entry. +func NewLongDirectoryClusterEntry(name string, shortName string) ([]*DirectoryClusterEntry, error) { + // Split up the shortName properly + checksum := checksumShortName(shortNameEntryValue(shortName)) + + // Calcualte the number of entries we'll actually need to store + // the long name. + numLongEntries := len(name) / 13 + if len(name)%13 != 0 { + numLongEntries++ + } + + entries := make([]*DirectoryClusterEntry, numLongEntries) + for i := 0; i < numLongEntries; i++ { + entries[i] = new(DirectoryClusterEntry) + entry := entries[i] + entry.attr = AttrLongName + entry.longOrd = uint8(numLongEntries - i) + + if i == 0 { + entry.longOrd |= LastLongEntryMask + } + + // Calculate the offsets of the string for this entry + j := (numLongEntries - i - 1) * 13 + k := j + 13 + if k > len(name) { + k = len(name) + } + + entry.longChecksum = checksum + entry.longName = name[j:k] + } + + return entries, nil +} + +func decodeDOSTime(date, dosTime uint16, tenths uint8) time.Time { + return time.Date( + 1980+int(date>>9), + time.Month((date>>5)&0x0F), + int(date&0x1F), + int(dosTime>>11), + int((dosTime>>5)&0x3F), + int((dosTime&0x1F)*2), + int(tenths)*10*int(time.Millisecond), + time.Local) +} + +func encodeDOSTime(t time.Time) (uint16, uint16, uint8) { + var date uint16 = uint16((t.Year() - 1980) << 9) + date |= uint16(t.Month()) << 5 + date += uint16(t.Day() & 0xFF) + + var time uint16 = uint16(t.Hour() << 11) + time |= uint16(t.Minute() << 5) + time += uint16(t.Second() / 2) + + var tenths uint8 + // TODO(mitchellh): Do tenths + + return date, time, tenths +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/fat.go b/vendor/github.com/mitchellh/go-fs/fat/fat.go new file mode 100644 index 000000000..8597986f6 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/fat.go @@ -0,0 +1,268 @@ +package fat + +import ( + "errors" + "fmt" + "github.com/mitchellh/go-fs" + "math" +) + +// The first cluster that can really hold user data is always 2 +const FirstCluster = 2 + +// FAT is the actual file allocation table data structure that is +// stored on disk to describe the various clusters on the disk. +type FAT struct { + bs *BootSectorCommon + entries []uint32 +} + +func DecodeFAT(device fs.BlockDevice, bs *BootSectorCommon, n int) (*FAT, error) { + if n > int(bs.NumFATs) { + return nil, fmt.Errorf("FAT #%d greater than total FATs: %d", n, bs.NumFATs) + } + + data := make([]byte, bs.SectorsPerFat*uint32(bs.BytesPerSector)) + if _, err := device.ReadAt(data, int64(bs.FATOffset(n))); err != nil { + return nil, err + } + + result := &FAT{ + bs: bs, + entries: make([]uint32, FATEntryCount(bs)), + } + + fatType := bs.FATType() + for i := 0; i < int(FATEntryCount(bs)); i++ { + var entryData uint32 + switch fatType { + case FAT12: + entryData = fatReadEntry12(data, i) + case FAT16: + entryData = fatReadEntry16(data, i) + default: + entryData = fatReadEntry32(data, i) + } + + result.entries[i] = entryData + } + + return result, nil +} + +// NewFAT creates a new FAT data structure, properly initialized. +func NewFAT(bs *BootSectorCommon) (*FAT, error) { + result := &FAT{ + bs: bs, + entries: make([]uint32, FATEntryCount(bs)), + } + + // Set the initial two entries according to spec + result.entries[0] = (uint32(bs.Media) & 0xFF) | + (0xFFFFFF00 & result.entryMask()) + result.entries[1] = 0xFFFFFFFF & result.entryMask() + + return result, nil +} + +// Bytes returns the raw bytes for the FAT that should be written to +// the block device. +func (f *FAT) Bytes() []byte { + result := make([]byte, f.bs.SectorsPerFat*uint32(f.bs.BytesPerSector)) + + for i, entry := range f.entries { + switch f.bs.FATType() { + case FAT12: + f.writeEntry12(result, i, entry) + case FAT16: + f.writeEntry16(result, i, entry) + default: + f.writeEntry32(result, i, entry) + } + } + + return result +} + +func (f *FAT) AllocChain() (uint32, error) { + return f.allocNew() +} + +func (f *FAT) allocNew() (uint32, error) { + dataSize := (f.bs.TotalSectors * uint32(f.bs.BytesPerSector)) + dataSize -= f.bs.DataOffset() + clusterCount := dataSize / f.bs.BytesPerCluster() + lastClusterIndex := clusterCount + FirstCluster + + var availIdx uint32 + found := false + for i := uint32(FirstCluster); i < lastClusterIndex; i++ { + if f.entries[i] == 0 { + availIdx = i + found = true + break + } + } + + if !found { + return 0, errors.New("FAT FULL") + } + + // Mark that this is now in use + f.entries[availIdx] = 0xFFFFFFFF & f.entryMask() + + return availIdx, nil +} + +// Chain returns the chain of clusters starting at a certain cluster. +func (f *FAT) Chain(start uint32) []uint32 { + chain := make([]uint32, 0, 2) + + cluster := start + for { + chain = append(chain, cluster) + cluster = f.entries[cluster] + + if f.isEofCluster(cluster) || cluster == 0 { + break + } + } + + return chain +} + +// ResizeChain takes a given cluster number and resizes the chain +// to the given length. It returns the new chain of clusters. +func (f *FAT) ResizeChain(start uint32, length int) ([]uint32, error) { + chain := f.Chain(start) + if len(chain) == length { + return chain, nil + } + + change := int(math.Abs(float64(length - len(chain)))) + if length > len(chain) { + var lastCluster uint32 + + lastCluster = chain[0] + for i := 1; i < len(chain); i++ { + if f.isEofCluster(f.entries[lastCluster]) { + break + } + + lastCluster = chain[i] + } + + for i := 0; i < change; i++ { + newCluster, err := f.allocNew() + if err != nil { + return nil, err + } + + f.entries[lastCluster] = newCluster + lastCluster = newCluster + } + } else { + panic("making chains smaller not implemented yet") + } + + return f.Chain(start), nil +} + +func (f *FAT) WriteToDevice(device fs.BlockDevice) error { + fatBytes := f.Bytes() + for i := 0; i < int(f.bs.NumFATs); i++ { + offset := int64(f.bs.FATOffset(i)) + if _, err := device.WriteAt(fatBytes, offset); err != nil { + return err + } + } + + return nil +} + +func (f *FAT) entryMask() uint32 { + switch f.bs.FATType() { + case FAT12: + return 0x0FFF + case FAT16: + return 0xFFFF + default: + return 0x0FFFFFFF + } +} + +func (f *FAT) isEofCluster(cluster uint32) bool { + return cluster >= (0xFFFFFF8 & f.entryMask()) +} + +func (f *FAT) writeEntry12(data []byte, idx int, entry uint32) { + dataIdx := idx + (idx / 2) + data = data[dataIdx : dataIdx+2] + + if idx%2 == 1 { + // ODD + data[0] |= byte((entry & 0x0F) << 4) + data[1] = byte((entry >> 4) & 0xFF) + } else { + // Even + data[0] = byte(entry & 0xFF) + data[1] = byte((entry >> 8) & 0x0F) + } +} + +func (f *FAT) writeEntry16(data []byte, idx int, entry uint32) { + idx <<= 1 + data[idx] = byte(entry & 0xFF) + data[idx+1] = byte((entry >> 8) & 0xFF) +} + +func (f *FAT) writeEntry32(data []byte, idx int, entry uint32) { + idx <<= 2 + data[idx] = byte(entry & 0xFF) + data[idx+1] = byte((entry >> 8) & 0xFF) + data[idx+2] = byte((entry >> 16) & 0xFF) + data[idx+3] = byte((entry >> 24) & 0xFF) +} + +// FATEntryCount returns the number of entries per fat for the given +// boot sector. +func FATEntryCount(bs *BootSectorCommon) uint32 { + // Determine the number of entries that'll go in the FAT. + var entryCount uint32 = bs.SectorsPerFat * uint32(bs.BytesPerSector) + switch bs.FATType() { + case FAT12: + entryCount = uint32((uint64(entryCount) * 8) / 12) + case FAT16: + entryCount /= 2 + case FAT32: + entryCount /= 4 + default: + panic("impossible fat type") + } + + return entryCount +} + +func fatReadEntry12(data []byte, idx int) uint32 { + idx += idx / 2 + + var result uint32 = (uint32(data[idx+1]) << 8) | uint32(data[idx]) + if idx%2 == 0 { + return result & 0xFFF + } else { + return result >> 4 + } +} + +func fatReadEntry16(data []byte, idx int) uint32 { + idx <<= 1 + return (uint32(data[idx+1]) << 8) | uint32(data[idx]) +} + +func fatReadEntry32(data []byte, idx int) uint32 { + idx <<= 2 + return (uint32(data[idx+3]) << 24) | + (uint32(data[idx+2]) << 16) | + (uint32(data[idx+1]) << 8) | + uint32(data[idx+0]) +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/file.go b/vendor/github.com/mitchellh/go-fs/fat/file.go new file mode 100644 index 000000000..84d827e6b --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/file.go @@ -0,0 +1,26 @@ +package fat + +type File struct { + chain *ClusterChain + dir *Directory + entry *DirectoryClusterEntry +} + +func (f *File) Read(p []byte) (n int, err error) { + return f.chain.Read(p) +} + +func (f *File) Write(p []byte) (n int, err error) { + lastByte := f.chain.writeOffset + uint32(len(p)) + if lastByte > f.entry.fileSize { + // Increase the file size since we're writing past the end of the file + f.entry.fileSize = lastByte + + // Write the entry out + if err := f.dir.dirCluster.WriteToDevice(f.dir.device, f.dir.fat); err != nil { + return 0, err + } + } + + return f.chain.Write(p) +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/filesystem.go b/vendor/github.com/mitchellh/go-fs/fat/filesystem.go new file mode 100644 index 000000000..3102e0e6d --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/filesystem.go @@ -0,0 +1,57 @@ +package fat + +import ( + "github.com/mitchellh/go-fs" +) + +// FileSystem is the implementation of fs.FileSystem that can read a +// FAT filesystem. +type FileSystem struct { + bs *BootSectorCommon + device fs.BlockDevice + fat *FAT + rootDir *DirectoryCluster +} + +// New returns a new FileSystem for accessing a previously created +// FAT filesystem. +func New(device fs.BlockDevice) (*FileSystem, error) { + bs, err := DecodeBootSector(device) + if err != nil { + return nil, err + } + + fat, err := DecodeFAT(device, bs, 0) + if err != nil { + return nil, err + } + + var rootDir *DirectoryCluster + if bs.FATType() == FAT32 { + panic("FAT32 not implemented yet") + } else { + rootDir, err = DecodeFAT16RootDirectoryCluster(device, bs) + if err != nil { + return nil, err + } + } + + result := &FileSystem{ + bs: bs, + device: device, + fat: fat, + rootDir: rootDir, + } + + return result, nil +} + +func (f *FileSystem) RootDir() (fs.Directory, error) { + dir := &Directory{ + device: f.device, + dirCluster: f.rootDir, + fat: f.fat, + } + + return dir, nil +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/short_name.go b/vendor/github.com/mitchellh/go-fs/fat/short_name.go new file mode 100644 index 000000000..df03a2aaf --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/short_name.go @@ -0,0 +1,166 @@ +package fat + +import ( + "bytes" + "fmt" + "strings" +) + +// checksumShortName returns the checksum for the shortname that is used +// for the long name entries. +func checksumShortName(name string) uint8 { + var sum uint8 = name[0] + for i := uint8(1); i < 11; i++ { + sum = name[i] + (((sum & 1) << 7) + ((sum & 0xFE) >> 1)) + } + + return sum +} + +// generateShortName takes a list of existing short names and a long +// name and generates the next valid short name. This process is done +// according to the MS specification. +func generateShortName(longName string, used []string) (string, error) { + longName = strings.ToUpper(longName) + + // Split the string at the final "." + dotIdx := strings.LastIndex(longName, ".") + + var ext string + if dotIdx == -1 { + dotIdx = len(longName) + } else { + ext = longName[dotIdx+1 : len(longName)] + } + + ext = cleanShortString(ext) + ext = ext[0:len(ext)] + rawName := longName[0:dotIdx] + name := cleanShortString(rawName) + simpleName := fmt.Sprintf("%s.%s", name, ext) + if ext == "" { + simpleName = simpleName[0 : len(simpleName)-1] + } + + doSuffix := name != rawName || len(name) > 8 + if !doSuffix { + for _, usedSingle := range used { + if strings.ToUpper(usedSingle) == simpleName { + doSuffix = true + break + } + } + } + + if doSuffix { + found := false + for i := 1; i < 99999; i++ { + serial := fmt.Sprintf("~%d", i) + + nameOffset := 8 - len(serial) + if len(name) < nameOffset { + nameOffset = len(name) + } + + serialName := fmt.Sprintf("%s%s", name[0:nameOffset], serial) + simpleName = fmt.Sprintf("%s.%s", serialName, ext) + + exists := false + for _, usedSingle := range used { + if strings.ToUpper(usedSingle) == simpleName { + exists = true + break + } + } + + if !exists { + found = true + break + } + } + + if !found { + return "", fmt.Errorf("could not generate short name for %s", longName) + } + } + + return simpleName, nil +} + +// shortNameEntryValue returns the proper formatted short name value +// for the directory cluster entry. +func shortNameEntryValue(name string) string { + var shortParts []string + if name == "." || name == ".." { + shortParts = []string{name, ""} + } else { + shortParts = strings.Split(name, ".") + } + + if len(shortParts) == 1 { + shortParts = append(shortParts, "") + } + + if len(shortParts[0]) < 8 { + var temp bytes.Buffer + temp.WriteString(shortParts[0]) + for i := 0; i < 8-len(shortParts[0]); i++ { + temp.WriteRune(' ') + } + + shortParts[0] = temp.String() + } + + if len(shortParts[1]) < 3 { + var temp bytes.Buffer + temp.WriteString(shortParts[1]) + for i := 0; i < 3-len(shortParts[1]); i++ { + temp.WriteRune(' ') + } + + shortParts[1] = temp.String() + } + + return fmt.Sprintf("%s%s", shortParts[0], shortParts[1]) +} + +func cleanShortString(v string) string { + var result bytes.Buffer + for _, char := range v { + // We skip these chars + if char == '.' || char == ' ' { + continue + } + + if !validShortChar(char) { + char = '_' + } + + result.WriteRune(char) + } + + return result.String() +} + +func validShortChar(char rune) bool { + if char >= 'A' && char <= 'Z' { + return true + } + + if char >= '0' && char <= '9' { + return true + } + + validShortSymbols := []rune{ + '_', '^', '$', '~', '!', '#', '%', '&', '-', '{', '}', '(', + ')', '@', '\'', '`', + } + + for _, valid := range validShortSymbols { + if char == valid { + return true + } + } + + return false +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/super_floppy.go b/vendor/github.com/mitchellh/go-fs/fat/super_floppy.go new file mode 100644 index 000000000..acbcf2599 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/super_floppy.go @@ -0,0 +1,250 @@ +package fat + +import ( + "errors" + "fmt" + "github.com/mitchellh/go-fs" + "time" +) + +// SuperFloppyConfig is the configuration for various properties of +// a new super floppy formatted block device. Once this configuration is used +// to format a device, it must not be modified. +type SuperFloppyConfig struct { + // The type of FAT filesystem to use. + FATType FATType + + // The label of the drive. Defaults to "NONAME" + Label string + + // The OEM name for the FAT filesystem. Defaults to "gofs" if not set. + OEMName string +} + +// Formats an fs.BlockDevice with the "super floppy" format according +// to the given configuration. The "super floppy" standard means that the +// device will be formatted so that it does not contain a partition table. +// Instead, the entire device holds a single FAT file system. +func FormatSuperFloppy(device fs.BlockDevice, config *SuperFloppyConfig) error { + formatter := &superFloppyFormatter{ + config: config, + device: device, + } + + return formatter.format() +} + +// An internal struct that helps maintain state and perform calculations +// during a single formatting pass. +type superFloppyFormatter struct { + config *SuperFloppyConfig + device fs.BlockDevice +} + +func (f *superFloppyFormatter) format() error { + // First, create the boot sector on the device. Start by configuring + // the common elements of the boot sector. + sectorsPerCluster, err := f.SectorsPerCluster() + if err != nil { + return err + } + + bsCommon := BootSectorCommon{ + BytesPerSector: uint16(f.device.SectorSize()), + Media: MediaFixed, + NumFATs: 2, + NumHeads: 16, + OEMName: f.config.OEMName, + ReservedSectorCount: f.ReservedSectorCount(), + SectorsPerCluster: sectorsPerCluster, + SectorsPerTrack: 32, + TotalSectors: uint32(f.device.Len() / int64(f.device.SectorSize())), + } + + // Next, fill in the FAT-type specific boot sector information + switch f.config.FATType { + case FAT12, FAT16: + // Determine the filesystem type label, standard from the spec sheet + var label string + if f.config.FATType == FAT12 { + label = "FAT12 " + } else { + label = "FAT16 " + } + + // Determine the number of root directory entries + if f.device.Len() > 512*5*32 { + bsCommon.RootEntryCount = 512 + } else { + bsCommon.RootEntryCount = uint16(f.device.Len() / (5 * 32)) + } + + bsCommon.SectorsPerFat = f.sectorsPerFat(bsCommon.RootEntryCount, sectorsPerCluster) + + bs := &BootSectorFat16{ + BootSectorCommon: bsCommon, + FileSystemTypeLabel: label, + VolumeLabel: f.config.Label, + } + + // Write the boot sector + bsBytes, err := bs.Bytes() + if err != nil { + return err + } + + if _, err := f.device.WriteAt(bsBytes, 0); err != nil { + return err + } + case FAT32: + bsCommon.SectorsPerFat = f.sectorsPerFat(0, sectorsPerCluster) + + bs := &BootSectorFat32{ + BootSectorCommon: bsCommon, + FileSystemTypeLabel: "FAT32 ", + FSInfoSector: 1, + VolumeID: uint32(time.Now().Unix()), + VolumeLabel: f.config.Label, + } + + // Write the boot sector + bsBytes, err := bs.Bytes() + if err != nil { + return err + } + + if _, err := f.device.WriteAt(bsBytes, 0); err != nil { + return err + } + + // TODO(mitchellh): Create the fsinfo structure + // TODO(mitchellh): write the boot sector copy + default: + return fmt.Errorf("Unknown FAT type: %d", f.config.FATType) + } + + // Create the FATs + fat, err := NewFAT(&bsCommon) + if err != nil { + return err + } + + // Write the FAT + if err := fat.WriteToDevice(f.device); err != nil { + return err + } + + var rootDir *DirectoryCluster + if f.config.FATType == FAT32 { + panic("TODO") + } else { + rootDir, err = NewFat16RootDirectoryCluster(&bsCommon, f.config.Label) + if err != nil { + return err + } + + offset := int64(bsCommon.RootDirOffset()) + if _, err := f.device.WriteAt(rootDir.Bytes(), offset); err != nil { + return err + } + } + + return nil +} + +func (f *superFloppyFormatter) ReservedSectorCount() uint16 { + if f.config.FATType == FAT32 { + return 32 + } else { + return 1 + } +} + +func (f *superFloppyFormatter) SectorsPerCluster() (uint8, error) { + if f.config.FATType == FAT12 { + return f.defaultSectorsPerCluster12() + } else if f.config.FATType == FAT16 { + return f.defaultSectorsPerCluster16() + } else { + return f.defaultSectorsPerCluster32() + } +} + +func (f *superFloppyFormatter) defaultSectorsPerCluster12() (uint8, error) { + var result uint8 = 1 + sectors := f.device.Len() / int64(f.device.SectorSize()) + + for (sectors / int64(result)) > 4084 { + result *= 2 + if int(result)*f.device.SectorSize() > 4096 { + return 0, errors.New("disk too large for FAT12") + } + } + + return result, nil +} + +func (f *superFloppyFormatter) defaultSectorsPerCluster16() (uint8, error) { + sectors := f.device.Len() / int64(f.device.SectorSize()) + + if sectors <= 8400 { + return 0, errors.New("disk too small for FAT16") + } else if sectors > 4194304 { + return 0, errors.New("disk too large for FAT16") + } + + switch { + case sectors > 2097152: + return 64, nil + case sectors > 1048576: + return 32, nil + case sectors > 524288: + return 16, nil + case sectors > 262144: + return 8, nil + case sectors > 32680: + return 4, nil + default: + return 2, nil + } +} + +func (f *superFloppyFormatter) defaultSectorsPerCluster32() (uint8, error) { + sectors := f.device.Len() / int64(f.device.SectorSize()) + + if sectors <= 66600 { + return 0, errors.New("disk too small for FAT32") + } + + switch { + case sectors > 67108864: + return 64, nil + case sectors > 33554432: + return 32, nil + case sectors > 16777216: + return 16, nil + case sectors > 532480: + return 8, nil + default: + return 1, nil + } +} + +func (f *superFloppyFormatter) fatCount() uint8 { + return 2 +} + +func (f *superFloppyFormatter) sectorsPerFat(rootEntCount uint16, sectorsPerCluster uint8) uint32 { + bytesPerSec := f.device.SectorSize() + totalSectors := int(f.device.Len()) / bytesPerSec + rootDirSectors := ((int(rootEntCount) * 32) + (bytesPerSec - 1)) / bytesPerSec + + tmp1 := totalSectors - (int(f.ReservedSectorCount()) + rootDirSectors) + tmp2 := (256 * int(sectorsPerCluster)) + int(f.fatCount()) + + if f.config.FATType == FAT32 { + tmp2 /= 2 + } + + return uint32((tmp1 + (tmp2 - 1)) / tmp2) +} diff --git a/vendor/github.com/mitchellh/go-fs/fat/type.go b/vendor/github.com/mitchellh/go-fs/fat/type.go new file mode 100644 index 000000000..9fc5eda5d --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/fat/type.go @@ -0,0 +1,26 @@ +package fat + +import "github.com/mitchellh/go-fs" + +// FATType is a simple enum of the available FAT filesystem types. +type FATType uint8 + +const ( + FAT12 FATType = iota + FAT16 + FAT32 +) + +// TypeForDevice determines the usable FAT type based solely on +// size information about the block device. +func TypeForDevice(device fs.BlockDevice) FATType { + sizeInMB := device.Len() / (1024 * 1024) + switch { + case sizeInMB < 4: + return FAT12 + case sizeInMB < 512: + return FAT16 + default: + return FAT32 + } +} diff --git a/vendor/github.com/mitchellh/go-fs/file.go b/vendor/github.com/mitchellh/go-fs/file.go new file mode 100644 index 000000000..a19eb376a --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/file.go @@ -0,0 +1,9 @@ +package fs + +import "io" + +// File is a single file within a filesystem. +type File interface { + io.Reader + io.Writer +} diff --git a/vendor/github.com/mitchellh/go-fs/file_disk.go b/vendor/github.com/mitchellh/go-fs/file_disk.go new file mode 100644 index 000000000..da4497302 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/file_disk.go @@ -0,0 +1,52 @@ +package fs + +import ( + "errors" + "os" +) + +// A FileDisk is an implementation of a BlockDevice that uses a +// *os.File as its backing store. +type FileDisk struct { + f *os.File + size int64 +} + +// NewFileDisk creates a new FileDisk from the given *os.File. The +// file must already be created and set the to the proper size. +func NewFileDisk(f *os.File) (*FileDisk, error) { + fi, err := f.Stat() + if err != nil { + return nil, err + } + + if fi.IsDir() { + return nil, errors.New("file is a directory") + } + + return &FileDisk{ + f: f, + size: fi.Size(), + }, nil +} + +func (f *FileDisk) Close() error { + return f.f.Close() +} + +func (f *FileDisk) Len() int64 { + return f.size +} + +func (f *FileDisk) ReadAt(p []byte, off int64) (int, error) { + return f.f.ReadAt(p, off) +} + +func (f *FileDisk) SectorSize() int { + // Hardcoded for now, one day we may want to make this customizable + return 512 +} + +func (f *FileDisk) WriteAt(p []byte, off int64) (int, error) { + return f.f.WriteAt(p, off) +} diff --git a/vendor/github.com/mitchellh/go-fs/filesystem.go b/vendor/github.com/mitchellh/go-fs/filesystem.go new file mode 100644 index 000000000..6cf913736 --- /dev/null +++ b/vendor/github.com/mitchellh/go-fs/filesystem.go @@ -0,0 +1,8 @@ +package fs + +// A FileSystem provides access to a tree hierarchy of directories +// and files. +type FileSystem interface { + // RootDir returns the single root directory. + RootDir() (Directory, error) +} diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 000000000..d70706d5b --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md @@ -0,0 +1,14 @@ +# go-homedir + +This is a Go library for detecting the user's home directory without +the use of cgo, so the library can be used in cross-compilation environments. + +Usage is incredibly simple, just call `homedir.Dir()` to get the home directory +for a user, and `homedir.Expand()` to expand the `~` in a path to the home +directory. + +**Why not just use `os/user`?** The built-in `os/user` package requires +cgo on Darwin systems. This means that any Go code that uses that package +cannot cross compile. But 99% of the time the use for `os/user` is just to +retrieve the home directory, which we can do for the current user without +cgo. This library does that, enabling cross-compilation. diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go new file mode 100644 index 000000000..6944957d5 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -0,0 +1,132 @@ +package homedir + +import ( + "bytes" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" +) + +// DisableCache will disable caching of the home directory. Caching is enabled +// by default. +var DisableCache bool + +var homedirCache string +var cacheLock sync.RWMutex + +// Dir returns the home directory for the executing user. +// +// This uses an OS-specific method for discovering the home directory. +// An error is returned if a home directory cannot be detected. +func Dir() (string, error) { + if !DisableCache { + cacheLock.RLock() + cached := homedirCache + cacheLock.RUnlock() + if cached != "" { + return cached, nil + } + } + + cacheLock.Lock() + defer cacheLock.Unlock() + + var result string + var err error + if runtime.GOOS == "windows" { + result, err = dirWindows() + } else { + // Unix-like system, so just assume Unix + result, err = dirUnix() + } + + if err != nil { + return "", err + } + homedirCache = result + return result, nil +} + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func Expand(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := Dir() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +func dirUnix() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + // If that fails, try getent + var stdout bytes.Buffer + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If "getent" is missing, ignore it + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + + // If all else fails, try the shell + stdout.Reset() + cmd = exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil +} + +func dirWindows() (string, error) { + drive := os.Getenv("HOMEDRIVE") + path := os.Getenv("HOMEPATH") + home := drive + path + if drive == "" || path == "" { + home = os.Getenv("USERPROFILE") + } + if home == "" { + return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") + } + + return home, nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/LICENSE b/vendor/github.com/mitchellh/go-vnc/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-vnc/README.md b/vendor/github.com/mitchellh/go-vnc/README.md new file mode 100644 index 000000000..cb0575b9c --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/README.md @@ -0,0 +1,16 @@ +# VNC Library for Go + +go-vnc is a VNC library for Go, initially supporting VNC clients but +with the goal of eventually implementing a VNC server. + +This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143). + +## Usage & Installation + +The library is installable via standard `go get`. The package name is `vnc`. + +``` +$ go get github.com/mitchellh/go-vnc +``` + +Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc diff --git a/vendor/github.com/mitchellh/go-vnc/client.go b/vendor/github.com/mitchellh/go-vnc/client.go new file mode 100644 index 000000000..91402c944 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/client.go @@ -0,0 +1,482 @@ +// Package vnc implements a VNC client. +// +// References: +// [PROTOCOL]: http://tools.ietf.org/html/rfc6143 +package vnc + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "net" + "unicode" +) + +type ClientConn struct { + c net.Conn + config *ClientConfig + + // If the pixel format uses a color map, then this is the color + // map that is used. This should not be modified directly, since + // the data comes from the server. + ColorMap [256]Color + + // Encodings supported by the client. This should not be modified + // directly. Instead, SetEncodings should be used. + Encs []Encoding + + // Width of the frame buffer in pixels, sent from the server. + FrameBufferWidth uint16 + + // Height of the frame buffer in pixels, sent from the server. + FrameBufferHeight uint16 + + // Name associated with the desktop, sent from the server. + DesktopName string + + // The pixel format associated with the connection. This shouldn't + // be modified. If you wish to set a new pixel format, use the + // SetPixelFormat method. + PixelFormat PixelFormat +} + +// A ClientConfig structure is used to configure a ClientConn. After +// one has been passed to initialize a connection, it must not be modified. +type ClientConfig struct { + // A slice of ClientAuth methods. Only the first instance that is + // suitable by the server will be used to authenticate. + Auth []ClientAuth + + // Exclusive determines whether the connection is shared with other + // clients. If true, then all other clients connected will be + // disconnected when a connection is established to the VNC server. + Exclusive bool + + // The channel that all messages received from the server will be + // sent on. If the channel blocks, then the goroutine reading data + // from the VNC server may block indefinitely. It is up to the user + // of the library to ensure that this channel is properly read. + // If this is not set, then all messages will be discarded. + ServerMessageCh chan<- ServerMessage + + // A slice of supported messages that can be read from the server. + // This only needs to contain NEW server messages, and doesn't + // need to explicitly contain the RFC-required messages. + ServerMessages []ServerMessage +} + +func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error) { + conn := &ClientConn{ + c: c, + config: cfg, + } + + if err := conn.handshake(); err != nil { + conn.Close() + return nil, err + } + + go conn.mainLoop() + + return conn, nil +} + +func (c *ClientConn) Close() error { + return c.c.Close() +} + +// CutText tells the server that the client has new text in its cut buffer. +// The text string MUST only contain Latin-1 characters. This encoding +// is compatible with Go's native string format, but can only use up to +// unicode.MaxLatin values. +// +// See RFC 6143 Section 7.5.6 +func (c *ClientConn) CutText(text string) error { + var buf bytes.Buffer + + // This is the fixed size data we'll send + fixedData := []interface{}{ + uint8(6), + uint8(0), + uint8(0), + uint8(0), + uint32(len(text)), + } + + for _, val := range fixedData { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + for _, char := range text { + if char > unicode.MaxLatin1 { + return fmt.Errorf("Character '%s' is not valid Latin-1", char) + } + + if err := binary.Write(&buf, binary.BigEndian, uint8(char)); err != nil { + return err + } + } + + dataLength := 8 + len(text) + if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil { + return err + } + + return nil +} + +// Requests a framebuffer update from the server. There may be an indefinite +// time between the request and the actual framebuffer update being +// received. +// +// See RFC 6143 Section 7.5.3 +func (c *ClientConn) FramebufferUpdateRequest(incremental bool, x, y, width, height uint16) error { + var buf bytes.Buffer + var incrementalByte uint8 = 0 + + if incremental { + incrementalByte = 1 + } + + data := []interface{}{ + uint8(3), + incrementalByte, + x, y, width, height, + } + + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + if _, err := c.c.Write(buf.Bytes()[0:10]); err != nil { + return err + } + + return nil +} + +// KeyEvent indiciates a key press or release and sends it to the server. +// The key is indicated using the X Window System "keysym" value. Use +// Google to find a reference of these values. To simulate a key press, +// you must send a key with both a down event, and a non-down event. +// +// See 7.5.4. +func (c *ClientConn) KeyEvent(keysym uint32, down bool) error { + var downFlag uint8 = 0 + if down { + downFlag = 1 + } + + data := []interface{}{ + uint8(4), + downFlag, + uint8(0), + uint8(0), + keysym, + } + + for _, val := range data { + if err := binary.Write(c.c, binary.BigEndian, val); err != nil { + return err + } + } + + return nil +} + +// PointerEvent indicates that pointer movement or a pointer button +// press or release. +// +// The mask is a bitwise mask of various ButtonMask values. When a button +// is set, it is pressed, when it is unset, it is released. +// +// See RFC 6143 Section 7.5.5 +func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error { + var buf bytes.Buffer + + data := []interface{}{ + uint8(5), + uint8(mask), + x, + y, + } + + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + if _, err := c.c.Write(buf.Bytes()[0:6]); err != nil { + return err + } + + return nil +} + +// SetEncodings sets the encoding types in which the pixel data can +// be sent from the server. After calling this method, the encs slice +// given should not be modified. +// +// See RFC 6143 Section 7.5.2 +func (c *ClientConn) SetEncodings(encs []Encoding) error { + data := make([]interface{}, 3+len(encs)) + data[0] = uint8(2) + data[1] = uint8(0) + data[2] = uint16(len(encs)) + + for i, enc := range encs { + data[3+i] = int32(enc.Type()) + } + + var buf bytes.Buffer + for _, val := range data { + if err := binary.Write(&buf, binary.BigEndian, val); err != nil { + return err + } + } + + dataLength := 4 + (4 * len(encs)) + if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil { + return err + } + + c.Encs = encs + + return nil +} + +// SetPixelFormat sets the format in which pixel values should be sent +// in FramebufferUpdate messages from the server. +// +// See RFC 6143 Section 7.5.1 +func (c *ClientConn) SetPixelFormat(format *PixelFormat) error { + var keyEvent [20]byte + keyEvent[0] = 0 + + pfBytes, err := writePixelFormat(format) + if err != nil { + return err + } + + // Copy the pixel format bytes into the proper slice location + copy(keyEvent[4:], pfBytes) + + // Send the data down the connection + if _, err := c.c.Write(keyEvent[:]); err != nil { + return err + } + + // Reset the color map as according to RFC. + var newColorMap [256]Color + c.ColorMap = newColorMap + + return nil +} + +const pvLen = 12 // ProtocolVersion message length. + +func parseProtocolVersion(pv []byte) (uint, uint, error) { + var major, minor uint + + if len(pv) < pvLen { + return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), pvLen) + } + + l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor) + if l != 2 { + return 0, 0, fmt.Errorf("error parsing ProtocolVersion.") + } + if err != nil { + return 0, 0, err + } + + return major, minor, nil +} + +func (c *ClientConn) handshake() error { + var protocolVersion [pvLen]byte + + // 7.1.1, read the ProtocolVersion message sent by the server. + if _, err := io.ReadFull(c.c, protocolVersion[:]); err != nil { + return err + } + + maxMajor, maxMinor, err := parseProtocolVersion(protocolVersion[:]) + if err != nil { + return err + } + if maxMajor < 3 { + return fmt.Errorf("unsupported major version, less than 3: %d", maxMajor) + } + if maxMinor < 8 { + return fmt.Errorf("unsupported minor version, less than 8: %d", maxMinor) + } + + // Respond with the version we will support + if _, err = c.c.Write([]byte("RFB 003.008\n")); err != nil { + return err + } + + // 7.1.2 Security Handshake from server + var numSecurityTypes uint8 + if err = binary.Read(c.c, binary.BigEndian, &numSecurityTypes); err != nil { + return err + } + + if numSecurityTypes == 0 { + return fmt.Errorf("no security types: %s", c.readErrorReason()) + } + + securityTypes := make([]uint8, numSecurityTypes) + if err = binary.Read(c.c, binary.BigEndian, &securityTypes); err != nil { + return err + } + + clientSecurityTypes := c.config.Auth + if clientSecurityTypes == nil { + clientSecurityTypes = []ClientAuth{new(ClientAuthNone)} + } + + var auth ClientAuth +FindAuth: + for _, curAuth := range clientSecurityTypes { + for _, securityType := range securityTypes { + if curAuth.SecurityType() == securityType { + // We use the first matching supported authentication + auth = curAuth + break FindAuth + } + } + } + + if auth == nil { + return fmt.Errorf("no suitable auth schemes found. server supported: %#v", securityTypes) + } + + // Respond back with the security type we'll use + if err = binary.Write(c.c, binary.BigEndian, auth.SecurityType()); err != nil { + return err + } + + if err = auth.Handshake(c.c); err != nil { + return err + } + + // 7.1.3 SecurityResult Handshake + var securityResult uint32 + if err = binary.Read(c.c, binary.BigEndian, &securityResult); err != nil { + return err + } + + if securityResult == 1 { + return fmt.Errorf("security handshake failed: %s", c.readErrorReason()) + } + + // 7.3.1 ClientInit + var sharedFlag uint8 = 1 + if c.config.Exclusive { + sharedFlag = 0 + } + + if err = binary.Write(c.c, binary.BigEndian, sharedFlag); err != nil { + return err + } + + // 7.3.2 ServerInit + if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferWidth); err != nil { + return err + } + + if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferHeight); err != nil { + return err + } + + // Read the pixel format + if err = readPixelFormat(c.c, &c.PixelFormat); err != nil { + return err + } + + var nameLength uint32 + if err = binary.Read(c.c, binary.BigEndian, &nameLength); err != nil { + return err + } + + nameBytes := make([]uint8, nameLength) + if err = binary.Read(c.c, binary.BigEndian, &nameBytes); err != nil { + return err + } + + c.DesktopName = string(nameBytes) + + return nil +} + +// mainLoop reads messages sent from the server and routes them to the +// proper channels for users of the client to read. +func (c *ClientConn) mainLoop() { + defer c.Close() + + // Build the map of available server messages + typeMap := make(map[uint8]ServerMessage) + + defaultMessages := []ServerMessage{ + new(FramebufferUpdateMessage), + new(SetColorMapEntriesMessage), + new(BellMessage), + new(ServerCutTextMessage), + } + + for _, msg := range defaultMessages { + typeMap[msg.Type()] = msg + } + + if c.config.ServerMessages != nil { + for _, msg := range c.config.ServerMessages { + typeMap[msg.Type()] = msg + } + } + + for { + var messageType uint8 + if err := binary.Read(c.c, binary.BigEndian, &messageType); err != nil { + break + } + + msg, ok := typeMap[messageType] + if !ok { + // Unsupported message type! Bad! + break + } + + parsedMsg, err := msg.Read(c, c.c) + if err != nil { + break + } + + if c.config.ServerMessageCh == nil { + continue + } + + c.config.ServerMessageCh <- parsedMsg + } +} + +func (c *ClientConn) readErrorReason() string { + var reasonLen uint32 + if err := binary.Read(c.c, binary.BigEndian, &reasonLen); err != nil { + return "" + } + + reason := make([]uint8, reasonLen) + if err := binary.Read(c.c, binary.BigEndian, &reason); err != nil { + return "" + } + + return string(reason) +} diff --git a/vendor/github.com/mitchellh/go-vnc/client_auth.go b/vendor/github.com/mitchellh/go-vnc/client_auth.go new file mode 100644 index 000000000..4ae7be9fc --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/client_auth.go @@ -0,0 +1,124 @@ +package vnc + +import ( + "net" + + "crypto/des" + "encoding/binary" +) + +// A ClientAuth implements a method of authenticating with a remote server. +type ClientAuth interface { + // SecurityType returns the byte identifier sent by the server to + // identify this authentication scheme. + SecurityType() uint8 + + // Handshake is called when the authentication handshake should be + // performed, as part of the general RFB handshake. (see 7.2.1) + Handshake(net.Conn) error +} + +// ClientAuthNone is the "none" authentication. See 7.2.1 +type ClientAuthNone byte + +func (*ClientAuthNone) SecurityType() uint8 { + return 1 +} + +func (*ClientAuthNone) Handshake(net.Conn) error { + return nil +} + +// PasswordAuth is VNC authentication, 7.2.2 +type PasswordAuth struct { + Password string +} + +func (p *PasswordAuth) SecurityType() uint8 { + return 2 +} + +func (p *PasswordAuth) Handshake(c net.Conn) error { + randomValue := make([]uint8, 16) + if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil { + return err + } + + crypted, err := p.encrypt(p.Password, randomValue) + + if (err != nil) { + return err + } + + if err := binary.Write(c, binary.BigEndian, &crypted); err != nil { + return err + } + + return nil +} + +func (p *PasswordAuth) reverseBits(b byte) byte { + var reverse = [256]int{ + 0, 128, 64, 192, 32, 160, 96, 224, + 16, 144, 80, 208, 48, 176, 112, 240, + 8, 136, 72, 200, 40, 168, 104, 232, + 24, 152, 88, 216, 56, 184, 120, 248, + 4, 132, 68, 196, 36, 164, 100, 228, + 20, 148, 84, 212, 52, 180, 116, 244, + 12, 140, 76, 204, 44, 172, 108, 236, + 28, 156, 92, 220, 60, 188, 124, 252, + 2, 130, 66, 194, 34, 162, 98, 226, + 18, 146, 82, 210, 50, 178, 114, 242, + 10, 138, 74, 202, 42, 170, 106, 234, + 26, 154, 90, 218, 58, 186, 122, 250, + 6, 134, 70, 198, 38, 166, 102, 230, + 22, 150, 86, 214, 54, 182, 118, 246, + 14, 142, 78, 206, 46, 174, 110, 238, + 30, 158, 94, 222, 62, 190, 126, 254, + 1, 129, 65, 193, 33, 161, 97, 225, + 17, 145, 81, 209, 49, 177, 113, 241, + 9, 137, 73, 201, 41, 169, 105, 233, + 25, 153, 89, 217, 57, 185, 121, 249, + 5, 133, 69, 197, 37, 165, 101, 229, + 21, 149, 85, 213, 53, 181, 117, 245, + 13, 141, 77, 205, 45, 173, 109, 237, + 29, 157, 93, 221, 61, 189, 125, 253, + 3, 131, 67, 195, 35, 163, 99, 227, + 19, 147, 83, 211, 51, 179, 115, 243, + 11, 139, 75, 203, 43, 171, 107, 235, + 27, 155, 91, 219, 59, 187, 123, 251, + 7, 135, 71, 199, 39, 167, 103, 231, + 23, 151, 87, 215, 55, 183, 119, 247, + 15, 143, 79, 207, 47, 175, 111, 239, + 31, 159, 95, 223, 63, 191, 127, 255, + } + + return byte(reverse[int(b)]) +} + +func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) { + keyBytes := []byte{0,0,0,0,0,0,0,0} + + if len(key) > 8 { + key = key[:8] + } + + for i := 0; i < len(key); i++ { + keyBytes[i] = p.reverseBits(key[i]) + } + + block, err := des.NewCipher(keyBytes) + + if err != nil { + return nil, err + } + + result1 := make([]byte, 8) + block.Encrypt(result1, bytes) + result2 := make([]byte, 8) + block.Encrypt(result2, bytes[8:]) + + crypted := append(result1, result2...) + + return crypted, nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/color.go b/vendor/github.com/mitchellh/go-vnc/color.go new file mode 100644 index 000000000..30df46739 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/color.go @@ -0,0 +1,6 @@ +package vnc + +// Color represents a single color in a color map. +type Color struct { + R, G, B uint16 +} diff --git a/vendor/github.com/mitchellh/go-vnc/encoding.go b/vendor/github.com/mitchellh/go-vnc/encoding.go new file mode 100644 index 000000000..719859571 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/encoding.go @@ -0,0 +1,69 @@ +package vnc + +import ( + "encoding/binary" + "io" +) + +// An Encoding implements a method for encoding pixel data that is +// sent by the server to the client. +type Encoding interface { + // The number that uniquely identifies this encoding type. + Type() int32 + + // Read reads the contents of the encoded pixel data from the reader. + // This should return a new Encoding implementation that contains + // the proper data. + Read(*ClientConn, *Rectangle, io.Reader) (Encoding, error) +} + +// RawEncoding is raw pixel data sent by the server. +// +// See RFC 6143 Section 7.7.1 +type RawEncoding struct { + Colors []Color +} + +func (*RawEncoding) Type() int32 { + return 0 +} + +func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { + bytesPerPixel := c.PixelFormat.BPP / 8 + pixelBytes := make([]uint8, bytesPerPixel) + + var byteOrder binary.ByteOrder = binary.LittleEndian + if c.PixelFormat.BigEndian { + byteOrder = binary.BigEndian + } + + colors := make([]Color, int(rect.Height)*int(rect.Width)) + + for y := uint16(0); y < rect.Height; y++ { + for x := uint16(0); x < rect.Width; x++ { + if _, err := io.ReadFull(r, pixelBytes); err != nil { + return nil, err + } + + var rawPixel uint32 + if c.PixelFormat.BPP == 8 { + rawPixel = uint32(pixelBytes[0]) + } else if c.PixelFormat.BPP == 16 { + rawPixel = uint32(byteOrder.Uint16(pixelBytes)) + } else if c.PixelFormat.BPP == 32 { + rawPixel = byteOrder.Uint32(pixelBytes) + } + + color := &colors[int(y)*int(rect.Width)+int(x)] + if c.PixelFormat.TrueColor { + color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax)) + color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax)) + color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax)) + } else { + *color = c.ColorMap[rawPixel] + } + } + } + + return &RawEncoding{colors}, nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/pixel_format.go b/vendor/github.com/mitchellh/go-vnc/pixel_format.go new file mode 100644 index 000000000..ff8edbff5 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/pixel_format.go @@ -0,0 +1,151 @@ +package vnc + +import ( + "bytes" + "encoding/binary" + "io" +) + +// PixelFormat describes the way a pixel is formatted for a VNC connection. +// +// See RFC 6143 Section 7.4 for information on each of the fields. +type PixelFormat struct { + BPP uint8 + Depth uint8 + BigEndian bool + TrueColor bool + RedMax uint16 + GreenMax uint16 + BlueMax uint16 + RedShift uint8 + GreenShift uint8 + BlueShift uint8 +} + +func readPixelFormat(r io.Reader, result *PixelFormat) error { + var rawPixelFormat [16]byte + if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil { + return err + } + + var pfBoolByte uint8 + brPF := bytes.NewReader(rawPixelFormat[:]) + if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil { + return err + } + + if pfBoolByte != 0 { + // Big endian is true + result.BigEndian = true + } + + if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil { + return err + } + + if pfBoolByte != 0 { + // True Color is true. So we also have to read all the color max & shifts. + result.TrueColor = true + + if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil { + return err + } + + if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil { + return err + } + } + + return nil +} + +func writePixelFormat(format *PixelFormat) ([]byte, error) { + var buf bytes.Buffer + + // Byte 1 + if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil { + return nil, err + } + + // Byte 2 + if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil { + return nil, err + } + + var boolByte byte + if format.BigEndian { + boolByte = 1 + } else { + boolByte = 0 + } + + // Byte 3 (BigEndian) + if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { + return nil, err + } + + if format.TrueColor { + boolByte = 1 + } else { + boolByte = 0 + } + + // Byte 4 (TrueColor) + if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { + return nil, err + } + + // If we have true color enabled then we have to fill in the rest of the + // structure with the color values. + if format.TrueColor { + if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil { + return nil, err + } + + if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil { + return nil, err + } + } + + return buf.Bytes()[0:16], nil +} diff --git a/vendor/github.com/mitchellh/go-vnc/pointer.go b/vendor/github.com/mitchellh/go-vnc/pointer.go new file mode 100644 index 000000000..86d84e396 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/pointer.go @@ -0,0 +1,16 @@ +package vnc + +// ButtonMask represents a mask of pointer presses/releases. +type ButtonMask uint8 + +// All available button mask components. +const ( + ButtonLeft ButtonMask = 1 << iota + ButtonMiddle + ButtonRight + Button4 + Button5 + Button6 + Button7 + Button8 +) diff --git a/vendor/github.com/mitchellh/go-vnc/server_messages.go b/vendor/github.com/mitchellh/go-vnc/server_messages.go new file mode 100644 index 000000000..c0aae5665 --- /dev/null +++ b/vendor/github.com/mitchellh/go-vnc/server_messages.go @@ -0,0 +1,192 @@ +package vnc + +import ( + "encoding/binary" + "fmt" + "io" +) + +// A ServerMessage implements a message sent from the server to the client. +type ServerMessage interface { + // The type of the message that is sent down on the wire. + Type() uint8 + + // Read reads the contents of the message from the reader. At the point + // this is called, the message type has already been read from the reader. + // This should return a new ServerMessage that is the appropriate type. + Read(*ClientConn, io.Reader) (ServerMessage, error) +} + +// FramebufferUpdateMessage consists of a sequence of rectangles of +// pixel data that the client should put into its framebuffer. +type FramebufferUpdateMessage struct { + Rectangles []Rectangle +} + +// Rectangle represents a rectangle of pixel data. +type Rectangle struct { + X uint16 + Y uint16 + Width uint16 + Height uint16 + Enc Encoding +} + +func (*FramebufferUpdateMessage) Type() uint8 { + return 0 +} + +func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var numRects uint16 + if err := binary.Read(r, binary.BigEndian, &numRects); err != nil { + return nil, err + } + + // Build the map of encodings supported + encMap := make(map[int32]Encoding) + for _, enc := range c.Encs { + encMap[enc.Type()] = enc + } + + // We must always support the raw encoding + rawEnc := new(RawEncoding) + encMap[rawEnc.Type()] = rawEnc + + rects := make([]Rectangle, numRects) + for i := uint16(0); i < numRects; i++ { + var encodingType int32 + + rect := &rects[i] + data := []interface{}{ + &rect.X, + &rect.Y, + &rect.Width, + &rect.Height, + &encodingType, + } + + for _, val := range data { + if err := binary.Read(r, binary.BigEndian, val); err != nil { + return nil, err + } + } + + enc, ok := encMap[encodingType] + if !ok { + return nil, fmt.Errorf("unsupported encoding type: %d", encodingType) + } + + var err error + rect.Enc, err = enc.Read(c, rect, r) + if err != nil { + return nil, err + } + } + + return &FramebufferUpdateMessage{rects}, nil +} + +// SetColorMapEntriesMessage is sent by the server to set values into +// the color map. This message will automatically update the color map +// for the associated connection, but contains the color change data +// if the consumer wants to read it. +// +// See RFC 6143 Section 7.6.2 +type SetColorMapEntriesMessage struct { + FirstColor uint16 + Colors []Color +} + +func (*SetColorMapEntriesMessage) Type() uint8 { + return 1 +} + +func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var result SetColorMapEntriesMessage + if err := binary.Read(r, binary.BigEndian, &result.FirstColor); err != nil { + return nil, err + } + + var numColors uint16 + if err := binary.Read(r, binary.BigEndian, &numColors); err != nil { + return nil, err + } + + result.Colors = make([]Color, numColors) + for i := uint16(0); i < numColors; i++ { + + color := &result.Colors[i] + data := []interface{}{ + &color.R, + &color.G, + &color.B, + } + + for _, val := range data { + if err := binary.Read(r, binary.BigEndian, val); err != nil { + return nil, err + } + } + + // Update the connection's color map + c.ColorMap[result.FirstColor+i] = *color + } + + return &result, nil +} + +// Bell signals that an audible bell should be made on the client. +// +// See RFC 6143 Section 7.6.3 +type BellMessage byte + +func (*BellMessage) Type() uint8 { + return 2 +} + +func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error) { + return new(BellMessage), nil +} + +// ServerCutTextMessage indicates the server has new text in the cut buffer. +// +// See RFC 6143 Section 7.6.4 +type ServerCutTextMessage struct { + Text string +} + +func (*ServerCutTextMessage) Type() uint8 { + return 3 +} + +func (*ServerCutTextMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { + // Read off the padding + var padding [1]byte + if _, err := io.ReadFull(r, padding[:]); err != nil { + return nil, err + } + + var textLength uint32 + if err := binary.Read(r, binary.BigEndian, &textLength); err != nil { + return nil, err + } + + textBytes := make([]uint8, textLength) + if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil { + return nil, err + } + + return &ServerCutTextMessage{string(textBytes)}, nil +} diff --git a/vendor/github.com/mitchellh/iochan/LICENSE.md b/vendor/github.com/mitchellh/iochan/LICENSE.md new file mode 100644 index 000000000..762008c22 --- /dev/null +++ b/vendor/github.com/mitchellh/iochan/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/iochan/README.md b/vendor/github.com/mitchellh/iochan/README.md new file mode 100644 index 000000000..23771b1b9 --- /dev/null +++ b/vendor/github.com/mitchellh/iochan/README.md @@ -0,0 +1,13 @@ +# iochan + +iochan is a Go library for treating `io` readers and writers like channels. +This is useful when sometimes you wish to use `io.Reader` and such in `select` +statements. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/iochan +``` diff --git a/vendor/github.com/mitchellh/iochan/iochan.go b/vendor/github.com/mitchellh/iochan/iochan.go new file mode 100644 index 000000000..c10cef02d --- /dev/null +++ b/vendor/github.com/mitchellh/iochan/iochan.go @@ -0,0 +1,41 @@ +package iochan + +import ( + "bufio" + "io" +) + +// DelimReader takes an io.Reader and produces the contents of the reader +// on the returned channel. The contents on the channel will be returned +// on boundaries specified by the delim parameter, and will include this +// delimiter. +// +// If an error occurs while reading from the reader, the reading will end. +// +// In the case of an EOF or error, the channel will be closed. +// +// This must only be called once for any individual reader. The behavior is +// unknown and will be unexpected if this is called multiple times with the +// same reader. +func DelimReader(r io.Reader, delim byte) <-chan string { + ch := make(chan string) + + go func() { + buf := bufio.NewReader(r) + + for { + line, err := buf.ReadString(delim) + if line != "" { + ch <- line + } + + if err != nil { + break + } + } + + close(ch) + }() + + return ch +} diff --git a/vendor/github.com/mitchellh/mapstructure/.travis.yml b/vendor/github.com/mitchellh/mapstructure/.travis.yml new file mode 100644 index 000000000..7f3fe9a96 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.4 + +script: + - go test diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 000000000..659d6885f --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 000000000..aa91f76ce --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,151 @@ +package mapstructure + +import ( + "errors" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Type, to reflect.Type, + data interface{}) (interface{}, error) { + // Build our arguments that reflect expects + argVals := make([]reflect.Value, 3) + argVals[0] = reflect.ValueOf(from) + argVals[1] = reflect.ValueOf(to) + argVals[2] = reflect.ValueOf(data) + + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from, to, data) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), data) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + var err error + for _, f1 := range fs { + data, err = DecodeHookExec(f1, f, t, data) + if err != nil { + return nil, err + } + + // Modify the from kind to be correct with the new data + f = reflect.ValueOf(data).Type() + } + + return data, nil + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } else { + return "0", nil + } + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 000000000..47a99e5af --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,50 @@ +package mapstructure + +import ( + "errors" + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +// WrappedErrors implements the errwrap.Wrapper interface to make this +// return value more useful with the errwrap and go-multierror libraries. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + + result := make([]error, len(e.Errors)) + for i, e := range e.Errors { + result[i] = errors.New(e) + } + + return result +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 000000000..40be5116d --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,745 @@ +// The mapstructure package exposes functionality to convert an +// abitrary map[string]interface{} into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +package mapstructure + +import ( + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type should be DecodeHookFuncType or DecodeHookFuncKind. +// Either is accepted. Types are a superset of Kinds (Types can return +// Kinds) and are generally a richer thing to use, but Kinds are simpler +// if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. + // + // If an error is returned, the entire decode will fail with that + // error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // + WeaklyTypedInput bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string +} + +// Decode takes a map and uses reflection to convert it into the +// given Go native structure. val must be a pointer to a struct. +func Decode(m interface{}, rawVal interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: rawVal, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(m) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(raw interface{}) error { + return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { + if data == nil { + // If the data is nil, then we don't set anything. + return nil + } + + dataVal := reflect.ValueOf(data) + if !dataVal.IsValid() { + // If the data value is invalid, then we just set the value + // to be the zero value. + val.Set(reflect.Zero(val.Type())) + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the data. + var err error + data, err = DecodeHookExec( + d.config.DecodeHook, + dataVal.Type(), val.Type(), data) + if err != nil { + return err + } + } + + var err error + dataKind := getKind(val) + switch dataKind { + case reflect.Bool: + err = d.decodeBool(name, data, val) + case reflect.Interface: + err = d.decodeBasic(name, data, val) + case reflect.String: + err = d.decodeString(name, data, val) + case reflect.Int: + err = d.decodeInt(name, data, val) + case reflect.Uint: + err = d.decodeUint(name, data, val) + case reflect.Float32: + err = d.decodeFloat(name, data, val) + case reflect.Struct: + err = d.decodeStruct(name, data, val) + case reflect.Map: + err = d.decodeMap(name, data, val) + case reflect.Ptr: + err = d.decodePtr(name, data, val) + case reflect.Slice: + err = d.decodeSlice(name, data, val) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, dataKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metadata. + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch { + case elemKind == reflect.Uint8: + val.SetString(string(dataVal.Interface().([]uint8))) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(float64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + // Check input type + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if dataVal.Kind() != reflect.Map { + // Accept empty array/slice instead of an empty map in weakly typed mode + if d.config.WeaklyTypedInput && + (dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) && + dataVal.Len() == 0 { + val.Set(valMap) + return nil + } else { + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } + } + + // Accumulate errors + errors := make([]string, 0) + + for _, k := range dataVal.MapKeys() { + fieldName := fmt.Sprintf("%s[%s]", name, k) + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + realVal := reflect.New(valElemType) + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return err + } + + val.Set(realVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + // Accept empty map instead of array/slice in weakly typed mode + if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } else { + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + } + } + + // Make a new slice to hold our result, same size as the original data. + valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valSlice.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + if dataValKind != reflect.Map { + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) + } + + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + fields := make(map[*reflect.StructField]reflect.Value) + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + + if fieldType.Anonymous { + fieldKind := fieldType.Type.Kind() + if fieldKind != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind)) + continue + } + } + + // If "squash" is specified in the tag, we squash the field down. + squash := false + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + + if squash { + structs = append(structs, val.FieldByName(fieldType.Name)) + continue + } + + // Normal struct field, store it away + fields[&fieldType] = structVal.Field(i) + } + } + + for fieldType, field := range fields { + fieldName := fieldType.Name + + tagValue := fieldType.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey, _ := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if strings.EqualFold(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Just ignore. + continue + } + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + if !field.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !field.CanSet() { + continue + } + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = fmt.Sprintf("%s.%s", name, fieldName) + } + + if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { + errors = appendErrors(errors, err) + } + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey, _ := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey, _ := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = fmt.Sprintf("%s.%s", name, key) + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + } + + return nil +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} diff --git a/vendor/github.com/mitchellh/multistep/LICENSE.md b/vendor/github.com/mitchellh/multistep/LICENSE.md new file mode 100644 index 000000000..c9d6b768c --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/LICENSE.md @@ -0,0 +1,22 @@ +Copyright (c) 2013 Mitchell Hashimoto + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/multistep/README.md b/vendor/github.com/mitchellh/multistep/README.md new file mode 100644 index 000000000..9ceae012a --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/README.md @@ -0,0 +1,59 @@ +# multistep + +multistep is a Go library for building up complex actions using discrete, +individual "steps." These steps are strung together and run in sequence +to achieve a more complex goal. The runner handles cleanup, cancelling, etc. +if necessary. + +## Basic Example + +Make a step to perform some action. The step can access your "state", +which is passed between steps by the runner. + +```go +type stepAdd struct{} + +func (s *stepAdd) Run(state multistep.StateBag) multistep.StepAction { + // Read our value and assert that it is they type we want + value := state.Get("value").(int) + fmt.Printf("Value is %d\n", value) + + // Store some state back + state.Put("value", value + 1) + return multistep.ActionContinue +} + +func (s *stepAdd) Cleanup(multistep.StateBag) { + // This is called after all the steps have run or if the runner is + // cancelled so that cleanup can be performed. +} +``` + +Make a runner and call your array of Steps. + +```go +func main() { + // Our "bag of state" that we read the value from + state := new(multistep.BasicStateBag) + state.Put("value", 0) + + steps := []multistep.Step{ + &stepAdd{}, + &stepAdd{}, + &stepAdd{}, + } + + runner := &multistep.BasicRunner{Steps: steps} + + // Executes the steps + runner.Run(state) +} +``` + +This will produce: + +``` +Value is 0 +Value is 1 +Value is 2 +``` diff --git a/vendor/github.com/mitchellh/multistep/basic_runner.go b/vendor/github.com/mitchellh/multistep/basic_runner.go new file mode 100644 index 000000000..35692a743 --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/basic_runner.go @@ -0,0 +1,102 @@ +package multistep + +import ( + "sync" + "sync/atomic" +) + +type runState int32 + +const ( + stateIdle runState = iota + stateRunning + stateCancelling +) + +// BasicRunner is a Runner that just runs the given slice of steps. +type BasicRunner struct { + // Steps is a slice of steps to run. Once set, this should _not_ be + // modified. + Steps []Step + + cancelCh chan struct{} + doneCh chan struct{} + state runState + l sync.Mutex +} + +func (b *BasicRunner) Run(state StateBag) { + b.l.Lock() + if b.state != stateIdle { + panic("already running") + } + + cancelCh := make(chan struct{}) + doneCh := make(chan struct{}) + b.cancelCh = cancelCh + b.doneCh = doneCh + b.state = stateRunning + b.l.Unlock() + + defer func() { + b.l.Lock() + b.cancelCh = nil + b.doneCh = nil + b.state = stateIdle + close(doneCh) + b.l.Unlock() + }() + + // This goroutine listens for cancels and puts the StateCancelled key + // as quickly as possible into the state bag to mark it. + go func() { + select { + case <-cancelCh: + // Flag cancel and wait for finish + state.Put(StateCancelled, true) + <-doneCh + case <-doneCh: + } + }() + + for _, step := range b.Steps { + // We also check for cancellation here since we can't be sure + // the goroutine that is running to set it actually ran. + if runState(atomic.LoadInt32((*int32)(&b.state))) == stateCancelling { + state.Put(StateCancelled, true) + break + } + + action := step.Run(state) + defer step.Cleanup(state) + + if _, ok := state.GetOk(StateCancelled); ok { + break + } + + if action == ActionHalt { + state.Put(StateHalted, true) + break + } + } +} + +func (b *BasicRunner) Cancel() { + b.l.Lock() + switch b.state { + case stateIdle: + // Not running, so Cancel is... done. + b.l.Unlock() + return + case stateRunning: + // Running, so mark that we cancelled and set the state + close(b.cancelCh) + b.state = stateCancelling + fallthrough + case stateCancelling: + // Already cancelling, so just wait until we're done + ch := b.doneCh + b.l.Unlock() + <-ch + } +} diff --git a/vendor/github.com/mitchellh/multistep/debug_runner.go b/vendor/github.com/mitchellh/multistep/debug_runner.go new file mode 100644 index 000000000..42f68f242 --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/debug_runner.go @@ -0,0 +1,110 @@ +package multistep + +import ( + "fmt" + "reflect" + "sync" +) + +// DebugLocation is the location where the pause is occuring when debugging +// a step sequence. "DebugLocationAfterRun" is after the run of the named +// step. "DebugLocationBeforeCleanup" is before the cleanup of the named +// step. +type DebugLocation uint + +const ( + DebugLocationAfterRun DebugLocation = iota + DebugLocationBeforeCleanup +) + +// DebugPauseFn is the type signature for the function that is called +// whenever the DebugRunner pauses. It allows the caller time to +// inspect the state of the multi-step sequence at a given step. +type DebugPauseFn func(DebugLocation, string, StateBag) + +// DebugRunner is a Runner that runs the given set of steps in order, +// but pauses between each step until it is told to continue. +type DebugRunner struct { + // Steps is the steps to run. These will be run in order. + Steps []Step + + // PauseFn is the function that is called whenever the debug runner + // pauses. The debug runner continues when this function returns. + // The function is given the state so that the state can be inspected. + PauseFn DebugPauseFn + + l sync.Mutex + runner *BasicRunner +} + +func (r *DebugRunner) Run(state StateBag) { + r.l.Lock() + if r.runner != nil { + panic("already running") + } + r.runner = new(BasicRunner) + r.l.Unlock() + + pauseFn := r.PauseFn + + // If no PauseFn is specified, use the default + if pauseFn == nil { + pauseFn = DebugPauseDefault + } + + // Rebuild the steps so that we insert the pause step after each + steps := make([]Step, len(r.Steps)*2) + for i, step := range r.Steps { + steps[i*2] = step + steps[(i*2)+1] = &debugStepPause{ + reflect.Indirect(reflect.ValueOf(step)).Type().Name(), + pauseFn, + } + } + + // Then just use a basic runner to run it + r.runner.Steps = steps + r.runner.Run(state) +} + +func (r *DebugRunner) Cancel() { + r.l.Lock() + defer r.l.Unlock() + + if r.runner != nil { + r.runner.Cancel() + } +} + +// DebugPauseDefault is the default pause function when using the +// DebugRunner if no PauseFn is specified. It outputs some information +// to stderr about the step and waits for keyboard input on stdin before +// continuing. +func DebugPauseDefault(loc DebugLocation, name string, state StateBag) { + var locationString string + switch loc { + case DebugLocationAfterRun: + locationString = "after run of" + case DebugLocationBeforeCleanup: + locationString = "before cleanup of" + } + + fmt.Printf("Pausing %s step '%s'. Press any key to continue.\n", locationString, name) + + var line string + fmt.Scanln(&line) +} + +type debugStepPause struct { + StepName string + PauseFn DebugPauseFn +} + +func (s *debugStepPause) Run(state StateBag) StepAction { + s.PauseFn(DebugLocationAfterRun, s.StepName, state) + return ActionContinue +} + +func (s *debugStepPause) Cleanup(state StateBag) { + s.PauseFn(DebugLocationBeforeCleanup, s.StepName, state) +} diff --git a/vendor/github.com/mitchellh/multistep/multistep.go b/vendor/github.com/mitchellh/multistep/multistep.go new file mode 100644 index 000000000..feef1406f --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/multistep.go @@ -0,0 +1,48 @@ +// multistep is a library for bulding up complex actions using individual, +// discrete steps. +package multistep + +// A StepAction determines the next step to take regarding multi-step actions. +type StepAction uint + +const ( + ActionContinue StepAction = iota + ActionHalt +) + +// This is the key set in the state bag when using the basic runner to +// signal that the step sequence was cancelled. +const StateCancelled = "cancelled" + +// This is the key set in the state bag when a step halted the sequence. +const StateHalted = "halted" + +// Step is a single step that is part of a potentially large sequence +// of other steps, responsible for performing some specific action. +type Step interface { + // Run is called to perform the action. The parameter is a "state bag" + // of untyped things. Please be very careful about type-checking the + // items in this bag. + // + // The return value determines whether multi-step sequences continue + // or should halt. + Run(StateBag) StepAction + + // Cleanup is called in reverse order of the steps that have run + // and allow steps to clean up after themselves. Do not assume if this + // ran that the entire multi-step sequence completed successfully. This + // method can be ran in the face of errors and cancellations as well. + // + // The parameter is the same "state bag" as Run, and represents the + // state at the latest possible time prior to calling Cleanup. + Cleanup(StateBag) +} + +// Runner is a thing that runs one or more steps. +type Runner interface { + // Run runs the steps with the given initial state. + Run(StateBag) + + // Cancel cancels a potentially running stack of steps. + Cancel() +} diff --git a/vendor/github.com/mitchellh/multistep/statebag.go b/vendor/github.com/mitchellh/multistep/statebag.go new file mode 100644 index 000000000..dab712316 --- /dev/null +++ b/vendor/github.com/mitchellh/multistep/statebag.go @@ -0,0 +1,47 @@ +package multistep + +import ( + "sync" +) + +// StateBag holds the state that is used by the Runner and Steps. The +// StateBag implementation must be safe for concurrent access. +type StateBag interface { + Get(string) interface{} + GetOk(string) (interface{}, bool) + Put(string, interface{}) +} + +// BasicStateBag implements StateBag by using a normal map underneath +// protected by a RWMutex. +type BasicStateBag struct { + data map[string]interface{} + l sync.RWMutex + once sync.Once +} + +func (b *BasicStateBag) Get(k string) interface{} { + result, _ := b.GetOk(k) + return result +} + +func (b *BasicStateBag) GetOk(k string) (interface{}, bool) { + b.l.RLock() + defer b.l.RUnlock() + + result, ok := b.data[k] + return result, ok +} + +func (b *BasicStateBag) Put(k string, v interface{}) { + b.l.Lock() + defer b.l.Unlock() + + // Make sure the map is initialized one time, on write + b.once.Do(func() { + b.data = make(map[string]interface{}) + }) + + // Write the data + b.data[k] = v +} diff --git a/vendor/github.com/mitchellh/panicwrap/LICENSE b/vendor/github.com/mitchellh/panicwrap/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/panicwrap/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/panicwrap/README.md b/vendor/github.com/mitchellh/panicwrap/README.md new file mode 100644 index 000000000..b48feae87 --- /dev/null +++ b/vendor/github.com/mitchellh/panicwrap/README.md @@ -0,0 +1,108 @@ +# panicwrap + +panicwrap is a Go library that re-executes a Go binary and monitors stderr +output from the binary for a panic. When it finds a panic, it executes a +user-defined handler function. Stdout, stderr, stdin, signals, and exit +codes continue to work as normal, making the existence of panicwrap mostly +invisible to the end user until a panic actually occurs. + +Since a panic is truly a bug in the program meant to crash the runtime, +globally catching panics within Go applications is not supposed to be possible. +Despite this, it is often useful to have a way to know when panics occur. +panicwrap allows you to do something with these panics, such as writing them +to a file, so that you can track when panics occur. + +panicwrap is ***not a panic recovery system***. Panics indicate serious +problems with your application and _should_ crash the runtime. panicwrap +is just meant as a way to monitor for panics. If you still think this is +the worst idea ever, read the section below on why. + +## Features + +* **SIMPLE!** +* Works with all Go applications on all platforms Go supports +* Custom behavior when a panic occurs +* Stdout, stderr, stdin, exit codes, and signals continue to work as + expected. + +## Usage + +Using panicwrap is simple. It behaves a lot like `fork`, if you know +how that works. A basic example is shown below. + +Because it would be sad to panic while capturing a panic, it is recommended +that the handler functions for panicwrap remain relatively simple and well +tested. panicwrap itself contains many tests. + +```go +package main + +import ( + "fmt" + "github.com/mitchellh/panicwrap" + "os" +) + +func main() { + exitStatus, err := panicwrap.BasicWrap(panicHandler) + if err != nil { + // Something went wrong setting up the panic wrapper. Unlikely, + // but possible. + panic(err) + } + + // If exitStatus >= 0, then we're the parent process and the panicwrap + // re-executed ourselves and completed. Just exit with the proper status. + if exitStatus >= 0 { + os.Exit(exitStatus) + } + + // Otherwise, exitStatus < 0 means we're the child. Continue executing as + // normal... + + // Let's say we panic + panic("oh shucks") +} + +func panicHandler(output string) { + // output contains the full output (including stack traces) of the + // panic. Put it in a file or something. + fmt.Printf("The child panicked:\n\n%s\n", output) + os.Exit(1) +} +``` + +## How Does it Work? + +panicwrap works by re-executing the running program (retaining arguments, +environmental variables, etc.) and monitoring the stderr of the program. +Since Go always outputs panics in a predictable way with a predictable +exit code, panicwrap is able to reliably detect panics and allow the parent +process to handle them. + +## WHY?! Panics should CRASH! + +Yes, panics _should_ crash. They are 100% always indicative of bugs and having +information on a production server or application as to what caused the panic is critical. + +### User Facing + +In user-facing programs (programs like +[Packer](http://github.com/mitchellh/packer) or +[Docker](http://github.com/dotcloud/docker)), it is up to the user to +report such panics. This is unreliable, at best, and it would be better if the +program could have a way to automatically report panics. panicwrap provides +a way to do this. + +### Server + +For backend applications, it is easier to detect crashes (since the application exits) +and having an idea as to why the crash occurs is equally important; +particularly on a production server. + +At [HashiCorp](http://www.hashicorp.com), +we use panicwrap to log panics to timestamped files with some additional +data (configuration settings at the time, environmental variables, etc.) + +The goal of panicwrap is _not_ to hide panics. It is instead to provide +a clean mechanism for capturing them and ultimately crashing. diff --git a/vendor/github.com/mitchellh/panicwrap/panicwrap.go b/vendor/github.com/mitchellh/panicwrap/panicwrap.go new file mode 100644 index 000000000..11eafe712 --- /dev/null +++ b/vendor/github.com/mitchellh/panicwrap/panicwrap.go @@ -0,0 +1,309 @@ +// The panicwrap package provides functions for capturing and handling +// panics in your application. It does this by re-executing the running +// application and monitoring stderr for any panics. At the same time, +// stdout/stderr/etc. are set to the same values so that data is shuttled +// through properly, making the existence of panicwrap mostly transparent. +// +// Panics are only detected when the subprocess exits with a non-zero +// exit status, since this is the only time panics are real. Otherwise, +// "panic-like" output is ignored. +package panicwrap + +import ( + "bytes" + "errors" + "github.com/kardianos/osext" + "io" + "os" + "os/exec" + "os/signal" + "syscall" + "time" +) + +const ( + DEFAULT_COOKIE_KEY = "cccf35992f8f3cd8d1d28f0109dd953e26664531" + DEFAULT_COOKIE_VAL = "7c28215aca87789f95b406b8dd91aa5198406750" +) + +// HandlerFunc is the type called when a panic is detected. +type HandlerFunc func(string) + +// WrapConfig is the configuration for panicwrap when wrapping an existing +// binary. To get started, in general, you only need the BasicWrap function +// that will set this up for you. However, for more customizability, +// WrapConfig and Wrap can be used. +type WrapConfig struct { + // Handler is the function called when a panic occurs. + Handler HandlerFunc + + // The cookie key and value are used within environmental variables + // to tell the child process that it is already executing so that + // wrap doesn't re-wrap itself. + CookieKey string + CookieValue string + + // If true, the panic will not be mirrored to the configured writer + // and will instead ONLY go to the handler. This lets you effectively + // hide panics from the end user. This is not recommended because if + // your handler fails, the panic is effectively lost. + HidePanic bool + + // The amount of time that a process must exit within after detecting + // a panic header for panicwrap to assume it is a panic. Defaults to + // 300 milliseconds. + DetectDuration time.Duration + + // The writer to send the stderr to. If this is nil, then it defaults + // to os.Stderr. + Writer io.Writer + + // The writer to send stdout to. If this is nil, then it defaults to + // os.Stdout. + Stdout io.Writer +} + +// BasicWrap calls Wrap with the given handler function, using defaults +// for everything else. See Wrap and WrapConfig for more information on +// functionality and return values. +func BasicWrap(f HandlerFunc) (int, error) { + return Wrap(&WrapConfig{ + Handler: f, + }) +} + +// Wrap wraps the current executable in a handler to catch panics. It +// returns an error if there was an error during the wrapping process. +// If the error is nil, then the int result indicates the exit status of the +// child process. If the exit status is -1, then this is the child process, +// and execution should continue as normal. Otherwise, this is the parent +// process and the child successfully ran already, and you should exit the +// process with the returned exit status. +// +// This function should be called very very early in your program's execution. +// Ideally, this runs as the first line of code of main. +// +// Once this is called, the given WrapConfig shouldn't be modified or used +// any further. +func Wrap(c *WrapConfig) (int, error) { + if c.Handler == nil { + return -1, errors.New("Handler must be set") + } + + if c.DetectDuration == 0 { + c.DetectDuration = 300 * time.Millisecond + } + + if c.Writer == nil { + c.Writer = os.Stderr + } + + // If we're already wrapped, exit out. + if Wrapped(c) { + return -1, nil + } + + // Get the path to our current executable + exePath, err := osext.Executable() + if err != nil { + return -1, err + } + + // Pipe the stderr so we can read all the data as we look for panics + stderr_r, stderr_w := io.Pipe() + + // doneCh is closed when we're done, signaling any other goroutines + // to end immediately. + doneCh := make(chan struct{}) + + // panicCh is the channel on which the panic text will actually be + // sent. + panicCh := make(chan string) + + // On close, make sure to finish off the copying of data to stderr + defer func() { + defer close(doneCh) + stderr_w.Close() + <-panicCh + }() + + // Start the goroutine that will watch stderr for any panics + go trackPanic(stderr_r, c.Writer, c.DetectDuration, panicCh) + + // Create the writer for stdout that we're going to use + var stdout_w io.Writer = os.Stdout + if c.Stdout != nil { + stdout_w = c.Stdout + } + + // Build a subcommand to re-execute ourselves. We make sure to + // set the environmental variable to include our cookie. We also + // set stdin/stdout to match the config. Finally, we pipe stderr + // through ourselves in order to watch for panics. + cmd := exec.Command(exePath, os.Args[1:]...) + cmd.Env = append(os.Environ(), c.CookieKey+"="+c.CookieValue) + cmd.Stdin = os.Stdin + cmd.Stdout = stdout_w + cmd.Stderr = stderr_w + if err := cmd.Start(); err != nil { + return 1, err + } + + // Listen to signals and capture them forever. We allow the child + // process to handle them in some way. + sigCh := make(chan os.Signal) + signal.Notify(sigCh, os.Interrupt) + go func() { + defer signal.Stop(sigCh) + for { + select { + case <-doneCh: + return + case <-sigCh: + } + } + }() + + if err := cmd.Wait(); err != nil { + exitErr, ok := err.(*exec.ExitError) + if !ok { + // This is some other kind of subprocessing error. + return 1, err + } + + exitStatus := 1 + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { + exitStatus = status.ExitStatus() + } + + // Close the writer end so that the tracker goroutine ends at some point + stderr_w.Close() + + // Wait on the panic data + panicTxt := <-panicCh + if panicTxt != "" { + if !c.HidePanic { + c.Writer.Write([]byte(panicTxt)) + } + + c.Handler(panicTxt) + } + + return exitStatus, nil + } + + return 0, nil +} + +// Wrapped checks if we're already wrapped according to the configuration +// given. +// +// Wrapped is very cheap and can be used early to short-circuit some pre-wrap +// logic your application may have. +func Wrapped(c *WrapConfig) bool { + if c.CookieKey == "" { + c.CookieKey = DEFAULT_COOKIE_KEY + } + + if c.CookieValue == "" { + c.CookieValue = DEFAULT_COOKIE_VAL + } + + // If the cookie key/value match our environment, then we are the + // child, so just exit now and tell the caller that we're the child + return os.Getenv(c.CookieKey) == c.CookieValue +} + +// trackPanic monitors the given reader for a panic. If a panic is detected, +// it is outputted on the result channel. This will close the channel once +// it is complete. +func trackPanic(r io.Reader, w io.Writer, dur time.Duration, result chan<- string) { + defer close(result) + + var panicTimer <-chan time.Time + panicBuf := new(bytes.Buffer) + panicHeaders := [][]byte{ + []byte("panic:"), + []byte("fatal error: fault"), + } + panicType := -1 + + tempBuf := make([]byte, 2048) + for { + var buf []byte + var n int + + if panicTimer == nil && panicBuf.Len() > 0 { + // We're not tracking a panic but the buffer length is + // greater than 0. We need to clear out that buffer, but + // look for another panic along the way. + + // First, remove the previous panic header so we don't loop + w.Write(panicBuf.Next(len(panicHeaders[panicType]))) + + // Next, assume that this is our new buffer to inspect + n = panicBuf.Len() + buf = make([]byte, n) + copy(buf, panicBuf.Bytes()) + panicBuf.Reset() + } else { + var err error + buf = tempBuf + n, err = r.Read(buf) + if n <= 0 && err == io.EOF { + if panicBuf.Len() > 0 { + // We were tracking a panic, assume it was a panic + // and return that as the result. + result <- panicBuf.String() + } + + return + } + } + + if panicTimer != nil { + // We're tracking what we think is a panic right now. + // If the timer ended, then it is not a panic. + isPanic := true + select { + case <-panicTimer: + isPanic = false + default: + } + + // No matter what, buffer the text some more. + panicBuf.Write(buf[0:n]) + + if !isPanic { + // It isn't a panic, stop tracking. Clean-up will happen + // on the next iteration. + panicTimer = nil + } + + continue + } + + panicType = -1 + flushIdx := n + for i, header := range panicHeaders { + idx := bytes.Index(buf[0:n], header) + if idx >= 0 { + panicType = i + flushIdx = idx + break + } + } + + // Flush to stderr what isn't a panic + w.Write(buf[0:flushIdx]) + + if panicType == -1 { + // Not a panic so just continue along + continue + } + + // We have a panic header. Write we assume is a panic os far. + panicBuf.Write(buf[flushIdx:n]) + panicTimer = time.After(dur) + } +} diff --git a/vendor/github.com/mitchellh/prefixedio/LICENSE b/vendor/github.com/mitchellh/prefixedio/LICENSE new file mode 100644 index 000000000..35827a58c --- /dev/null +++ b/vendor/github.com/mitchellh/prefixedio/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/prefixedio/README.md b/vendor/github.com/mitchellh/prefixedio/README.md new file mode 100644 index 000000000..1c8636020 --- /dev/null +++ b/vendor/github.com/mitchellh/prefixedio/README.md @@ -0,0 +1,30 @@ +# prefixedio + +`prefixedio` (Golang package: `prefixedio`) is a package for Go +that takes an `io.Reader` and de-multiplexes line-oriented data based +on a line prefix to a set of readers. + +## Installation and Usage + +Install using `go get github.com/mitchellh/prefixedio`. + +Full documentation is available at +http://godoc.org/github.com/mitchellh/prefixedio + +Below is an example of its usage ignoring errors: + +```go +// Assume r is some set io.Reader. Perhaps a file, network, anything. +var r io.Reader + +// Initialize the prefixed reader +pr, _ := prefixedio.NewReader(r) + +// Grab readers for a couple prefixes +errR, _ := pr.Prefix("err: ") +outR, _ := pr.Prefix("out: ") + +// Copy the data to different places based on the prefix +go io.Copy(os.Stderr, errR) +go io.Copy(os.Stdout, outR) +``` diff --git a/vendor/github.com/mitchellh/prefixedio/reader.go b/vendor/github.com/mitchellh/prefixedio/reader.go new file mode 100644 index 000000000..82266a9cf --- /dev/null +++ b/vendor/github.com/mitchellh/prefixedio/reader.go @@ -0,0 +1,220 @@ +package prefixedio + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "sync" + "time" +) + +// Reader reads from another io.Reader and de-multiplexes line-oriented +// data into different io.Reader streams. +// +// Lines are delimited with the '\n' character. +// +// When `Read` is called, any data that doesn't currently have a prefix +// registered will be discarded. Data won't start being discarded until +// the first Read is called on a prefix. Once the first Read is called, +// data is read until EOF. Therefore, be sure to request all prefix +// readers before issuing any Read calls on any prefixes. +// +// Reads will block if all the readers aren't routinely draining their +// buffers. Therefore, be sure to be actively reading from all registered +// prefixes, otherwise you can encounter deadlock scenarios. +type Reader struct { + FlushTimeout time.Duration + + done bool + prefixes map[string]*io.PipeWriter + r io.Reader + + l sync.Mutex + once sync.Once +} + +// NewReader creates a new Reader with the given io.Reader. +func NewReader(r io.Reader) (*Reader, error) { + if r == nil { + return nil, errors.New("Reader must not be nil") + } + + return &Reader{r: r}, nil +} + +// Prefix returns a new io.Reader that will read data that +// is prefixed with the given prefix. +// +// The read data is line-oriented so calling Read will result +// in a full line of output (including the line separator), +// but is exposed as an io.Reader for useful utility interoperating +// with other Go libraries. +// +// The data read has the prefix stripped, but contains the line +// delimiter. +// +// An empty prefix "" will read the data before any other prefix match is +// found, allowing you to have a default reader before a prefix is matched. +func (r *Reader) Prefix(p string) (io.Reader, error) { + r.l.Lock() + defer r.l.Unlock() + + if r.prefixes == nil { + r.prefixes = make(map[string]*io.PipeWriter) + } + + if _, ok := r.prefixes[p]; ok { + return nil, fmt.Errorf("Prefix already registered: %s", p) + } + + pr, pw := io.Pipe() + r.prefixes[p] = pw + + if r.done { + pw.Close() + } + + return &prefixReader{ + r: r, + pr: pr, + }, nil +} + +// init starts the goroutine that reads from the underlying reader +// and sends data to the proper place. +// +// This is safe to call multiple times. +func (r *Reader) init() { + r.once.Do(func() { + go r.read() + }) +} + +// read runs in a goroutine and performs a read on the reader, +// dispatching lines to prefixes where necessary. +func (r *Reader) read() { + var err error + var lastPrefix string + buf := bufio.NewReader(r.r) + + // Listen for bytes in a goroutine. We do this so that if we're blocking + // we can flush the bytes we have after some configured time. There is + // probably a way to make this a lot faster but this works for now. + byteCh := make(chan byte) + doneCh := make(chan error) + go func() { + defer close(doneCh) + for { + b, err := buf.ReadByte() + if err != nil { + doneCh <- err + return + } + + byteCh <- b + } + }() + + // Figure out the timeout we wait until we flush if we see no data + ft := r.FlushTimeout + if ft == 0 { + ft = 100 * time.Millisecond + } + + lineBuf := make([]byte, 0, 80) + for { + line := lineBuf[0:0] + for { + brk := false + + select { + case b := <-byteCh: + line = append(line, b) + brk = b == '\n' + case err = <-doneCh: + brk = true + case <-time.After(ft): + brk = true + } + + if brk { + break + } + } + + // If an error occurred and its not an EOF, then report that + // error to all pipes and exit. + if err != nil && err != io.EOF { + break + } + + // Go through each prefix and write if the line matches. + // If no lines match, the data is lost. + var prefix string + r.l.Lock() + for p, _ := range r.prefixes { + if p == "" { + continue + } + + if bytes.HasPrefix(line, []byte(p)) { + prefix = p + line = line[len(p):] + break + } + } + + if prefix == "" { + prefix = lastPrefix + } + + pw, ok := r.prefixes[prefix] + if ok { + lastPrefix = prefix + + // Make sure we write all the data before we exit. + n := 0 + for n < len(line) { + ni, err := pw.Write(line[n:]) + if err != nil { + break + } + + n += ni + } + } + r.l.Unlock() + + if err == io.EOF { + break + } + } + + r.l.Lock() + defer r.l.Unlock() + + // Mark us done so that we don't create anymore readers + r.done = true + + // All previous writers should be closed so that the readers + // properly return an EOF (or another error if we had one) + for _, pw := range r.prefixes { + if err != nil && err != io.EOF { + pw.CloseWithError(err) + } else { + pw.Close() + } + } +} + +type prefixReader struct { + r *Reader + pr io.Reader +} + +func (r *prefixReader) Read(p []byte) (int, error) { + r.r.init() + return r.pr.Read(p) +} diff --git a/vendor/github.com/mitchellh/reflectwalk/LICENSE b/vendor/github.com/mitchellh/reflectwalk/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/reflectwalk/README.md b/vendor/github.com/mitchellh/reflectwalk/README.md new file mode 100644 index 000000000..ac82cd2e1 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/README.md @@ -0,0 +1,6 @@ +# reflectwalk + +reflectwalk is a Go library for "walking" a value in Go using reflection, +in the same way a directory tree can be "walked" on the filesystem. Walking +a complex structure can allow you to do manipulations on unknown structures +such as those decoded from JSON. diff --git a/vendor/github.com/mitchellh/reflectwalk/location.go b/vendor/github.com/mitchellh/reflectwalk/location.go new file mode 100644 index 000000000..7c59d764c --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location.go @@ -0,0 +1,17 @@ +package reflectwalk + +//go:generate stringer -type=Location location.go + +type Location uint + +const ( + None Location = iota + Map + MapKey + MapValue + Slice + SliceElem + Struct + StructField + WalkLoc +) diff --git a/vendor/github.com/mitchellh/reflectwalk/location_string.go b/vendor/github.com/mitchellh/reflectwalk/location_string.go new file mode 100644 index 000000000..d3cfe8545 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type=Location location.go; DO NOT EDIT + +package reflectwalk + +import "fmt" + +const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemStructStructFieldWalkLoc" + +var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 41, 52, 59} + +func (i Location) String() string { + if i+1 >= Location(len(_Location_index)) { + return fmt.Sprintf("Location(%d)", i) + } + return _Location_name[_Location_index[i]:_Location_index[i+1]] +} diff --git a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go new file mode 100644 index 000000000..1f2066598 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go @@ -0,0 +1,279 @@ +// reflectwalk is a package that allows you to "walk" complex structures +// similar to how you may "walk" a filesystem: visiting every element one +// by one and calling callback functions allowing you to handle and manipulate +// those elements. +package reflectwalk + +import ( + "reflect" +) + +// PrimitiveWalker implementations are able to handle primitive values +// within complex structures. Primitive values are numbers, strings, +// booleans, funcs, chans. +// +// These primitive values are often members of more complex +// structures (slices, maps, etc.) that are walkable by other interfaces. +type PrimitiveWalker interface { + Primitive(reflect.Value) error +} + +// MapWalker implementations are able to handle individual elements +// found within a map structure. +type MapWalker interface { + Map(m reflect.Value) error + MapElem(m, k, v reflect.Value) error +} + +// SliceWalker implementations are able to handle slice elements found +// within complex structures. +type SliceWalker interface { + Slice(reflect.Value) error + SliceElem(int, reflect.Value) error +} + +// StructWalker is an interface that has methods that are called for +// structs when a Walk is done. +type StructWalker interface { + Struct(reflect.Value) error + StructField(reflect.StructField, reflect.Value) error +} + +// EnterExitWalker implementations are notified before and after +// they walk deeper into complex structures (into struct fields, +// into slice elements, etc.) +type EnterExitWalker interface { + Enter(Location) error + Exit(Location) error +} + +// PointerWalker implementations are notified when the value they're +// walking is a pointer or not. Pointer is called for _every_ value whether +// it is a pointer or not. +type PointerWalker interface { + PointerEnter(bool) error + PointerExit(bool) error +} + +// Walk takes an arbitrary value and an interface and traverses the +// value, calling callbacks on the interface if they are supported. +// The interface should implement one or more of the walker interfaces +// in this package, such as PrimitiveWalker, StructWalker, etc. +func Walk(data, walker interface{}) (err error) { + v := reflect.ValueOf(data) + ew, ok := walker.(EnterExitWalker) + if ok { + err = ew.Enter(WalkLoc) + } + + if err == nil { + err = walk(v, walker) + } + + if ok && err == nil { + err = ew.Exit(WalkLoc) + } + + return +} + +func walk(v reflect.Value, w interface{}) (err error) { + // Determine if we're receiving a pointer and if so notify the walker. + pointer := false + if v.Kind() == reflect.Ptr { + pointer = true + v = reflect.Indirect(v) + } + if pw, ok := w.(PointerWalker); ok { + if err = pw.PointerEnter(pointer); err != nil { + return + } + + defer func() { + if err != nil { + return + } + + err = pw.PointerExit(pointer) + }() + } + + // We preserve the original value here because if it is an interface + // type, we want to pass that directly into the walkPrimitive, so that + // we can set it. + originalV := v + if v.Kind() == reflect.Interface { + v = v.Elem() + } + + k := v.Kind() + if k >= reflect.Int && k <= reflect.Complex128 { + k = reflect.Int + } + + switch k { + // Primitives + case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid: + err = walkPrimitive(originalV, w) + return + case reflect.Map: + err = walkMap(v, w) + return + case reflect.Slice: + err = walkSlice(v, w) + return + case reflect.Struct: + err = walkStruct(v, w) + return + default: + panic("unsupported type: " + k.String()) + } +} + +func walkMap(v reflect.Value, w interface{}) error { + ew, ewok := w.(EnterExitWalker) + if ewok { + ew.Enter(Map) + } + + if mw, ok := w.(MapWalker); ok { + if err := mw.Map(v); err != nil { + return err + } + } + + for _, k := range v.MapKeys() { + kv := v.MapIndex(k) + + if mw, ok := w.(MapWalker); ok { + if err := mw.MapElem(v, k, kv); err != nil { + return err + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(MapKey) + } + + if err := walk(k, w); err != nil { + return err + } + + if ok { + ew.Exit(MapKey) + ew.Enter(MapValue) + } + + if err := walk(kv, w); err != nil { + return err + } + + if ok { + ew.Exit(MapValue) + } + } + + if ewok { + ew.Exit(Map) + } + + return nil +} + +func walkPrimitive(v reflect.Value, w interface{}) error { + if pw, ok := w.(PrimitiveWalker); ok { + return pw.Primitive(v) + } + + return nil +} + +func walkSlice(v reflect.Value, w interface{}) (err error) { + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(Slice) + } + + if sw, ok := w.(SliceWalker); ok { + if err := sw.Slice(v); err != nil { + return err + } + } + + for i := 0; i < v.Len(); i++ { + elem := v.Index(i) + + if sw, ok := w.(SliceWalker); ok { + if err := sw.SliceElem(i, elem); err != nil { + return err + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(SliceElem) + } + + if err := walk(elem, w); err != nil { + return err + } + + if ok { + ew.Exit(SliceElem) + } + } + + ew, ok = w.(EnterExitWalker) + if ok { + ew.Exit(Slice) + } + + return nil +} + +func walkStruct(v reflect.Value, w interface{}) (err error) { + ew, ewok := w.(EnterExitWalker) + if ewok { + ew.Enter(Struct) + } + + if sw, ok := w.(StructWalker); ok { + if err = sw.Struct(v); err != nil { + return + } + } + + vt := v.Type() + for i := 0; i < vt.NumField(); i++ { + sf := vt.Field(i) + f := v.FieldByIndex([]int{i}) + + if sw, ok := w.(StructWalker); ok { + err = sw.StructField(sf, f) + if err != nil { + return + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(StructField) + } + + err = walk(f, w) + if err != nil { + return + } + + if ok { + ew.Exit(StructField) + } + } + + if ewok { + ew.Exit(Struct) + } + + return nil +} diff --git a/vendor/github.com/nu7hatch/gouuid/.gitignore b/vendor/github.com/nu7hatch/gouuid/.gitignore new file mode 100644 index 000000000..f9d9cd8ab --- /dev/null +++ b/vendor/github.com/nu7hatch/gouuid/.gitignore @@ -0,0 +1,11 @@ +_obj +_test +*.6 +*.out +_testmain.go +\#* +.\#* +*.log +_cgo* +*.o +*.a diff --git a/vendor/github.com/nu7hatch/gouuid/COPYING b/vendor/github.com/nu7hatch/gouuid/COPYING new file mode 100644 index 000000000..d7849fd8f --- /dev/null +++ b/vendor/github.com/nu7hatch/gouuid/COPYING @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Krzysztof Kowalik + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/nu7hatch/gouuid/README.md b/vendor/github.com/nu7hatch/gouuid/README.md new file mode 100644 index 000000000..e3d025d5e --- /dev/null +++ b/vendor/github.com/nu7hatch/gouuid/README.md @@ -0,0 +1,21 @@ +# Pure Go UUID implementation + +This package provides immutable UUID structs and the functions +NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 +and 5 UUIDs as specified in [RFC 4122](http://www.ietf.org/rfc/rfc4122.txt). + +## Installation + +Use the `go` tool: + + $ go get github.com/nu7hatch/gouuid + +## Usage + +See [documentation and examples](http://godoc.org/github.com/nu7hatch/gouuid) +for more information. + +## Copyright + +Copyright (C) 2011 by Krzysztof Kowalik . See [COPYING](https://github.com/nu7hatch/gouuid/tree/master/COPYING) +file for details. diff --git a/vendor/github.com/nu7hatch/gouuid/uuid.go b/vendor/github.com/nu7hatch/gouuid/uuid.go new file mode 100644 index 000000000..ac9623b72 --- /dev/null +++ b/vendor/github.com/nu7hatch/gouuid/uuid.go @@ -0,0 +1,173 @@ +// This package provides immutable UUID structs and the functions +// NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 +// and 5 UUIDs as specified in RFC 4122. +// +// Copyright (C) 2011 by Krzysztof Kowalik +package uuid + +import ( + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "encoding/hex" + "errors" + "fmt" + "hash" + "regexp" +) + +// The UUID reserved variants. +const ( + ReservedNCS byte = 0x80 + ReservedRFC4122 byte = 0x40 + ReservedMicrosoft byte = 0x20 + ReservedFuture byte = 0x00 +) + +// The following standard UUIDs are for use with NewV3() or NewV5(). +var ( + NamespaceDNS, _ = ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + NamespaceURL, _ = ParseHex("6ba7b811-9dad-11d1-80b4-00c04fd430c8") + NamespaceOID, _ = ParseHex("6ba7b812-9dad-11d1-80b4-00c04fd430c8") + NamespaceX500, _ = ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +) + +// Pattern used to parse hex string representation of the UUID. +// FIXME: do something to consider both brackets at one time, +// current one allows to parse string with only one opening +// or closing bracket. +const hexPattern = "^(urn\\:uuid\\:)?\\{?([a-z0-9]{8})-([a-z0-9]{4})-" + + "([1-5][a-z0-9]{3})-([a-z0-9]{4})-([a-z0-9]{12})\\}?$" + +var re = regexp.MustCompile(hexPattern) + +// A UUID representation compliant with specification in +// RFC 4122 document. +type UUID [16]byte + +// ParseHex creates a UUID object from given hex string +// representation. Function accepts UUID string in following +// formats: +// +// uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +// uuid.ParseHex("{6ba7b814-9dad-11d1-80b4-00c04fd430c8}") +// uuid.ParseHex("urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8") +// +func ParseHex(s string) (u *UUID, err error) { + md := re.FindStringSubmatch(s) + if md == nil { + err = errors.New("Invalid UUID string") + return + } + hash := md[2] + md[3] + md[4] + md[5] + md[6] + b, err := hex.DecodeString(hash) + if err != nil { + return + } + u = new(UUID) + copy(u[:], b) + return +} + +// Parse creates a UUID object from given bytes slice. +func Parse(b []byte) (u *UUID, err error) { + if len(b) != 16 { + err = errors.New("Given slice is not valid UUID sequence") + return + } + u = new(UUID) + copy(u[:], b) + return +} + +// Generate a UUID based on the MD5 hash of a namespace identifier +// and a name. +func NewV3(ns *UUID, name []byte) (u *UUID, err error) { + if ns == nil { + err = errors.New("Invalid namespace UUID") + return + } + u = new(UUID) + // Set all bits to MD5 hash generated from namespace and name. + u.setBytesFromHash(md5.New(), ns[:], name) + u.setVariant(ReservedRFC4122) + u.setVersion(3) + return +} + +// Generate a random UUID. +func NewV4() (u *UUID, err error) { + u = new(UUID) + // Set all bits to randomly (or pseudo-randomly) chosen values. + _, err = rand.Read(u[:]) + if err != nil { + return + } + u.setVariant(ReservedRFC4122) + u.setVersion(4) + return +} + +// Generate a UUID based on the SHA-1 hash of a namespace identifier +// and a name. +func NewV5(ns *UUID, name []byte) (u *UUID, err error) { + u = new(UUID) + // Set all bits to truncated SHA1 hash generated from namespace + // and name. + u.setBytesFromHash(sha1.New(), ns[:], name) + u.setVariant(ReservedRFC4122) + u.setVersion(5) + return +} + +// Generate a MD5 hash of a namespace and a name, and copy it to the +// UUID slice. +func (u *UUID) setBytesFromHash(hash hash.Hash, ns, name []byte) { + hash.Write(ns[:]) + hash.Write(name) + copy(u[:], hash.Sum([]byte{})[:16]) +} + +// Set the two most significant bits (bits 6 and 7) of the +// clock_seq_hi_and_reserved to zero and one, respectively. +func (u *UUID) setVariant(v byte) { + switch v { + case ReservedNCS: + u[8] = (u[8] | ReservedNCS) & 0xBF + case ReservedRFC4122: + u[8] = (u[8] | ReservedRFC4122) & 0x7F + case ReservedMicrosoft: + u[8] = (u[8] | ReservedMicrosoft) & 0x3F + } +} + +// Variant returns the UUID Variant, which determines the internal +// layout of the UUID. This will be one of the constants: RESERVED_NCS, +// RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE. +func (u *UUID) Variant() byte { + if u[8]&ReservedNCS == ReservedNCS { + return ReservedNCS + } else if u[8]&ReservedRFC4122 == ReservedRFC4122 { + return ReservedRFC4122 + } else if u[8]&ReservedMicrosoft == ReservedMicrosoft { + return ReservedMicrosoft + } + return ReservedFuture +} + +// Set the four most significant bits (bits 12 through 15) of the +// time_hi_and_version field to the 4-bit version number. +func (u *UUID) setVersion(v byte) { + u[6] = (u[6] & 0xF) | (v << 4) +} + +// Version returns a version number of the algorithm used to +// generate the UUID sequence. +func (u *UUID) Version() uint { + return uint(u[6] >> 4) +} + +// Returns unparsed version of the generated UUID sequence. +func (u *UUID) String() string { + return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) +} diff --git a/vendor/github.com/packer-community/winrmcp/LICENSE b/vendor/github.com/packer-community/winrmcp/LICENSE new file mode 100644 index 000000000..22a81f8c9 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2015 Dylan Meissner + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/cp.go b/vendor/github.com/packer-community/winrmcp/winrmcp/cp.go new file mode 100644 index 000000000..1065e4529 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/cp.go @@ -0,0 +1,200 @@ +package winrmcp + +import ( + "encoding/base64" + "errors" + "fmt" + "io" + "log" + "os" + "sync" + + "github.com/masterzen/winrm/winrm" + "github.com/mitchellh/packer/common/uuid" +) + +func doCopy(client *winrm.Client, config *Config, in io.Reader, toPath string) error { + tempFile := fmt.Sprintf("winrmcp-%s.tmp", uuid.TimeOrderedUUID()) + tempPath := "$env:TEMP\\" + tempFile + + if os.Getenv("WINRMCP_DEBUG") != "" { + log.Printf("Copying file to %s\n", tempPath) + } + + err := uploadContent(client, config.MaxOperationsPerShell, "%TEMP%\\"+tempFile, in) + if err != nil { + return errors.New(fmt.Sprintf("Error uploading file to %s: %v", tempPath, err)) + } + + if os.Getenv("WINRMCP_DEBUG") != "" { + log.Printf("Moving file from %s to %s", tempPath, toPath) + } + + err = restoreContent(client, tempPath, toPath) + if err != nil { + return errors.New(fmt.Sprintf("Error restoring file from %s to %s: %v", tempPath, toPath, err)) + } + + if os.Getenv("WINRMCP_DEBUG") != "" { + log.Printf("Removing temporary file %s", tempPath) + } + + err = cleanupContent(client, tempPath) + if err != nil { + return errors.New(fmt.Sprintf("Error removing temporary file %s: %v", tempPath, err)) + } + + return nil +} + +func uploadContent(client *winrm.Client, maxChunks int, filePath string, reader io.Reader) error { + var err error + done := false + for !done { + done, err = uploadChunks(client, filePath, maxChunks, reader) + if err != nil { + return err + } + } + + return nil +} + +func uploadChunks(client *winrm.Client, filePath string, maxChunks int, reader io.Reader) (bool, error) { + shell, err := client.CreateShell() + if err != nil { + return false, errors.New(fmt.Sprintf("Couldn't create shell: %v", err)) + } + defer shell.Close() + + // Upload the file in chunks to get around the Windows command line size limit. + // Base64 encodes each set of three bytes into four bytes. In addition the output + // is padded to always be a multiple of four. + // + // ceil(n / 3) * 4 = m1 - m2 + // + // where: + // n = bytes + // m1 = max (8192 character command limit.) + // m2 = len(filePath) + + chunkSize := ((8000 - len(filePath)) / 4) * 3 + chunk := make([]byte, chunkSize) + + if maxChunks == 0 { + maxChunks = 1 + } + + for i := 0; i < maxChunks; i++ { + n, err := reader.Read(chunk) + + if err != nil && err != io.EOF { + return false, err + } + if n == 0 { + return true, nil + } + + content := base64.StdEncoding.EncodeToString(chunk[:n]) + if err = appendContent(shell, filePath, content); err != nil { + return false, err + } + } + + return false, nil +} + +func restoreContent(client *winrm.Client, fromPath, toPath string) error { + shell, err := client.CreateShell() + if err != nil { + return err + } + + defer shell.Close() + script := fmt.Sprintf(` + $tmp_file_path = [System.IO.Path]::GetFullPath("%s") + $dest_file_path = [System.IO.Path]::GetFullPath("%s") + if (Test-Path $dest_file_path) { + rm $dest_file_path + } + else { + $dest_dir = ([System.IO.Path]::GetDirectoryName($dest_file_path)) + New-Item -ItemType directory -Force -ErrorAction SilentlyContinue -Path $dest_dir | Out-Null + } + + if (Test-Path $tmp_file_path) { + $base64_lines = Get-Content $tmp_file_path + $base64_string = [string]::join("",$base64_lines) + $bytes = [System.Convert]::FromBase64String($base64_string) + [System.IO.File]::WriteAllBytes($dest_file_path, $bytes) + } else { + echo $null > $dest_file_path + } + `, fromPath, toPath) + + cmd, err := shell.Execute(winrm.Powershell(script)) + if err != nil { + return err + } + defer cmd.Close() + + var wg sync.WaitGroup + copyFunc := func(w io.Writer, r io.Reader) { + defer wg.Done() + io.Copy(w, r) + } + + wg.Add(2) + go copyFunc(os.Stdout, cmd.Stdout) + go copyFunc(os.Stderr, cmd.Stderr) + + cmd.Wait() + wg.Wait() + + if cmd.ExitCode() != 0 { + return errors.New(fmt.Sprintf("restore operation returned code=%d", cmd.ExitCode())) + } + return nil +} + +func cleanupContent(client *winrm.Client, filePath string) error { + shell, err := client.CreateShell() + if err != nil { + return err + } + + defer shell.Close() + cmd, _ := shell.Execute("powershell", "Remove-Item", filePath, "-ErrorAction SilentlyContinue") + + cmd.Wait() + cmd.Close() + return nil +} + +func appendContent(shell *winrm.Shell, filePath, content string) error { + cmd, err := shell.Execute(fmt.Sprintf("echo %s >> \"%s\"", content, filePath)) + + if err != nil { + return err + } + + defer cmd.Close() + var wg sync.WaitGroup + copyFunc := func(w io.Writer, r io.Reader) { + defer wg.Done() + io.Copy(w, r) + } + + wg.Add(2) + go copyFunc(os.Stdout, cmd.Stdout) + go copyFunc(os.Stderr, cmd.Stderr) + + cmd.Wait() + wg.Wait() + + if cmd.ExitCode() != 0 { + return errors.New(fmt.Sprintf("upload operation returned code=%d", cmd.ExitCode())) + } + + return nil +} diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/endpoint.go b/vendor/github.com/packer-community/winrmcp/winrmcp/endpoint.go new file mode 100644 index 000000000..ccd7d0d12 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/endpoint.go @@ -0,0 +1,42 @@ +package winrmcp + +import ( + "errors" + "fmt" + "net" + "strconv" + "strings" + + "github.com/masterzen/winrm/winrm" +) + +func parseEndpoint(addr string, https bool, insecure bool, caCert []byte) (*winrm.Endpoint, error) { + var host string + var port int + + if addr == "" { + return nil, errors.New("Couldn't convert \"\" to an address.") + } + if !strings.Contains(addr, ":") { + host = addr + port = 5985 + } else { + shost, sport, err := net.SplitHostPort(addr) + if err != nil { + return nil, errors.New(fmt.Sprintf("Couldn't convert \"%s\" to an address.", addr)) + } + host = shost + port, err = strconv.Atoi(sport) + if err != nil { + return nil, errors.New("Couldn't convert \"%s\" to a port number.") + } + } + + return &winrm.Endpoint{ + Host: host, + Port: port, + HTTPS: https, + Insecure: insecure, + CACert: &caCert, + }, nil +} diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/ls.go b/vendor/github.com/packer-community/winrmcp/winrmcp/ls.go new file mode 100644 index 000000000..1a6cbaf5c --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/ls.go @@ -0,0 +1,71 @@ +package winrmcp + +import ( + "encoding/xml" + "errors" + "fmt" + "log" + "os" + "strconv" + + "github.com/masterzen/winrm/winrm" +) + +type FileItem struct { + Name string + Path string + Mode string + LastWriteTime string + Length int +} + +func fetchList(client *winrm.Client, remotePath string) ([]FileItem, error) { + script := fmt.Sprintf("Get-ChildItem %s", remotePath) + stdout, stderr, _, err := client.RunWithString("powershell -Command \""+script+" | ConvertTo-Xml -NoTypeInformation -As String\"", "") + if err != nil { + return nil, errors.New(fmt.Sprintf("Couldn't execute script %s: %v", script, err)) + } + + if stderr != "" { + if os.Getenv("WINRMCP_DEBUG") != "" { + log.Printf("STDERR returned: %s\n", stderr) + } + } + + if stdout != "" { + doc := pslist{} + err := xml.Unmarshal([]byte(stdout), &doc) + if err != nil { + return nil, errors.New(fmt.Sprintf("Couldn't parse results: %v", err)) + } + + return convertFileItems(doc.Objects), nil + } + + return []FileItem{}, nil +} + +func convertFileItems(objects []psobject) []FileItem { + items := make([]FileItem, len(objects)) + + for i, object := range objects { + for _, property := range object.Properties { + switch property.Name { + case "Name": + items[i].Name = property.Value + case "Mode": + items[i].Mode = property.Value + case "FullName": + items[i].Path = property.Value + case "Length": + if n, err := strconv.Atoi(property.Value); err == nil { + items[i].Length = n + } + case "LastWriteTime": + items[i].LastWriteTime = property.Value + } + } + } + + return items +} diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/path.go b/vendor/github.com/packer-community/winrmcp/winrmcp/path.go new file mode 100644 index 000000000..c35cc0728 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/path.go @@ -0,0 +1,18 @@ +package winrmcp + +import ( + "fmt" + "strings" +) + +func winPath(path string) string { + if len(path) == 0 { + return path + } + + if strings.Contains(path, " ") { + path = fmt.Sprintf("'%s'", strings.Trim(path, "'\"")) + } + + return strings.Replace(path, "/", "\\", -1) +} diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go b/vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go new file mode 100644 index 000000000..5374fdba5 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go @@ -0,0 +1,17 @@ +package winrmcp + +type pslist struct { + Objects []psobject `xml:"Object"` +} + +type psobject struct { + Properties []psproperty `xml:"Property"` + Value string `xml:",innerxml"` +} + +type psproperty struct { + Name string `xml:"Name,attr"` + Value string `xml:",innerxml"` +} + + diff --git a/vendor/github.com/packer-community/winrmcp/winrmcp/winrmcp.go b/vendor/github.com/packer-community/winrmcp/winrmcp/winrmcp.go new file mode 100644 index 000000000..844c5a2f6 --- /dev/null +++ b/vendor/github.com/packer-community/winrmcp/winrmcp/winrmcp.go @@ -0,0 +1,117 @@ +package winrmcp + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "time" + + "github.com/dylanmei/iso8601" + "github.com/masterzen/winrm/winrm" +) + +type Winrmcp struct { + client *winrm.Client + config *Config +} + +type Config struct { + Auth Auth + Https bool + Insecure bool + CACertBytes []byte + OperationTimeout time.Duration + MaxOperationsPerShell int +} + +type Auth struct { + User string + Password string +} + +func New(addr string, config *Config) (*Winrmcp, error) { + endpoint, err := parseEndpoint(addr, config.Https, config.Insecure, config.CACertBytes) + if err != nil { + return nil, err + } + if config == nil { + config = &Config{} + } + + params := winrm.DefaultParameters() + if config.OperationTimeout.Seconds() > 0 { + params.Timeout = iso8601.FormatDuration(config.OperationTimeout) + } + client, err := winrm.NewClientWithParameters( + endpoint, config.Auth.User, config.Auth.Password, params) + return &Winrmcp{client, config}, err +} + +func (fs *Winrmcp) Copy(fromPath, toPath string) error { + f, err := os.Open(fromPath) + if err != nil { + return errors.New(fmt.Sprintf("Couldn't read file %s: %v", fromPath, err)) + } + + defer f.Close() + fi, err := f.Stat() + if err != nil { + return errors.New(fmt.Sprintf("Couldn't stat file %s: %v", fromPath, err)) + } + + if !fi.IsDir() { + return fs.Write(toPath, f) + } else { + fw := fileWalker{ + client: fs.client, + config: fs.config, + toDir: toPath, + fromDir: fromPath, + } + return filepath.Walk(fromPath, fw.copyFile) + } +} + +func (fs *Winrmcp) Write(toPath string, src io.Reader) error { + return doCopy(fs.client, fs.config, src, winPath(toPath)) +} + +func (fs *Winrmcp) List(remotePath string) ([]FileItem, error) { + return fetchList(fs.client, winPath(remotePath)) +} + +type fileWalker struct { + client *winrm.Client + config *Config + toDir string + fromDir string +} + +func (fw *fileWalker) copyFile(fromPath string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + if !shouldUploadFile(fi) { + return nil + } + + hostPath, _ := filepath.Abs(fromPath) + fromDir, _ := filepath.Abs(fw.fromDir) + relPath, _ := filepath.Rel(fromDir, hostPath) + toPath := filepath.Join(fw.toDir, relPath) + + f, err := os.Open(hostPath) + if err != nil { + return errors.New(fmt.Sprintf("Couldn't read file %s: %v", fromPath, err)) + } + + return doCopy(fw.client, fw.config, f, winPath(toPath)) +} + +func shouldUploadFile(fi os.FileInfo) bool { + // Ignore dir entries and OS X special hidden file + return !fi.IsDir() && ".DS_Store" != fi.Name() +} diff --git a/vendor/github.com/pierrec/lz4/.travis.yml b/vendor/github.com/pierrec/lz4/.travis.yml new file mode 100644 index 000000000..5fd623633 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4 + - 1.5 + +script: + - go test -cpu=2 + - go test -cpu=2 -race \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/LICENSE b/vendor/github.com/pierrec/lz4/LICENSE new file mode 100644 index 000000000..bd899d835 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015, Pierre Curto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of xxHash nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/pierrec/lz4/README.md b/vendor/github.com/pierrec/lz4/README.md new file mode 100644 index 000000000..dd3c9d47e --- /dev/null +++ b/vendor/github.com/pierrec/lz4/README.md @@ -0,0 +1,31 @@ +[![godoc](https://godoc.org/github.com/pierrec/lz4?status.png)](https://godoc.org/github.com/pierrec/lz4) +[![Build Status](https://travis-ci.org/pierrec/lz4.svg?branch=master)](https://travis-ci.org/pierrec/lz4) + +# lz4 +LZ4 compression and decompression in pure Go + +## Usage + +```go +import "github.com/pierrec/lz4" +``` + +## Description + +Package lz4 implements reading and writing lz4 compressed data (a frame), +as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html, +using an io.Reader (decompression) and io.Writer (compression). +It is designed to minimize memory usage while maximizing throughput by being able to +[de]compress data concurrently. + +The Reader and the Writer support concurrent processing provided the supplied buffers are +large enough (in multiples of BlockMaxSize) and there is no block dependency. +Reader.WriteTo and Writer.ReadFrom do leverage the concurrency transparently. +The runtime.GOMAXPROCS() value is used to apply concurrency or not. + +Although the block level compression and decompression functions are exposed and are fully compatible +with the lz4 block format definition, they are low level and should not be used directly. +For a complete description of an lz4 compressed block, see: +http://fastcompression.blogspot.fr/2011/05/lz4-explained.html + +See https://github.com/Cyan4973/lz4 for the reference C implementation. diff --git a/vendor/github.com/pierrec/lz4/block.go b/vendor/github.com/pierrec/lz4/block.go new file mode 100644 index 000000000..145eec270 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/block.go @@ -0,0 +1,445 @@ +package lz4 + +import ( + "encoding/binary" + "errors" +) + +// block represents a frame data block. +// Used when compressing or decompressing frame blocks concurrently. +type block struct { + compressed bool + zdata []byte // compressed data + data []byte // decompressed data + offset int // offset within the data as with block dependency the 64Kb window is prepended to it + checksum uint32 // compressed data checksum + err error // error while [de]compressing +} + +var ( + // ErrInvalidSource is returned by UncompressBlock when a compressed block is corrupted. + ErrInvalidSource = errors.New("lz4: invalid source") + // ErrShortBuffer is returned by UncompressBlock, CompressBlock or CompressBlockHC when + // the supplied buffer for [de]compression is too small. + ErrShortBuffer = errors.New("lz4: short buffer") +) + +// CompressBlockBound returns the maximum size of a given buffer of size n, when not compressible. +func CompressBlockBound(n int) int { + return n + n/255 + 16 +} + +// UncompressBlock decompresses the source buffer into the destination one, +// starting at the di index and returning the decompressed size. +// +// The destination buffer must be sized appropriately. +// +// An error is returned if the source data is invalid or the destination buffer is too small. +func UncompressBlock(src, dst []byte, di int) (int, error) { + si, sn, di0 := 0, len(src), di + if sn == 0 { + return 0, nil + } + + for { + // literals and match lengths (token) + lLen := int(src[si] >> 4) + mLen := int(src[si] & 0xF) + if si++; si == sn { + return di, ErrInvalidSource + } + + // literals + if lLen > 0 { + if lLen == 0xF { + for src[si] == 0xFF { + lLen += 0xFF + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + lLen += int(src[si]) + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + if len(dst)-di < lLen || si+lLen > sn { + return di - di0, ErrShortBuffer + } + di += copy(dst[di:], src[si:si+lLen]) + + if si += lLen; si >= sn { + return di - di0, nil + } + } + + if si += 2; si >= sn { + return di, ErrInvalidSource + } + offset := int(src[si-2]) | int(src[si-1])<<8 + if di-offset < 0 || offset == 0 { + return di - di0, ErrInvalidSource + } + + // match + if mLen == 0xF { + for src[si] == 0xFF { + mLen += 0xFF + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + mLen += int(src[si]) + if si++; si == sn { + return di - di0, ErrInvalidSource + } + } + // minimum match length is 4 + mLen += 4 + if len(dst)-di <= mLen { + return di - di0, ErrShortBuffer + } + + // copy the match (NB. match is at least 4 bytes long) + // NB. past di, copy() would write old bytes instead of + // the ones we just copied, so split the work into the largest chunk. + for ; mLen >= offset; mLen -= offset { + di += copy(dst[di:], dst[di-offset:di]) + } + di += copy(dst[di:], dst[di-offset:di-offset+mLen]) + } +} + +// CompressBlock compresses the source buffer starting at soffet into the destination one. +// This is the fast version of LZ4 compression and also the default one. +// +// The size of the compressed data is returned. If it is 0 and no error, then the data is incompressible. +// +// An error is returned if the destination buffer is too small. +func CompressBlock(src, dst []byte, soffset int) (int, error) { + sn, dn := len(src)-mfLimit, len(dst) + if sn <= 0 || dn == 0 || soffset >= sn { + return 0, nil + } + var si, di int + + // fast scan strategy: + // we only need a hash table to store the last sequences (4 bytes) + var hashTable [1 << hashLog]int + var hashShift = uint((minMatch * 8) - hashLog) + + // Initialise the hash table with the first 64Kb of the input buffer + // (used when compressing dependent blocks) + for si < soffset { + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + si++ + hashTable[h] = si + } + + anchor := si + fma := 1 << skipStrength + for si < sn-minMatch { + // hash the next 4 bytes (sequence)... + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + // -1 to separate existing entries from new ones + ref := hashTable[h] - 1 + // ...and store the position of the hash in the hash table (+1 to compensate the -1 upon saving) + hashTable[h] = si + 1 + // no need to check the last 3 bytes in the first literal 4 bytes as + // this guarantees that the next match, if any, is compressed with + // a lower size, since to have some compression we must have: + // ll+ml-overlap > 1 + (ll-15)/255 + (ml-4-15)/255 + 2 (uncompressed size>compressed size) + // => ll+ml>3+2*overlap => ll+ml>= 4+2*overlap + // and by definition we do have: + // ll >= 1, ml >= 4 + // => ll+ml >= 5 + // => so overlap must be 0 + + // the sequence is new, out of bound (64kb) or not valid: try next sequence + if ref < 0 || fma&(1<>winSizeLog > 0 || + src[ref] != src[si] || + src[ref+1] != src[si+1] || + src[ref+2] != src[si+2] || + src[ref+3] != src[si+3] { + // variable step: improves performance on non-compressible data + si += fma >> skipStrength + fma++ + continue + } + // match found + fma = 1 << skipStrength + lLen := si - anchor + offset := si - ref + + // encode match length part 1 + si += minMatch + mLen := si // match length has minMatch already + for si <= sn && src[si] == src[si-offset] { + si++ + } + mLen = si - mLen + if mLen < 0xF { + dst[di] = byte(mLen) + } else { + dst[di] = 0xF + } + + // encode literals length + if lLen < 0xF { + dst[di] |= byte(lLen << 4) + } else { + dst[di] |= 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + l := lLen - 0xF + for ; l >= 0xFF; l -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(l) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // literals + if di+lLen >= dn { + return di, ErrShortBuffer + } + di += copy(dst[di:], src[anchor:anchor+lLen]) + anchor = si + + // encode offset + if di += 2; di >= dn { + return di, ErrShortBuffer + } + dst[di-2], dst[di-1] = byte(offset), byte(offset>>8) + + // encode match length part 2 + if mLen >= 0xF { + for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(mLen) + if di++; di == dn { + return di, ErrShortBuffer + } + } + } + + if anchor == 0 { + // incompressible + return 0, nil + } + + // last literals + lLen := len(src) - anchor + if lLen < 0xF { + dst[di] = byte(lLen << 4) + } else { + dst[di] = 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + lLen -= 0xF + for ; lLen >= 0xFF; lLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(lLen) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // write literals + src = src[anchor:] + switch n := di + len(src); { + case n > dn: + return di, ErrShortBuffer + case n >= sn: + // incompressible + return 0, nil + } + di += copy(dst[di:], src) + return di, nil +} + +// CompressBlockHC compresses the source buffer starting at soffet into the destination one. +// CompressBlockHC compression ratio is better than CompressBlock but it is also slower. +// +// The size of the compressed data is returned. If it is 0 and no error, then the data is not compressible. +// +// An error is returned if the destination buffer is too small. +func CompressBlockHC(src, dst []byte, soffset int) (int, error) { + sn, dn := len(src)-mfLimit, len(dst) + if sn <= 0 || dn == 0 || soffset >= sn { + return 0, nil + } + var si, di int + + // Hash Chain strategy: + // we need a hash table and a chain table + // the chain table cannot contain more entries than the window size (64Kb entries) + var hashTable [1 << hashLog]int + var chainTable [winSize]int + var hashShift = uint((minMatch * 8) - hashLog) + + // Initialise the hash table with the first 64Kb of the input buffer + // (used when compressing dependent blocks) + for si < soffset { + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + chainTable[si&winMask] = hashTable[h] + si++ + hashTable[h] = si + } + + anchor := si + for si < sn-minMatch { + // hash the next 4 bytes (sequence)... + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + + // follow the chain until out of window and give the longest match + mLen := 0 + offset := 0 + for next := hashTable[h] - 1; next > 0 && next > si-winSize; next = chainTable[next&winMask] - 1 { + // the first (mLen==0) or next byte (mLen>=minMatch) at current match length must match to improve on the match length + if src[next+mLen] == src[si+mLen] { + for ml := 0; ; ml++ { + if src[next+ml] != src[si+ml] || si+ml > sn { + // found a longer match, keep its position and length + if mLen < ml && ml >= minMatch { + mLen = ml + offset = si - next + } + break + } + } + } + } + chainTable[si&winMask] = hashTable[h] + hashTable[h] = si + 1 + + // no match found + if mLen == 0 { + si++ + continue + } + + // match found + // update hash/chain tables with overlaping bytes: + // si already hashed, add everything from si+1 up to the match length + for si, ml := si+1, si+mLen; si < ml; { + h := binary.LittleEndian.Uint32(src[si:]) * hasher >> hashShift + chainTable[si&winMask] = hashTable[h] + si++ + hashTable[h] = si + } + + lLen := si - anchor + si += mLen + mLen -= minMatch // match length does not include minMatch + + if mLen < 0xF { + dst[di] = byte(mLen) + } else { + dst[di] = 0xF + } + + // encode literals length + if lLen < 0xF { + dst[di] |= byte(lLen << 4) + } else { + dst[di] |= 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + l := lLen - 0xF + for ; l >= 0xFF; l -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(l) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // literals + if di+lLen >= dn { + return di, ErrShortBuffer + } + di += copy(dst[di:], src[anchor:anchor+lLen]) + anchor = si + + // encode offset + if di += 2; di >= dn { + return di, ErrShortBuffer + } + dst[di-2], dst[di-1] = byte(offset), byte(offset>>8) + + // encode match length part 2 + if mLen >= 0xF { + for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(mLen) + if di++; di == dn { + return di, ErrShortBuffer + } + } + } + + if anchor == 0 { + // incompressible + return 0, nil + } + + // last literals + lLen := len(src) - anchor + if lLen < 0xF { + dst[di] = byte(lLen << 4) + } else { + dst[di] = 0xF0 + if di++; di == dn { + return di, ErrShortBuffer + } + lLen -= 0xF + for ; lLen >= 0xFF; lLen -= 0xFF { + dst[di] = 0xFF + if di++; di == dn { + return di, ErrShortBuffer + } + } + dst[di] = byte(lLen) + } + if di++; di == dn { + return di, ErrShortBuffer + } + + // write literals + src = src[anchor:] + switch n := di + len(src); { + case n > dn: + return di, ErrShortBuffer + case n >= sn: + // incompressible + return 0, nil + } + di += copy(dst[di:], src) + return di, nil +} diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/01572067d493db8dc8161f05c339a5192b0b4087-22 new file mode 100644 index 0000000000000000000000000000000000000000..4b8b629d5449a3467afe85535aa7eec4223bac59 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f e%z-KxKUFp4G@E%rU3w`^c_n8 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/02766f768fbfbd81b752cce427eb5242a44929cc-5 new file mode 100644 index 0000000000000000000000000000000000000000..ead0ac0d319ff48ac6dc14c1db920ee00ceb917a GIT binary patch literal 19 ZcmZQk@|DO-Y&o%a|NB@5Mg|~g002Oq1@Hg> literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/032f04032e12567057782672bb12670c20d38439-10 new file mode 100644 index 0000000000000000000000000000000000000000..f1a389337beb616a2f139bf9205844ad38db9044 GIT binary patch literal 23 dcmZQk@|Ey)P+GZn|N8>%=qn6B;H2d%0RUK(2I>F+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/0367b985641aca66e6e4eeea68acf5e2a02c62a8-16 new file mode 100644 index 0000000000000000000000000000000000000000..753a67cd3ca9f4e93e6370b727a4729ed05f2bfe GIT binary patch literal 38 scmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+ULaZX|9=AmgG3$^g957r0O39gRsaA1 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 b/vendor/github.com/pierrec/lz4/fuzz/corpus/03e85abc49352b2f7cc83efd7e4274da02d78b84-6 new file mode 100644 index 0000000000000000000000000000000000000000..d2017a91adb9aca4ffd9ec8a84fd76ffc43f5083 GIT binary patch literal 13 RcmZS4@|9o!0u~@W82||00lEMH literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/049f82a81bb6b4d7cf69fac5e413f6ce299d48cf-8 new file mode 100644 index 0000000000000000000000000000000000000000..a69e01f280889b4a8249ce9b8cb378b796c262e0 GIT binary patch literal 19 acmZQk@|Ey)U|?|4^5tPrXJlYF#{>Wye*)G3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/04c05c7956f17e57a91a47909bd0706135cf17a6-1 new file mode 100644 index 0000000000000000000000000000000000000000..0ea966b8f7cc3049888e796ad3ccdd9f375d71b6 GIT binary patch literal 46 zcmZ>Y$}l!`j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`F~O1^kq;)OQ06z*mIMgS$D B4Kx4% literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 b/vendor/github.com/pierrec/lz4/fuzz/corpus/050e2af2a57d8044139ba21375f0ac6fcb7ab0b1-12 new file mode 100644 index 0000000000000000000000000000000000000000..6cb971272a19d3fa9fddcb0617ef95cb36991fbc GIT binary patch literal 84 XcmZ>Y%CHbGaY$}lu^j8qGbEVa7Mz`*dT=HS0UrPW literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/0990ac54decbca1a97893e83c7feb2be89cb10ea-14 new file mode 100644 index 0000000000000000000000000000000000000000..37a0194e55dcdb47987d0f668a3ddc54ffaf1529 GIT binary patch literal 68 ocmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lW~Fqwx$Ld20pU~CW#0Ig98lmGw# literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/09f2eda28ecc97304659afded4d13a188baf2107-22 new file mode 100644 index 0000000000000000000000000000000000000000..c1b1ad50619559026aeac86cefc84eda3e3a405f GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y%CHbGa08$7BS^xk5 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/0cf885cd35e7124005b0ba0c3c4431ddfaeff84d-11 new file mode 100644 index 0000000000000000000000000000000000000000..b45509f6e5afba39a7f6aa400b98857af321b0f6 GIT binary patch literal 48 ScmZS4@|9o!0u~}@kQxA6pacd0 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 new file mode 100644 index 000000000..666657295 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/0d7c02d4e91d82b0355baaca1237062639442db6-3 @@ -0,0 +1 @@ +"M@5 \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/0e1b2b0c49dfb86fe01d3453dd24e39482e132e8-7 new file mode 100644 index 0000000000000000000000000000000000000000..8ca78705a4e4e7465e5326de594a8bccfe422481 GIT binary patch literal 21 bcmZQk@|DO-Y&o%a|NB@5Mg}GZAaDc#OG^c_ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..c21a363248ee3e69300c4f872699e14d94b64609 GIT binary patch literal 42 ycmZ>Y$}lu^j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}ki!aB=VRT6ih(^4M27xNDQn(7AT+u5(ddY JltL+}HURCk8Dsze literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 b/vendor/github.com/pierrec/lz4/fuzz/corpus/10fa5d9f0fe75f73c0e92a1fe1c00f0041ec8f39-24 new file mode 100644 index 0000000000000000000000000000000000000000..62459e7280d635ee35f1980023b924ec33fd2c66 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%z8{OoL FL;wi63k(1N literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/11.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/11.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..b8539d875265721333033cef148a8ddb5b49cee6 GIT binary patch literal 14 TcmZ>Y$}kcyaY$}ko$aY$}kZxaY$}kl#aB=VRT6c`y~85kOrK*B)O0Fi-GP*nhK C#S`%W literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/142d4f8cb427dd3562d72d889dfc0ea3a2b03d98-22 new file mode 100644 index 0000000000000000000000000000000000000000..d162c38e792e97a45e2f10a9bbc70df796f7e142 GIT binary patch literal 83 bcmZQk@|DO-Y&o%a|NB@5Mg|~gpcDfDw7d=Q literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/15.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/15.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..bd2c29c27df1ef3674b1ac103ab04003f810e7c7 GIT binary patch literal 14 TcmZ>Y$}kfzaY$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42DdC He^MI&cccu4 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/16.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/16.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..5e13f64415b9b631a4303809662903f269bf3e4d GIT binary patch literal 14 TcmZ>Y$}kr%aY%CHbGaY$}lu^j8qGbRA4aVVK{Oq^<3Y%CHnKaY$}lu^j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGh+=a literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/191e0dd24b8c7f8babeae4839768df39acc17eb1-17 new file mode 100644 index 0000000000000000000000000000000000000000..000242c63608a1181bc2c414ded8cc81b0d4bb8e GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^&cG||4gkZR3)27q literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1a582381781f264f551bd6f0f2284a931147e6d9-4 new file mode 100644 index 0000000000000000000000000000000000000000..c02b40509a98970d9d91af2f9b6dfbf090a79955 GIT binary patch literal 9 QcmZ?L@|EzFU|?VX00=h$Hvj+t literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1c2781a1ffae4059ce3e93a55ec8d8cbf8bdecdf-22 new file mode 100644 index 0000000000000000000000000000000000000000..a9c4864764d15e1589fee301bc67511e661421a1 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f e%z-KxKUFp4K-j2Y8n8g?j1q^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 new file mode 100644 index 000000000..ee12c7a5d --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/1d37fb332301cf7de0bd51a8c1aa9be4935e89fc-1 @@ -0,0 +1 @@ +"M \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1d6b87b52e62cb84be834478ad88129f5e1f247b-9 new file mode 100644 index 0000000000000000000000000000000000000000..bd5ff8ff1fa0e21cada483100c931b2c0509ea8a GIT binary patch literal 32 icmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d2niHrNCW_vPza6y literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 new file mode 100644 index 000000000..7eeb2e864 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/1ec2f11a8d8b9cf188a58f673a0b4a8608a926ca-3 @@ -0,0 +1 @@ +"M3 \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1fc2ba0bb981fec47badea1c80219452c9e3c76c-22 new file mode 100644 index 0000000000000000000000000000000000000000..b53b47a542019475666d8c29698187d4d7d018c9 GIT binary patch literal 88 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txS)D9UKnWxamihm` M0i*y-feDE`0G!1a#sB~S literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/1fd8444ac43541c44a1c6ed8df2f688b1fa09681-1 new file mode 100644 index 0000000000000000000000000000000000000000..f3fe56210bc1e92f2456695a25d79a5f01b7af13 GIT binary patch literal 29 kcmZ>Y$}lu^j8qGbWG}V6&cMLH$Y9@~z`(Y$}lo?j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}lo?j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGms4| literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/202a9c8b188cae90f29bce3bf0438a035c504eb4-20 new file mode 100644 index 0000000000000000000000000000000000000000..0014dc68bb5ab4a287ce9ac3fee91de7158de0d2 GIT binary patch literal 62 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(R~r1H%=dMgVf`6d(Wq literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/20cf0057443ecb322ff1169ecbe6cf20250f15af-13 new file mode 100644 index 0000000000000000000000000000000000000000..f83424bf2b5731f4849848410e7298b21be08baa GIT binary patch literal 32 icmZQk@|DO-Y&o%a|NB@5Mh0F628RC-kjDgMO8@}S8w~yc literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/20d1a26afe563ad77e7a95fbee6ff59ebf3e61ab-13 new file mode 100644 index 0000000000000000000000000000000000000000..ecd0320fc6c4619a9705f58e75c34e3817de2cc0 GIT binary patch literal 46 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d93(>?0Qg!67ytkO literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/21.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/21.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0701d3d648e96b370bc62da1aaa0ab9d125cb2ff GIT binary patch literal 48 zcmZ>Y$}l!`j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGrbKh literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/22.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/22.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..25578e2dbe9903b2544519f846e4e149f2b37ca1 GIT binary patch literal 48 zcmZ>Y$}ll>j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DGwKa4 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2201e32d052c15874f0323a09c330f3666029a72-1 new file mode 100644 index 0000000000000000000000000000000000000000..c4353fe81683aeb72f1cc8ec101a86d5391353a4 GIT binary patch literal 1473 zcmV;y1wQ&hT4*^jL0KkKS(G)X0|3c~|A2H5p~Qdp|M>s^|LQ;g|L|hUKKsA`6YlAD zc`I*Yq>cap03SdA000000Pe>@o%ZE+&|9wQdZK`RbC%m4%MG;|_Z&S3uFrNr00Yvf zPytkx3ZMko01IFM1MbBD=%4@+NF%Ic3;?8kv>bPxFFi;`@6aWAeqKW_jHKKq5loTBl0MJoVC{aKaD`r6|I>_9? zM-U21B2p*-P%g%l=nSX;C@ZZ12HN{%DIf&^prud%0HT0U0)POJ0HHt>000F508@wo zs-*y+P(lKPiUD5i0011Q3ZqJiAt#e00)2o9%b#m03!C@cI|cX z^ewwOgP}kG00jU5PyhfF00000KIUddWzUy*zYj(XS zo#2k@&yew7MfZI4zGbj5%K6?ETfXnR=e?&s%=R5=*Q$L!xO%M*Oy+NSp7(1bO*@-! zeNVjg!`Ha__?%a};t#KV*Ig4ehLd#HZe5%WSj~3RyPd!h+Oykk-8A;c00%OJ&5)RG ztzZTyDyoWr1qzf8ce-*`#_b&`~O?by^sztE~1O3vuo5Rh`LsGW40~*GGGf zPkZB|RQR@KQ$s-R(QfYVxO>gByB(iRb4rwhNl&iel{AKY-g)hu*{4F9(z?@gEw^V} z*k>>R001Z(;r99-PrD}1S6tohk5Or+g!>WWuW9l?;k?@!?(**4fMbO2WQ3SjEY|`r1R~S-8op4hizH5 zZJVK|2rd%0M72}MN_ly03Lu262{qixapuq!IDEzDy6p7ni5vE zvAVms$OAwqHg4?L0noVH4FKD=8s*Sk7t5?i9^UP%z3b8Dbba^F2hWYOH{EvTcYP0f zCNbRm>+Apk0000!$C&xIS@S)4>^Ugzy;~{NwKG>SO?}u?-^ zYoHD4qPvZGO1tfYRDJWhUER|;dA-{3yPL<#rBr|b$7zpvoxMJNA5aw?>zhca6KxH7 zeeN~f01B<{6~4WFd+yyc)y>^ERz2)Q8e0majit0`DFGT1=yEP;Q&{Xck1STz7;T2u z0ZJMhd8O}XJH_ForBPGT#_v6DbiBKCLidMCgSG(i-E2rb0N1CX>GlKR@1~Ri3i+WN znwxeQcJ1!PQ?Wj}`p3q7?Fqc-TjRM6 zn5%=UyEmMpdvxS-dE2MDX7*z@x!-N?yRB{&w(fn`nmcoMZEyep9RL&n4u-0(==*Bv zZvlY_pIQgEv|#k_Ub-!sYV3F3-F){w(DUYj<|MOax&;6R<#2euGN*3La1^9T%+}iO z?G7oq_keq?2iqmq54P*O0YFdy2J_0R%t|Fb=eN7P+2?uNw>fR*#qV`Zb#{ty4$bDO zS@+O4zTdH@9gy?Rx_gJm2Ww{7>!eaL;wXwQ-&hMT*9zW5v9^Y43I zxLc>YyAMoK?X2w8RUHV{rRmw7cYOdf3(p&a*_F1J(>865RH?AlX}fjRBv5yydcX(UP7O~$LJ<%^fDqFm83fa6nWPN{i1w$Y bJxnyhAqYYtOp_=ur;|~jGynmh0006^ON7Ej literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/226780b32ba8f87ec614fdb376aa0884011c4ca9-17 new file mode 100644 index 0000000000000000000000000000000000000000..747cfa5225ae3e20fdc337a7414292ff69eff5d4 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R6qK!TBhiQ#{Q{C@zSmkDD4 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/22897c61698649d7570de91613afdc19b66e6965-20 new file mode 100644 index 0000000000000000000000000000000000000000..ea2cb769eb165150857c610aab5410ff18651319 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%ZSkOdM-AYqV9&Hw)(SqKGYOXL9n DeYF#P literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/23.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/23.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..bc8b6be6a45bc9948999c68a8ec9070ce440a596 GIT binary patch literal 48 zcmZ>Y$}lx_j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG#3po literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/234cc427d9be32470f3c2e11a6bc16567f558e55-22 new file mode 100644 index 0000000000000000000000000000000000000000..c69e874b3b8a83312db1400176c83fb7889b297a GIT binary patch literal 37 kcmZQk@|Ey)U|?|4^5tPrXB1*!V2C@NY}6vb%Y$}lr@j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG(-(B literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2486a84bf0f161f45b050d9c19ea9e35f5def864-8 new file mode 100644 index 0000000000000000000000000000000000000000..9ed0d0e084d5b31b353699faaa49f01fedd1ec0a GIT binary patch literal 25 ecmZQk@|DO-Y&o%a|NB@5Mg}GZ1_ltH!4Uvv*#{l~ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/25.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/25.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..869a668b58382ce1b5c9d869d038e9b47a3a2840 GIT binary patch literal 48 zcmZ>Y$}l%{j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG;s|v literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 b/vendor/github.com/pierrec/lz4/fuzz/corpus/25252b16cd4afa8ef86122448688c7095684c86b-12 new file mode 100644 index 0000000000000000000000000000000000000000..b5a986b2526123e39a24241fc9c34fda8adb9e40 GIT binary patch literal 25 bcmZQk@|B28Y&o&_G6MqxBM>t%uz-aCP=5tz literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/26.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/26.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..2d7678a7acfdaf4e7ec6cf9de1e87cc3b26dcd70 GIT binary patch literal 48 zcmZ>Y%CInWj8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG@cDI literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/263fb3d738b862ec4050e5a9fbabfbd99cb0d9a5-16 new file mode 100644 index 0000000000000000000000000000000000000000..72e921a6686e4a2eda634e52f94048f906a51078 GIT binary patch literal 32 lcmZQk@|EyTY&pTe$nfhwBLgo314I3P5J+cdWcdG|0RXLx408Yg literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/27.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/27.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..409a9a2d97d6f314b6e6c898648fa5a1a57ef4d0 GIT binary patch literal 48 zcmZ>Y%CIzaj8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{{s!*Z42R!)vp%>NPq DG|LS$ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/276580343a14eec04143e89a778dae3e14df472c-17 new file mode 100644 index 0000000000000000000000000000000000000000..ce6896874300e2ea4a8df1a3bbbbe3415fa37ea3 GIT binary patch literal 52 qcmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?kU#SB{{n1Qk>VvhmV1qnj{ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/27fb5dc4016dc640e55a60719a222c38c604fa6b-2 new file mode 100644 index 0000000000000000000000000000000000000000..c742bacacc44aee87823184e0084d75395aa9b02 GIT binary patch literal 14 VcmZ>Y%CHbGaz1i=6R literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/28.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/28.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..112aea2e8c0e8b29c3121f2be1ec2a17b9e35f86 GIT binary patch literal 157 zcmV;O0Al|_T4*sbL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*Y%CHbGad{ivR!s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 new file mode 100644 index 000000000..27cfb62c4 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/2b39aa66ecfac58e61185c9664a968233931496a-9 @@ -0,0 +1 @@ +"MM@"©½¿ïp+[Ô \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2c2a5947341d76797a7e2299f39d01e3aebb2eb8-19 new file mode 100644 index 0000000000000000000000000000000000000000..e94d8da56642f42dec7b8e176ad022612050e10e GIT binary patch literal 70 ocmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?jJ5kr+VY>{9F0ENyAp8x;= literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2cc2308b75a2e8f7eafcf69370767e5fce314892-13 new file mode 100644 index 0000000000000000000000000000000000000000..202625196ed4cd0cd6601c52e0e0557ad943d6d3 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628RFt|2Hr&NaQgA*%AP=Y$}lo?j8qGb6zG4f!@$5^{oTi@A>%^Ir@q-C3PxY|a9gTBdgrm6ONdGEPig}I Dnb8ta literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2de93224b5f0db491ced1ec491a9f41d71820671-11 new file mode 100644 index 0000000000000000000000000000000000000000..71c5a14eba7cd3ebbcb82906e86c2f2bd2274ede GIT binary patch literal 23 ecmZQk@|Ey)P+GZn|N8>%=qn5i3=K|Nz7hai6bEVm literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2e8487cf61feda70c0d74f12bfb5b692b684f82a-9 new file mode 100644 index 0000000000000000000000000000000000000000..f1c5b7a4fefd4ada12ca7689806d3ebe6ed44dae GIT binary patch literal 25 dcmZQk@|B28Y&o&_G6MqxBLfqVl*j|}839z823Y_A literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2f0ee9cf4bb951a37efc6460d5709442bc3de54e-6 new file mode 100644 index 0000000000000000000000000000000000000000..49c3db23b6d6173fb72a79e88637ff17a29379bb GIT binary patch literal 23 ccmZQk@|DO-Y&o%a|NB@5Mg|bbNX%0J09l;|#{d8T literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 b/vendor/github.com/pierrec/lz4/fuzz/corpus/2f1ba7fe1cd90a4023706a2ea9c7c9dca8128119-30 new file mode 100644 index 0000000000000000000000000000000000000000..3d62f949ed5e5b9647961e404b8e3c9ab7fb29e3 GIT binary patch literal 167 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz%r&j9?jJ5yK|S$Y$6A0L}>w3IG5A literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..197b557835ae0dacf12146abcfdea1713aa313aa GIT binary patch literal 42 ycmZ>Y$}l!`j8qGbWG}V6&cMLH$Y9@~z+lM3aO60|QVF$Okgy69EUm B3$XwI literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/31.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/31.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..22bbfb22c38d277892dc0bd8d87aee40bcfe6533 GIT binary patch literal 157 zcmV;O0Al|_T4*#eL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*iL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e_0kn2jrQ&<)@Eixu}cN3W|eT2obV{S=$ zAzI3A5HnhFs6ue@OfL1nJQJm4Zx?=H_0Wa}WDBNGGL(qUj^!B))kRsU*Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkg$`6D9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3771c6e8ea0f20350dae0180a9b14e36b8aef244-22 new file mode 100644 index 0000000000000000000000000000000000000000..0d255bfa1e0cf635c76827fc44bafdc32e6a7823 GIT binary patch literal 71 scmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%ZSkOdMgU|}4R06eD+pa1{> literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/37ee7fab504f2d2039753d73dd0290c884bd57bf-8 new file mode 100644 index 0000000000000000000000000000000000000000..901a42d396b5128898f62b06b22b2c70753ba00e GIT binary patch literal 25 VcmZS3@|9o!0v04%!dHTY0RS7;0yh8v literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/38.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/38.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..30ca1c20ad7c03598b3103c2dbf1976e55f3a3f1 GIT binary patch literal 58 zcmZ>Y$}lo?j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkh0S|=$ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/39.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/39.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..16298f604e58d565c56b9217a7432c381fa4208b GIT binary patch literal 58 zcmZ>Y$}l!`j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhI1h#Z literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/396101a712463bb336a18f4096fc3eb5923600c1-10 new file mode 100644 index 0000000000000000000000000000000000000000..7274cb5ed0009231db71fae8344f5c297e5eef84 GIT binary patch literal 74 WcmZ>Y%CHbGa%=qn5i3=Oz20R7MjnE(I) literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/39ccf446395ef707cf92a04b5508deda399372c2-15 new file mode 100644 index 0000000000000000000000000000000000000000..974c4236d8fd0df9d712bb0ee8d611ebe05ebaea GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$ngI^0|3Y84P*cS literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3de3c5c394a3cf05620bb80871a1f10e9e36f25b-8 new file mode 100644 index 0000000000000000000000000000000000000000..667f2f2a71501f2b69634fa6d3faf406cde73dda GIT binary patch literal 25 ecmZQk@|DO-Y&o%a|NB@5Mg}$ph6a!bgChWFvIi^x literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3dee65f1cf51dfe2e5be498150ce22d2ac5a07fd-1 new file mode 100644 index 0000000000000000000000000000000000000000..8600d6d505cd27825bbe8a69b069f3b7fdc17e16 GIT binary patch literal 22 dcmZ>Y$}ll>j8qGbObcOP5R-3kU{_Mm2LM3Y1pNR2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3e34341fb51769fd9d948bdd20c011e335b145f4-1 new file mode 100644 index 0000000000000000000000000000000000000000..194057f9beefcd15205479ab1c65f3d361d07cf6 GIT binary patch literal 64 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x RvzUFH8ZM-K>YE*+008=i5OM$j literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/3ee211efb3d5d8058cd9a8c59e40c8d0f7a3df53-1 new file mode 100644 index 0000000000000000000000000000000000000000..bb86190c205ae17643f402d0d6983e2f9b6ff02d GIT binary patch literal 51 zcmZ>Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lU!CAaqss*m1z HEaw6MO5F`n literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..679a04b7741552f16f2107271c43c7d5cf2d24cc GIT binary patch literal 42 ycmZ>Y$}ll>j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}ll>j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhZx4q6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/405726718b3f54a0cfae1666f06d3cc1ee747104-14 new file mode 100644 index 0000000000000000000000000000000000000000..63f58da0e6967f29514d765df519a8db4f388194 GIT binary patch literal 27 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=J?00Ch$OivR!s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/407188676d45d6f9dd5f3c84e7df0e763c7cca57-22 new file mode 100644 index 0000000000000000000000000000000000000000..76680dd54f939e3ed45a4bb7932d17663e6dfbb5 GIT binary patch literal 82 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H(>B=VRT6ih(^4L~+Rg)C4&2_y`XfhdJi GP;CJBSQ)MW literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/408ac1a4a83e082e848c208eed903930d81e81b6-17 new file mode 100644 index 0000000000000000000000000000000000000000..934e10f0702b38f38b1066f17363509c7ffbec7a GIT binary patch literal 67 zcmZQk@|Ey)U|?|4^5tPrXVhR|Xkf@MOD!@~F*GnTGBz+WF*7nXG&M6dF)%SQHZwLf UGqW(TG_Wu-FlGRP*KX>e0HSvd2><{9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/41.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/41.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..d63608f3990a460aacc4e5e5f072b726fb26b767 GIT binary patch literal 58 zcmZ>Y$}lx_j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkhrVoe! literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 new file mode 100644 index 000000000..8e4e35297 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/413e39442f005279560ddad02bbdd1a05c9f0eaf-4 @@ -0,0 +1 @@ +"Mna„Ƚ¿ï½¿ï½ \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/41b7eaf8892043eccf381ccbc46ab024eb9c503c-4 new file mode 100644 index 0000000000000000000000000000000000000000..6b428d19e1d8c2a3ed5259538555cd48520856ef GIT binary patch literal 9 QcmZS4@|7?VU|?VX00nFS*Z=?k literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/42.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/42.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f0f25c7fd78aae73103e7cc63a701c3c11e818ee GIT binary patch literal 58 zcmZ>Y$}lr@j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkh-4BTX literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4208b7fe7ac3a530c159a1c8fd09dd3078b5650f-15 new file mode 100644 index 0000000000000000000000000000000000000000..c8c2c6aa62426046320864a69c8868615dac6e1f GIT binary patch literal 35 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=QZQ0JNS6ivR!s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/421bd1daa317c5d67fa21879de29d062c342294b-5 new file mode 100644 index 0000000000000000000000000000000000000000..6a19eb3d8ac56d593b679b31cfab290dbe9f960d GIT binary patch literal 19 ZcmZQk@|DO-Y&o%a|NB@5Mg}0Y7XU}<2$%o> literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/42b056f9dac9cc658c80092e490b3dbcd436e3f8-15 new file mode 100644 index 0000000000000000000000000000000000000000..2b38240671da6d27fa7c9648dfe5085d580c4684 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628IeCW?+!WV`5NXl>h*diw3#? literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/43.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/43.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f68d3a73a41dcc6ca6420448a0efc858b52bc8df GIT binary patch literal 58 zcmZ>Y$}l%{j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggki6c363 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/432c09281c46537c98864bc7d601780562b68410-1 new file mode 100644 index 0000000000000000000000000000000000000000..f462929668c6773d243d7ecbe686edd62ef035e2 GIT binary patch literal 22 dcmZ>Y$}lo?j8qGbYz<~$V7L>*z_5UU0RTmB1%vY%CInWj8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkiOAm_x literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/446dc91ff0ddc34c3b02f741e3f6f079a4dfcae8-17 new file mode 100644 index 0000000000000000000000000000000000000000..2ae4b5acf927f24991600909fda9df2bd6913ed0 GIT binary patch literal 81 WcmZ?L@|9o!0w*-ul0-gCKLY?@_XrRG literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/45.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/45.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..855e812da10291f9a0b563932857d0324099879c GIT binary patch literal 58 zcmZ>Y%CIzaj8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSe^Ch?U462Xb Oc`WA=l6WJqDggkif)9)U literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/451831159c1afb87077066147630b4b6caeb54c3-11 new file mode 100644 index 0000000000000000000000000000000000000000..bfd673d45aa96bdd9ee338aa4dab59c6b96156e2 GIT binary patch literal 25 ScmZ?L@|9o!0w-h|!~p;(&;vyP literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/46.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/46.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..a11978d36014479974c9b2ec30e1dc1b82b8d5e2 GIT binary patch literal 82 zcmZ>Y$}lu^j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bg4w_5c6? literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/47.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/47.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..78995878879f418a2ff19c29f808255ee361aacf GIT binary patch literal 82 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bi;q_W%F@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/48.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/48.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..d7b0df5d367f6506b92c91de2859a23911995b40 GIT binary patch literal 82 zcmZ>Y$}l!`j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bltk_y7O^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/49.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/49.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0e16e69c13346cdfcbbd4306e763a01ab43af9f0 GIT binary patch literal 82 zcmZ>Y$}ll>j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Boce`2YX_ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/49861b3d9bca3e2857d806aaecaac09af4bff1dd-2 new file mode 100644 index 0000000000000000000000000000000000000000..0648054b9d0bb5320f83f8cfbfc79ee18ca0b232 GIT binary patch literal 35 rcmZ>Y$}lu^j8qGbRA4aVVK{Oq^<3Y%CHbGa}ga9Lxe< literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4b0ab2fc1fdfc56066c5c1f2751b292f4ddc557e-16 new file mode 100644 index 0000000000000000000000000000000000000000..51ffa5a1efd59285a4f3cf5df05f47a3369140ec GIT binary patch literal 71 vcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMhMs_O3B=(cCY$}lo?j8qGb6zG4f!@$5^{k_4dA>%^Ir@q-C3PxY|a9gTBdgrm6ONdGEPig}I DpMesE literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4bd00d26b893ce064dad6e771f30541b541d43b9-18 new file mode 100644 index 0000000000000000000000000000000000000000..244f762135fc9bf5123f4dc774beda16f78d9593 GIT binary patch literal 114 zcmZQk@|B28lsGS_b(w*Iff0xqSinLpC-%ZcphCo`%1Z=l-2XlnXcQ9zLxU0nFOaPH QFA-UH-$u7RV}GIq0A!*YGynhq literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4cde5adc216a29fff2ec39e23ccc6fca80cd4a15-21 new file mode 100644 index 0000000000000000000000000000000000000000..9a3f3a8f744392c70e32a58cc5caa85c4ab87872 GIT binary patch literal 83 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=NcG0NBh9ivR!s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/4d1b64babe1f045b8374f4d74949622591546eb5-17 new file mode 100644 index 0000000000000000000000000000000000000000..983d0a4f2365a137bdc720b79c121899402f2796 GIT binary patch literal 56 zcmZQk@|Ey)U|?|4^5tPrXB1#yXkh3qOD!@~F*GnTF$Q8YsF;zdp{bdviGhicv6-V6mBLY%CHbGaY$}lx_j8qGbWG}V6&cMLH$Y9@~z+lM3aO6Y$}lx_j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0BrLY`Tzg` literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 b/vendor/github.com/pierrec/lz4/fuzz/corpus/50a87eb0c097a7ebf7f1bf3be2c6a7dbe6b6c5c3-23 new file mode 100644 index 0000000000000000000000000000000000000000..e6a919b262580e935678fd90159ab65434172abe GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEKr3#NF7+_ Q|NjOC2D2J41tui&0C9mGo&W#< literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/50e3ac1126c605158726db6f2cca3120f99b8e73-22 new file mode 100644 index 0000000000000000000000000000000000000000..5ad9706b72da7752f765a964e2aac568f88d9411 GIT binary patch literal 105 zcmZQk@|DO-Y&o%a|NB@5Mh0F628Npd{~H>BG!ugYBZDvlLxY5&p{0?5rICfDsi}cE eP=*1duAv55qbyKB2_y`b0h$0(0H(l%L>>UBf*nNw literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/51.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/51.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..b965c7a646f1fa109fa59d67bf21668b0f70ac4c GIT binary patch literal 82 zcmZ>Y$}lr@j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bu4S`v3p{ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/512ed5fb4e92818b75bd7633f58d6ca5340ffd94-27 new file mode 100644 index 0000000000000000000000000000000000000000..b2dfe276d2c9e652d54bf5c586ec5a9d162bfd1b GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3_!@#)W965 zf&rwip$4WAsEY%CHbGaY$}l%{j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0Bw;M`~Uy| literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/53.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/53.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..2ab0a6de2512a19021319339370d361a190bb63f GIT binary patch literal 82 zcmZ>Y%CInWj8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0BztG{Qv*} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/54.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/54.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..6004de354485e1710d01b2429c4db9a597e4d835 GIT binary patch literal 82 zcmZ>Y%CIzaj8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x kvzUFH8Zs`VeCnGWqG0rO54WZIqjw(5xrCSm|D-km0B$cA{r~^~ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5431cabbc58d8dc143ece079de40300c1ce6e101-1 new file mode 100644 index 0000000000000000000000000000000000000000..4061e90f86018fa5953c22b91b481bf3e4647abe GIT binary patch literal 144 zcmV;B0B`?7T4*#eL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl~nOSXvokWkRG5V zdMTsS^q8KZko66x9F(-twnFIpJXXe#>q^5@SQa)dGA4L;6PYf3gvGLBZb^C}TFPz^ yGg@(|LU8d+F7?1X6QyKt7k**&(1r$NPn3wxj^!B))kRsU*Y$}lu^j8qGbRA4YE=Y$}kZxaB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDoFhCV&Y}g{f%%IGWcZ#XfDFpy!tOnr# literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/59b254c3565c9eed2bc93385b821da897afcbb15-1 new file mode 100644 index 0000000000000000000000000000000000000000..a6cbaf736a7253a27ec10d0aa24f3ee5611619d3 GIT binary patch literal 44 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)(SgCCfkTKvfT2-9fI;Da0)rs{3}gzD literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5a962e3d6a128983afe9ea78a28cce0f40a790c0-14 new file mode 100644 index 0000000000000000000000000000000000000000..014f6a6f30af0debdd97a780bfb590e6e6181838 GIT binary patch literal 42 jcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#Xv#;$|48p literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5af52ef91b6f717ffdd805585e24806407e9621b-14 new file mode 100644 index 0000000000000000000000000000000000000000..8695d399b324f101638ad360c39949a7f582aa2a GIT binary patch literal 114 XcmZ>Y%CHbGa%=qn5i3=JUcq?IM%1OR}02uT0{ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5bd895c23369df9505dd99ffcd035dc5e897264b-1 new file mode 100644 index 0000000000000000000000000000000000000000..affcc488964e3a17c555604546dd3bfe94d8d2d9 GIT binary patch literal 49 zcmZ>Y$}ll>j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`G#bI3=Bj1w2+u6&udaKcyK FY$}l!`j8qGbjGmAd!oVQ*e*az|QU&63^Rt2ERA-*6u8}Km#wz;#n520K00b%* AQvd(} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 new file mode 100644 index 000000000..6282cf69c --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/5c4f347c3567baf700dfccf49a91192c83b89da2-8 @@ -0,0 +1 @@ +"MM@"©½¿ïp+[ \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5dd8001f8a87c24f866074c36b6b80f42b298ff0-1 new file mode 100644 index 0000000000000000000000000000000000000000..39ef02cbfe8c969084e4200339e01042b5782d19 GIT binary patch literal 38 tcmZ>Y%CInWj8qGb>{?*|jDdlbAw`6Nfnf)O0)rCQLzUoGPL5T~{{Y4_3PS(@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5ddf63d61aa38da1d409e37b301e0fe5a207a051-27 new file mode 100644 index 0000000000000000000000000000000000000000..ea34cb440c9d3528e08033b6177f44ebd54201be GIT binary patch literal 156 ecmZQk@|Ey#P+GZn|N8=^=qn6Bz%odLRssM#7BOuA literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5e54c67050ee8583c7453ff13d6eec15b2255288-20 new file mode 100644 index 0000000000000000000000000000000000000000..0a87f43f7dc7ded006b3b5e0945ade4bd4fb5845 GIT binary patch literal 83 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=NcG0NmCNnE(I) literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 new file mode 100644 index 000000000..bf8e930d3 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/5fbebd9edd144c4b9869ed4ab40c7cc3c46a4a8f-4 @@ -0,0 +1 @@ +"M@c¯ \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/6.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/6.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0cfbc601e365f93232364b895863098d7a65bf63 GIT binary patch literal 42 ycmZ>Y$}lr@j8qGbWG}V6&cMLH$Y9@~z+lM3aO69u6S@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 b/vendor/github.com/pierrec/lz4/fuzz/corpus/6046b14dd1f6925bcfe470a8484353f525db6a9c-19 new file mode 100644 index 0000000000000000000000000000000000000000..1cd81c49e0b0da9db531291694f168544beb4c34 GIT binary patch literal 57 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz(P<6s6_$*62=nb literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 new file mode 100644 index 000000000..79174b206 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/608a9993a51ec7bf252ac76b163def5f7002d2e4-4 @@ -0,0 +1 @@ +"M@T \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/610d8dc3cf4012e4e2d070988b0720285a4c361e-7 new file mode 100644 index 0000000000000000000000000000000000000000..20c9dd137d1deb6d2a0cf22c2712cd86361c57e5 GIT binary patch literal 21 ccmZQk@|DO-Y&o%a|NB@5Mg}GZh6V;l08GmUGXMYp literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/61b196987682fb64ef9c4ff37532bf9b2ac201bc-14 new file mode 100644 index 0000000000000000000000000000000000000000..d9fd8979ef91e7678a72d9e5eed974dbd34e5346 GIT binary patch literal 30 lcmZQk@|Ey)U|?|4^5tPrXJlhwU&Y}k?__V{qN8~{!f2I&9* literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 b/vendor/github.com/pierrec/lz4/fuzz/corpus/626f8b6efa3ea0f254789fe6cf52f6e52538f357-25 new file mode 100644 index 0000000000000000000000000000000000000000..6b1a5b5844ac62b4a9fc4c350a76770f1c18031e GIT binary patch literal 219 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEKr3#NF7+_ S|NjOC2BR7<_5c3>nG67ZGB@7< literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/6277f2e0a6df2ac61660ee1965c690b87c26b556-7 new file mode 100644 index 0000000000000000000000000000000000000000..a3979ce0f5fcfeb5e57fe29c3ea562d2c34e65db GIT binary patch literal 21 ccmZQk@|DO-Y&o%a|NB@5Mg}GZ28Iug08J|fqW}N^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/62c738f00c488f493989b2037d9cf1781f0bbd40-11 new file mode 100644 index 0000000000000000000000000000000000000000..f965e8c674b218d6516f5ff33a6f46637087e39d GIT binary patch literal 38 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dWD+a@0K1Y0jsO4v literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 b/vendor/github.com/pierrec/lz4/fuzz/corpus/631ffa88df9713a124b3ba6c704c0c75727af2ff-6 new file mode 100644 index 0000000000000000000000000000000000000000..b8f1f4a4d8a6408ee66904e79899ff314ed057b2 GIT binary patch literal 16 RcmZ?L@|9o!0w)OV1OO4z0p$Py literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/635d5de257a1910a7fd0db2e567edfa348e47270-11 new file mode 100644 index 0000000000000000000000000000000000000000..32aa66d51fa27ed4d950f8a7adac40d1aaa9e029 GIT binary patch literal 38 icmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dWD+RQkOu&~Vh8pB literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/64c500b5addcbf8c673188a1477e4159851ae04f-1 new file mode 100644 index 0000000000000000000000000000000000000000..6c6541ba79787771828977d31a017d6585d7ff42 GIT binary patch literal 124 zcmV-?0E7QRT4*;hL0KkKSzC~1Q~&@LAAmpyA|NjWQ~*Ek+z=oDl|xkVKxoL&9*`cO zB}{~RDWlZ%n4Y1K^$n*SV}F#i(Y8Y9`#e^V>q^5@SQa)dGA4L;6PYf3gvGLBZb^C} eTFPz^Gg@(|LU8d+F7?1X6QyKt7k**&(1r$k<1+sM literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/660387064a3cf4cb81046989929abe1b4fbfc815-17 new file mode 100644 index 0000000000000000000000000000000000000000..1bf5f59afb271f1bcd67fbf5bc329a415862e7f9 GIT binary patch literal 51 ccmZQk@|Ey#P+GZn|N8=^=qn5i3=M=Z083p8ivR!s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/66068a7e7bdfd1038a84aeb3dec6e3cb4d17ad57-2 new file mode 100644 index 0000000000000000000000000000000000000000..1a2cd7c6d79c283c95fbabe626d0a03b09827cc1 GIT binary patch literal 16 VcmZ>Y%CHbGa&Y=~gBNH7D%Qp6qu0F0IgmH+?% literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/6bc138796e9b80572a6cb1b4a7ba30c97c22359d-1 new file mode 100644 index 0000000000000000000000000000000000000000..e1fdc112331bc4a7efc663e09681430342ec387d GIT binary patch literal 46636 zcmV)GK)%01T4*sbL0KkKS(G)X0|3c~|A2H5p~Qdp|M>s^|LQ;g|L|hUKKsA`6YlAD zc`I*Yq>cap03SdA000000Pe>@o%ZE+&|9wQdZK`RbC%m4%MG;|_Z&S3uFrNr00Yvf zPytkx3ZMko01IFM1MbBD=%4@+NF%Ic3;?8kv>bPxFFi;`@6aWAeqKW_jHKKq5loTBl0MJoVC{aKaD`r6|I>_9? zM-U21B2p*-P%g%l=nSX;C@ZZ12HN{%DIf&^prud%0HT0U0)POJ0HHt>000F508@wo zs-*y+P(lKPiUD5i0011Q3ZqJiAt#e00)2o9%b#m03!C@cI|cX z^ewwOgP}kG00jU5PyhfF00000KIUddWzUy*zYj(XS zo#2k@&yew7MfZI4zGbj5%K6?ETfXnR=e?&s%=R5=*Q$L!xO%M*Oy+NSp7(1bO*@-! zeNVjg!`Ha__?%a};t#KV*Ig4ehLd#HZe5%WSj~3RyPd!h+Oykk-8A;c00%OJ&5)RG ztzZTyDyoWr1qzf8ce-*`#_b&`~O?by^sztE~1O3vuo5Rh`LsGW40~*GGGf zPkZB|RQR@KQ$s-R(QfYVxO>gByB(iRb4rwhNl&iel{AKY-g)hu*{4F9(z?@gEw^V} z*k>>R001Z(;r99-PrD}1S6tohk5Or+g!>WWuW9l?;k?@!?(**4fMbO2WQ3SjEY|`r1R~S-8op4hizH5 zZJVK|2rd%0M72}MN_ly03Lu262{qixapuq!IDEzDy6p7ni5vE zvAVms$OAwqHg4?L0noVH4FKD=8s*Sk7t5?i9^UP%z3b8Dbba^F2hWYOH{EvTcYP0f zCNbRm>+Apk0000!$C&xIS@S)4>^Ugzy;~{NwKG>SO?}u?-^ zYoHD4qPvZGO1tfYRDJWhUER|;dA-{3yPL<#rBr|b$7zpvoxMJNA5aw?>zhca6KxH7 zeeN~f01B<{6~4WFd+yyc)y>^ERz2)Q8e0majit0`DFGT1=yEP;Q&{Xck1STz7;T2u z0ZJMhd8O}XJH_ForBPGT#_v6DbiBKCLidMCgSG(i-E2rb0N1CX>GlKR@1~Ri3i+WN znwxeQcJ1!PQ?Wj}`p3q7?Fqc-TjRM6 zn5%=UyEmMpdvxS-dE2MDX7*z@x!-N?yRB{&w(fn`nmcoMZEyep9RL&n4u-0(==*Bv zZvlY_pIQgEv|#k_Ub-!sYV3F3-F){w(DUYj<|MOax&;6R<#2euGN*3La1^9T%+}iO z?G7oq_keq?2iqmq54P*O0YFdy2J_0R%t|Fb=eN7P+2?uNw>fR*#qV`Zb#{ty4$bDO zS@+O4zTdH@9gy?Rx_gJm2Ww{7>!eaL;wXwQ-&hMT*9zW5v9^Y43I zxLc>YyAMoK?X2w8RUHV{rRmw7cYOdf3(p&a*_F1J(>865RH?AlX}fjRBv5yydcX(UP7O~WKtd4^K!6a_AsGbIYMG=B28i~j zr9DhE!XXGkAxx7fFsGAIpfmshpa1{@Or)YoH8jK$pQzf1^*u(Or?pHV%|J8&003#A zlSqjP1P~^Gig~FX)FG#o9-sgK001FKh#(1&nv7G_#Gaa|_>4k%O{xHB0NR0|2{e?@ zff^7H6G1Tq$iyb26V%C}pc-kDLBHb&N`1#6N(x9-bgUsyHpNx17~aGF{`qHrI~gyj zvdwoZg3&ol6NwD74zjpMq34916hk2irb(PgESOfcF~~?RU6+Jfu&ro_tf1O(h&3XD zOK3n)QEG$%MKuyNA}Kf+Y~^tXx}p;(jvB<1E0mF{MYQEv)d-qRI;99k9!2g#dD?m- zhi-AXCUWCU;Y?O*WTJ#3Sragh7jjAcZquHMh9OM}p*Pf=Zc8Ouq;WWz$gNvhzISez zAxX07SyNR}Cp(w1@#M-VB6EUtDnQ}1jOcgHj#O&QGO9??wM`PZTrA;CO;}SEPFzVK zvJ<5!L0yWlt1FZsh*V+3%!UmPHCrxSoz5Y^^e)OO#w+dTUN!PVjj1R7ny88|`%;L< zJD>Z9Cc-R=iQbh2QD7?{PkW@$MMOq1O|(Htl%lLx_p{RIf~E?)P6swCG8C0D0Xb7T z{QqUyKbQHdPaeSPA`+6|`R_w0$0O61mojRIC?F!D2`Gq1 zE>|F`A_{e3ooDp~q9_XySchgZL~2<^ z>f!aj4?xaTaus-iUCN;OLLu`igSb==-6DWc0{8dx_3!ELc=X?&re|KK9SA$D<3!It z_UE12-{LQmc}tkTcKP*uU@v^C9P;DOSD$W%^+#|X{1^@qK=A;1)S6~Lt(UcuR!!2a zx_0SjUDkeH;6(u>5G;lCghT=#|C@aIKz&SGBMQ(6AhPT+!##ezaOQw}zhwSLJMY=N zIKf6Dhiz3DkzTUbEk-Vy*+ya?bn?y;&ks!JiVfDo>+{!~oM@g0n>#q4ciSZui1~k= zdzHG%AzK>}4}Z?5b69k`j=K1_DGJ?<*%7FHI_ntjQa-J}>X)(3(D~atswfZPL*WcP z=t~vh*t1Bf>&CJup`?3GLiNKEfuT~G28tpO75{2UYaY`vASic8a!wGn9|&tHuA$P={xuE`ay!)%U(TBBFIC*OkMIygrwKea zXIMJMn-b(<%x`hJsA$EaRE4M@2s67ny9k*KJ3}W&J3}Z@#HFZhw(%Viy%MJA3~BG~ zvxcwZNW3kXHntA*rH*qr*|+L_n?JG;Br%_i)*ab6&ZFl-EIO~Kh{QuV)ux{<=?3}b z_xGNeU)}QW#6do@z*6V-Kw-M`5Zuk95YX(*hKv?71M2s=x5QywEpr+qH_T&lGAa&Q z!4bkgJlqvzE}?JUQ-_ir9WxM6NM;}vMDI+xP48ODyBb&K-3@0YfsZY#iIU%+z3fGcRGb@x!-P>GA7}n*eq2$Ff7mh$nbejj270S!{FXeMb@FlD1YT zR0lDjO-QWX=3xj*2o6s4TG~{0?J_RE1}W_eEX7r%Y$p{f$_l3IPM=76A3F6f3YD>l z_bbrF3#>!g%)w$j^n`gQG>E6pu)!EGGHfRU#nQAG2nFze2}ZyZ0E3!{VUfw$W?#&x0{{Ujw2&Kuzlz zzcb40hUr|`oF9iB>6hb-=G>l{$TBl%BSRa$*I6DgvtN1UlFc#t+Oxjf&tFM_6mUU7 zW9fS82fgxKC``yfOCD>{rf+XNz43~P>N!fVb-Ha!vTD|t-gq(&#J(^j4$b`uiKg?h zPl@iJ_Um4oqk#-uh3H3bJTnf+LvTXUf%)kR#nV|>mZx^_2hG&tsv)4_6M9TWT}529 zEwb_?{N^{tQYX{663pDl>9$2s!(-n5W5Iuh_&sY?J-!(7?RH>%oEs@v6Lf{+$EP{C zf5HpUDs{r!(1BbN%wnezGh^vB$;=~J&S*WtIX=Fg=Dv4$EeJ9lX$J>0I={n1tm74u z@SG+pb@1;9MEp;62Oi%KpMHaH>EWJDzVqp$>)&DR+$|*hz z@DH0^@Iy5pm~jRat{I*ipC$|&^Q5ozk6y~U`_6NPVLQnN+=mYm7(-0EyHX#GKQCLs zzGqePtzPcWm%;{F0FA*4ZMSb|f%MRJzgF#~5X+STo5oCv?U%aI6O1;2ik%4Q{8RHS zw=*m8z3svwPFpfr{ExGYEjNkYfjK&YqTg@r@d6k@77RS64~@ciC*JJmKA6Wf8pIn> zzn8q0sV#jJ=&S?}6Q-NA9`dE)>I)4lY1jhusso4;9!e2=QrPYj&%zN##Gj_csY{&^lP zc10czAd|4Jx?$Ax&&xn9(Z2Dl;7HlGGsgOUarqS^ckF}3&qgbklgSXHxS5riRp_Y) z&`UDAAu=lUxUR%?wRjR3j*qC0^B)}(bFj00pCz+Nr6Bh*%s?gS-H&(g7mmAWAWY}I z#{-v^cc~j=3HS8+< z@5p>7{P}yv(>E~7rsc0Zzh;&wBdV95%}1|8w%OkDZKvsheC1XaF5a*(_LGkm4ChOy z^q%{Hf-!|grnl|$sm%InqrS!Q#$-<0E#~|y9ph9Wx8)4oU+*lq*?puzp{++J=&GLD z==l-%uM3BgW^Ik{Q>5^*TAs z^SQvy1-4Ojtl(p&y!K-b%yH@dc0Ko29?i-mlaqSeGiqi8%$f1I0DG_cG-QYzrt%pCm|%f=}2#(XTVjM2Q)+b+R%Sw29X2Y!qVBDni# z-w;$mz0_`^b6C7{-3U6A*g_37Uv)Jo&N^C%W^G*~9wgKWvqE-cHf$gkBt11OGo-tr zzUjAeZ(nqy5p|qlV^IR`!8fS&+(xivw6ntQF{gq( zH+7@tYf!_ZYVVyr!fot9;tM-#mi7BE1l;q}v*A-KdDl8{;(XhtUxU$dC$f+s$jkcE z;F*B#3r=Eh<9%s&pF>sc4iVB=HwRC|NS?d5Cw)kn7$h6}X1!Bmsqb`#Rx+lwhhtu{ z(VB^EtAnef+9n`-nBNr!+oo$*;{-eYd|AdCj>NBIU-7m)J()J`F8ei}MV}1JZqnbB zh2)g{v+Hk+(geYNpB3jt&L)lc-l)BCVZ$7un=f~zy8XhX&n#bi@ttOBqs z0(y4&YPIH9htEQ~sAI~fx5^Y3&^nnl$MWrA}DoarTi4LFDJizD- z=PdL$adQ%&Ek{pwN>z#5CK^F+_P(_Uppe%P)7|7ipWY%we)(%I9=>YFN|wSOw+NnJ zpR0IJ9)p2}5j@*DaTn$qu6M_1S&c=pq#A4992*#pw{|W<+2rb8X|u?0jW6@$i;xjE za$n}Ho~#HYSo=-i&Y$im8Fz~`Jq7STs}YEwl)_y)Y5@EXsaA?f(~R6f1G8gs~-s{0Fb!?fd@6@;!cD`~3VvAwJ6dcRoKW zcGNmoOhfNH`WIiu^ZL8*VbQVtHIWpZ;oR~y9o;;T;Iq^YMejgP^SAY+^$5v5QXC-< z-km&Ot~=zvr9EA3`@M$M+@&Oua^y2_-G){Ejr{OGPuu)sU%%f&>$g|LPv6(=v)eZ~ zFQ33wI+GvxVtBNT5VzM z4H4;EiwW3PUtaYpAd6A8t=Sf!N)U;m!c*n~lTtJpBaOt}arE^*=g;)J{Q8#%oXqsW zo7_H9nY5^%y0?${Ag%ToQa<)VB>U^QH%Be~-{GZvDZsG=WRE)?KN;QO0s3c*{C}6n@;y)AANl_Ow`uIoA5V`z%|AVHpG=Z} zdk)9HKY!=b>-PFOdp`X+_DFs|)uo0_ous*VBopRSISozg$L+Ab;rH#)@NdKWyng?` zyYDN@3O|+4Zx1_vORfX@-TLi1mOuyJvHkXMH=}qM*Qf7OjmNX-Ug&=S8K*H^blap>tC>+9IQ#A)mP->^le6;_*4ztX?q5 z{gc-=179;UrucP5o>H*<7=6v#RpR#Tv4Sj6C-UqY!`h`6my;d74^+RHS-=tLF_%bi zPw4pe^xS-XI``H2WbMPQqSkQx<&jZ2R1r`t1SaSe0Qo!|bE7@=&cvXf!#lM9*hGjP z@YpU-SFhC=U7_f>yo?v~{PmgK%`E7mcJ21EgB&CL8qg+3(VATKtIKT<^m2E5h%YlE z3%z>}j(2|cKRi@Vh7gmqx(9@kXo?w)-L>!Q7gnC1;U8^MD8UPnkQgYSQCJ~@4A#Iy zZPCq8OuXwC{FGqi(a%ht%5%YK$dWZC(>t5J(Xi( zLA8UgJvHyCz4Z@MsUO$0D|^N=q>#dcQmRt}q3H>LkNHL@=0GmWQiR8z=W=}mr9tn2 z%1^C%m-KO0W~oUaP#i67uQ1`RYuj7r?>`^LzZN*6X@vLo{&(P<=7LCE==!}oUjL2g(iP8S10n9==3+w^ryJ~ zU13;eQxgF{(%89v9Nc7w^EP{XdFcHgug~N6_pQC?2%=My1B79Om>r6tM|xWKG}k{+F90H~M{A)b_XXku}Z_VAC7) zs#O9r3L{G>1CrlI{;#+G{pVe;`(N_?e&NS&hui$0?&<7l{JQ7ot-q}R1c>_d9geDWRHgu&g>Xb>SmU2mx0M{r`?%^A)-3L6<4Ml%$ z*B%eoFFT!Be#iVj&;B3o{@?7re|cX+JYG{j*Zv=0r`>LbNDmLDFVY>gEg$cXKHoj{ z_cGys>)$)YceBq7WP+H$S--cp#s5FA+U@-75}=h(HjmN2%< z=KL~jz*GH+r|{}+n!(;URfp`AFj5x_34TY}vvkKRKJYje5P!>hO zkRKxt1kUf)&VC{J|J46a<^J3MRbs>M@9)$=kLDSJNBV!i?@m8(0~*crKcV@~3?JA1 zf9|ud=bzj4$o@I^BgX%b`u~UgKc+GJV|>+)>HfR&@84tW+nL6|8;KQFRQ2l?Dc9e} z+IYRo?b7RqnY=d&ZfFpov>b7__3!85)0gUb7yhhg_gD}*mHkE={eR~io7?>vFhN|y z1-+&Rne%k#9xl7N{W;gt`op+GP!#$>^LSg3{8h)<*Z*LW{WaVHjg&(B?;gJe#P%=I z&8!)~X#E^Fr2${B=V@OM)H?S-yHXQa$Lr7Qk^Q67{(raoI{s7Z{(sf-|J_4=b7nut z$LU}0A79=-{ysbG`tSMy_iy3h#y^!cFjl-hjeX)0&$lIkSJ3m@sP;$h2{jIC=*0- zL6Fb|1F3M1Vf2*Ln}q8Ns5KwAOa2;kF9Krg=r~Z<0A*g+y>imF!ubppL7D8(0 z+YgWIaf;Fw}u4V zR6XNmhOX2J-ON5ngO|Gsx)^lOINq_oMme8c&IyYkNZHZcdSz5_C*w#EevYJmj>rYg ztexd4?P+}*CCy@kYd(~54+u>xC>)*T*OeQ1(1FzEFxzH#Os?o}54R5}4B=h-U^+I* zfrXMk!x&++lPA_EC=vyv*mIR05tbgLrSWGmLFh*4CmpfF$mmNFSz~EB;mvCErV}ku zcc!$!AP|kLPubZQx)>tV$XICj>ldWJ1J?dfh#--Z-OvIB8waH!lhr&jZs>II$P^g~ zojV@1*G@M0{<3;Dn+fyr{n^^*%iv<$Kfr)7nDjILrr+*=K(C+K{mVm#fA@bk+>hh? ze`omg`PWYV9-q1&n!z}gyhEKxDusT#6bL+SNmVPO<4^QXk z@BI2-d~&z&y1#+?e>;X$=lJL8uOE2R)St?Z?@+qq;Nw9NDHDcgWT=*P2yxJfhIt+^ zdWlR|bgrpQRBB>5Lq+aPVj`(-zsFJtqks6_6G-O(J>WfE-`h^>-Wi2wEt}N;ku0@a zY{JgVmK&jfqe}A6Ez_p2ien59Pi#gtYRt(0JTzix=Ps7=AZw^V>oT#XGkK~RLEeKw zXI?eNyjrX@%dQ+=mQ=LVUlqKo(=HL^DfdmxoJiLZM;E(Dbr*}-_SnJY%7R1+y15w3 zzVjHNOxo4P0k2PXSf$PAYYUC6XHK_b^kYwEEmGz1@zv(?p}7n|zVu#=$f(l^Ra%jD zU|(k}jxWt>COcbyYTEy5fw>p#^TXcfZZTL$M(?Soof?H=q%@SdR}TW@qLF%p`D-W#W0M=MAkt+D7 zs;yPA7scBRgLS`R8q#Hl9P63I$UHSlYCU2pSnl0aTh%LE@Lf+bH!~Uqwr=heZO>g( z@NdS(PXI>7IuCMTZdmW7&1PQs&Y*PB)6-Rf^6!oc%A!)vfI~R{Me7f(S$tg!;D1LOdo~HhX!V_A!y$ zV?vODg)tg&d6{t`b`IxY6O5z87O|dC)l^nFo$I9=b|Uwz`pbtL8hLxpdo=7Q`Vpf8 zK8SHmz{U+{)7JAx;@6jlBPn%|t7Kn(UMUW0@842(s5LgngeeAw zBv<1c;?2FNHM%atw4AhFrK*awf+UCxj10XK<>d87TI`-E%*G|AF0lO*n4tKaN0W@+ zPnb!RuWa=!A$I*kEEdFPbo8$#`)zd?x|!E!S&o`6u4LD<7!qfh?$H%7ggEVw7%{@m zS@Uk;o%CbHnHSq3>*;yk^!7Hwm6wCJ^_zLLPUi0&+-gH}8n+uh>+xb$)1tC)@EZ@m7uyN?$h`{rk^+rGs;>khU@ zSzVbWw>R+6XtiJ>ZLU^eD$^z+Sq6bm>u~w8;b3hl?Du!vO;&Fg8{1tUIF7qF7%;e> zh3xmU|*RS2BL^XT`8YqMvyop-06z3Tb)%Eo~x`XDY7jGn4Y z;yv}Ih3glCdB9o3S>x9ksT&!`-x<%n?e1Bl#D&~JGMDVDQxT%OR}D+_yNd`V4J?*= z2MJ~5`E>y}(k0Oj+`g${IkQ-$O`dNXG|1nC%)Z4;VRmLNOo?v0%q+h~kB=OKV{Afhdz z2fj>~5=4q#AkyvAPDXjO7VwTAvgDe;J>Vq`X@pk`oLh5m&b&V_l(BEvt(?er)3Dd4 zkiuL^Xnq6|-q_;dn&SM6rNx|3#QS~Q(zH)kn1Y!CL2?P_TF}m9P|IPO-CYyw0XXg_ zo1Nc^Fvcmg7;b5V!|~1HlRJrIb(ed?wK&9~)}Iw8JnI8-zOFeiGB@fm4UkGChp!b^ za=jeO?$J*>I(oXe{BB%1jF!^(_n^erjMa^jgLd0@ke<@rZrv^{iX?nb?_=M+eF%u! z8}PFVgz}%6W%m+&s3+O>AR^_xZqL89wulPv5r0tSi3t?4+o1uGf(`lh;lYH1N;#+R z4_4i2t%&r~kTYN|G0%)XkJc}b5i!Q|lO1^%;Z&4$)BSR(M>MWGe!JdgZ(W`XvbRxC zzPeTSIKWUiJMS@02<&eT;WScH0tN%V;rCHEkr)k2gja?f>vVf*X z9@|0he+)jMk7!UNj2z|fs2nzODDYe-tn9oO@k?1E5u5nfBkM7LFwLc+*BmnhW*lIQ z-3lV-TFbq(My|A-t!~fX+WYv1`s0Rin{w7ByD7q|v(>QA)^)ahE8+j?e08GPB#$0M zi-AOs7RVYr#_G$;7~?yz^=E|etQ0SPJMBA(iL&~jz-#$pENIDC@{$VZ~)0kskMWas7=NM|my z*8|S?yNE7}Q|3P%PWoSS)!jBNOJ+P)uCCQLg6$}tkO-7e2-qSF7a}zmi^Q;G)M^WN z_0!znPa^YHd>lSo;~4Jo7JN(d(F_JKQqlIDE$~86q~hSZZu-!y6l{ zV+^kuHK{_`-fL#%s2@&+>kaBJH>qBTg2Z|MrFSO~)z)FLfAFR4C$-sFcIw`+6G?2Q zptfiG$lu?*wj#sP4oAyKcFNlYJy7h!gfS+Qck*lM@z!n6O;E6R@_u8z@Am74hb?d# z>uV1FK>o~q@bN1$(K1iARfMghYeYZX(_OD?(dS4Fn@#YW+by7>D_aNA(H_#0E@(3( z*zX#9X8kZem9l5HStM!&YGukWz{ivQyb}uuhWC`%j@iJY66+iFGf5LG$8mTbqh6}L z8;k4KuY@L9V(=)(ws(`!*NZG|?S@OeUGavpWCb90a>o0K+<`a9~z_(T6M{tJDt zsrzugMZIQHV2JSA-$Z?%qU3&Q3zyoht3Q_JS@wMxCFr%jYhBe zSQt!g84-Hz>aWJ_=zi<+K+)}v8rLf<<@QQ+py1a^x^}F7WxzTGbNl@24@eTe*flK{ zxpvdM8KrEcYZKl+so)nG`}u!Yy={7IiAvvtu4R3=3l!a~wxr)|{B#Bz@XWASUjEoI zvyga(s7nj_N%q<|)*H?AnNBRt+-5YJ@5_yC+TVgLW<8Gz1L)e`#^=JG!6U}?(vGXX z!>mhUvHh8*s|tlgF(;C>ki}+k@`5Ab69cl>!Wc47Ny!FrH62ql>iiHEO}J+&XX%?C zP2Tp$KhYt%4xgyc^^HSs2m}pqgN@_JZ00!L+g&+%qy` zYn&aP8#JNAk_o1}>C%b@h;&f5LkU3M8 z1a6rZaYRyvfI;Xjr}XhzyWENnm8lF$v~vstROGXv46x+Mun!*F)2n2oZ?ZZ*+$qMG zY>Q!s1iuN>Tw%&zLY;20x8<7|Q1oH$BL!7_Bg~m^dW=Aidye8Hj00&SL~7(KCzo!X zoQ$1b!4Z-=y0x@mh(9*pqp400(~XaXh=Tosy>rQ!&bZ!AYZ4c6LypF;H**jUpI8rO zD6dT209iPyf%Q7L`-&c8znZ_fx#4xI+NGu1R2n(b6xVB>77C7{b~w-{9WPmAL0Hhp{XRE9RDKo--!Mx?UVr;u=@q)yLHG7mJd zESp(9Gndvgab05%TW)h~Iaga~Nj8$q7EM+7@*SW$?VDBWhaD{|{yKA?NQjzz;B|+S40qG96-zy4^C2m}nPBJLL%&JR;Bd|$AY0=m zl+xJ&h=^iu_I%*f%mheh-b7Hq9T9>b;|_8Ki45;Kd?FH#CG(GZ30_*(ey@-zzHbS0 zXCmPe${W*Q<>jteK}kadMzaf!+W*2g*UnAm>Y#Wxd6+udL#AzML_53I{MPX&4z+e` zBM#VRelwA%t5Xo&yTZOBdye;4T@`|^6(@Rg6hd7E%L8HkKa7_c29HrCB zdF{_F8%h`J*$Nt%T#Sw&s}YOv*uYdd*=4K zztpY_aq4dy6gSkxta&0jcp)O(`*nzBd%)hTX7cI1q6vH zX>yyG>JM``)oj!j|#0c5$*qM53{*iWB#VJ|9;T*bH)s_<-dQ8qTn$=reCoPL3Ln=xc(BjN4m;Y zVR_W9%MwAc1dbPA<`dYRPlvZz$546xSu>SPch&xE;vLF=FMEfby8C#Tn!i0iD;8otwQ+hEK zRaj6ODqjj6x${B(5dj};#IYOGoP>rtK<3Ce!H`*f)|t;;s{e2Kf7SVpbM%ZPJm3y} z;Cqn~{SI5>8u67Sbqp*Q2ndKYZ2Am%aBNTHfEbAxkysZu*USuGS_EP6TMF%Tnkg|h zEEd=2>+u}@GVXiswNp6DRzepTSaNWa4+~hCyiusLvbbOLl@WJvJumMZs^VVo=l7dk z+)c899kOQhsp7uWdsEjT(fSFxKd`B1Xm6vn)j>V!Fh^vp z@X^wakm(@hpm&n@SZo4b^3LM?YX{mHxKcfCJ`;cF?^Ym73NI2qDNH_3<6>kV6(Ucv z5d@M87HfB>qT(f!05ZqFmot5^hiA`gBgr_%xMP8EfkP98Cz2K5FHD$kxp&w6kPbc@ zq^&6%8|+`%vUEqHK8!GcNXNFsRqcovhfNK&=_Ew-an6uNpVu>6wSW^*o4q+=&UT)e zjBfONy_boWn{+xIt`YVR-kYk_yPrA9`$5I^o?+yZtTYjHw+Coq@lApmozi#6~+H`PKyxjDSMuj))~);Pl6Pd|~c7hVog#e8UPaEXQB7>IO-a##)Te zbkJ3_x@-nonf;_E#eodnb&lds4f8lmnDO87OFhsG(-(+K33QPW$3-`M`(ca+E41OX zbo1Lr>Z#8^D$ogw#OI+k_mQvVI>FW|Erym2=+g(oe<-eTaErm;c)6)mv!=(%;UAzf zM(=yS=O|%3TKoE7L9E*NelzQTU!Hi=H$->(d^&>GPvvY_ii*xQP4B+ry?&|vcF$ac z?XX{MPvXwMHlDk=@MjZJu@O`jH#xd0sH_TUDSUc=uJ-bgmh%bpHtIA2aROKy=U2k4D7$WZ9>f zu^%5Wu=D7%=MmCSZeC(v5AmuMWZQ+vBv&p z0}+4I_{TG7P5NHyH3Yb3BfY!b=b|bMQlm_>UzvGO(C&iy6!LC^iOox!mzMO9>6?Gw zwYVFf!|Nnb{s#k-eEnR_8nrR*=Wp8BkoRAA5KqbkAPu2>Bws~prL8~9{95;Rf&nBF zXCJPn2tHEAH7Jg9pVu*u>#@8%+;Y>58&p#hnMP+T3<>&4FVrxWX4bt^_6bNS`e=3g z;|!#Lfj))-#+(O8faD$RhB_P0yQaapxY2M6QTuKGrP;Q9VayQ*A8Q;!R+^n2Phx?& zkvaIM@KR)3bT{t!svD zqi6nYqsi7d!?#1+1EuHho(Ng#jz_On`)%HNem`w(gHT6hgQ43ou;_^*+<7g%V{`6D zEDk>Q*YSNNvy<%yVY%M^o+qx^-Qrp;)UP?AccNJWZHy`NErvbl)lSa3m<{!O zZL>3MM(?uZxgHtfz5d@3B31U&8glQ;=K!69!XLvh_rx)MR;bK02-g`&IAcQaBBOv} z;YX(R6_DGfcwBax!Mhiikc7!!Wtjp*0?0SohM5c2C-j^LpDz?12%J7?F>%|o18xeQ zPCkY2X9f=U{P^>x?ifAMJzRfjW6xAI#d9otG(J0b4_h#>>===e5vR)~FRrw{zk?>d z_l7Qz>!0b(@qvZtyse+dd)xPI}%i z?v(PU_v=#fN8m%n@jPMIH~YsPx30P7_v@@2_k6xF9IqMPu*Q5;>saZT7ZsdZ;RAti zBT2`7xMBR`3=#mIEA3gX{BJqXZ?6Nt?u0aduNd%&;8sVdm$x$B(lgv}vKb{1{*?*t zLqImgCo@xwi^$<0Or0TBWKE9L79!xWlKznV9dc!=5IKdSjd#ZAlaqizC>CjO%nN`) z2QfUaP&bW0R(T=VUZvbg1Koi01 zqfcz=7_NG*@A*6jc+000$UF6>?oQon*O(0*F!O(N)OJ?aSY2p4dM z((OLpdLjovwe-?7p&@DALn0|aVUE||9tm}ZOu>o^DEepV2|A*Tx{mOt7YrI@unn6O zF8sR{vtgV$&oD8{rhrHFX*?2oDCNIK+;=_kL(Wq8wAc-Mhr6jM;pVx1{JaL4zG3qD zfOE9OO`E6CsQnywyi<^Md%$sx`iSJS5UxjJhkuD11AD*ewZF%^>(1t&{2_N|=s(&* zi?>B4z46?~PV5=q1im*5P}tXzH{uy@WMdGuoyO~h6K?T~zvr;K()}|HruC*}+6+Jj z*IqW0{l+YUe#`YAzg3sKz~mAM^FA{HpV&Y@5rbKF}RC z$+wRsm8K0tjH%`GPXpd?&X)flqkU$mQV{4n-?R1es*6rN;6o@w4D#$_>4Ep|+#*li zV|Qr-2F(t@pJv&{+pKK#4P8(5>BjPFP{k3R(}Ky#Y#;0U4Yxmqmss^Xfg|cysJkg# zHehY@r;w4S&yX{`ejy%Zf8M^Q4SMjKJfSU4`sl(2&AeVdaZ2Yyd(N~*!WYBwf5^fk z4GUw7ybk!y06@mn87HPsH4vPRRtmMg&A-oy@X4|GaG?)L2nCC<=03|DNB2K|>iN^Q zl{ho2WFxBns;{PgjdVX%dI(@QhZ?G|v96OMFHV(1=(L41nW)JS5E_gj3Yzg zkDAj4m5H3ca*kveRs;O{5EO}M@g{scd)&M2HNwD=a`6(%Gz11{{M4qP61`I<9?@%_zzeAh;X z23HGR;oV_$>YIT${dhCEcIcv@Na+tF<~rZVC5VV+Rx{aK-fW$*tvf{qRHKV96LWw z`=$p@-Y2@bj&{fMi{N6JPoZh@#A7xRL3vKR0_M^WL=6y5#yY^x-QQsFzsT>qk$~cx zqKh%P=v6;(mBq^5|60rD-$Sa|B=Fv^znQVU>B_AVM?@f5x@6$b_u;MS`VDb&JcOO` zDsyX>i~4B>Xv1g4Rrqhj?;ZM6y!?2D_0{o#(GKgHcgK>vD0q%qiw}<6dhB7bimupT zhqH)bc#C4hc`8k=2|MjL%B${hcuV&6_+_=m|DYhV;^oKs?#Ci)ngI~uFGNkQ_@roq z3ewT4j+Omm_MbCqiv5#0m6RiNWBA-77a1()cn$}7o6vxZv)iLg1HS# zD~9;QDe_q?^_x(eiCv&pm`prlp)La%vB%Edy;v*QpX(2afz2~&{lbp8-6Xyo8gzXr z9)5ejL!r!#2(z>1Ed5?cH3RT;;+6aJ^lfLntM6Jzsz<5{Q^t~MYb30WE0?ZvtTtfL z86cWckmG>bb_5$VB@aW@daFJUeK|KGCk@>yW6?VHri66eB@h!gxALW(W>x4nTNPoe zq;AAZ2}@Z0=PzHWEJya6v5~CAUuDSWtWVRtuU|L&U-tfQt-2Wx{Q290@Chwt#O%uN z1_xelVq~FjGx~aqZbZ<#Lxz9TB5%unZ%!p!C6!CT9X-C-b;mff_Cw_jD=`ZqDrM>1 zInGJ?sLB2sY?1nA-DG?A^Z#L9$vj$3&vWOiX5IfU;Jkm5@AbdUAc-CJ*Aer}cOxgp zsJjq|eFUZhyi1Cxa!DkSqg9qb;VFf-K8=5=Ly*e;NHiMT%<_k|dHk zA-N31IT#~kkT;ki-qLIduy9&`PfUN8-Oh;{}FAWU$ z#9M64|5B@4<1+qyXY8YGK37obrj{YE6uc}$ehuz`UPAUSCpqj~Ikx8`I0_-qaq zH+{8)TOQg7i{ax0ftXhq?2fn_%R(BEUT)6AU;-NbAJM1&)C4wQ53e?Tta+eW-8@`) z@(mt_5(>H_ImKk-Ir_hS(4cNH&09rX+Pf;(<1Kct;J&Z8CDz=I zb8o$x_O#RS{k=Cg$hmaE_qTraEp?8yhk-h0>p@nzch)Cb4Enb(1+sMg9m2K!Me`V2 z(?!~BXWQ;a-)B!4lss=U0h>*Yfsk!r(_O1<+-ga2=rneB)o*t<^oOl=tU>Wvbokz* zPvZcmQunuWJ@HL9Cb{(7kMiby8^PHZXMZ419DdynyvDjQkS`vSw&CU1GsjxUb9?lB zuXp5U&!*eYt#(Y!v8uLf6VL7UsrMJX%WpK-d$V^}!3r~L)9~QQ`$2DVI*okzH+UC2 z$+A7+t^CR$K(6b)eDi*A=RI{O`gY&*T=x<9NbOH+*B7IbgHMvFOL-x`hJ0ZYKe1yAnFkIPkZzgos0X6QB8o}wK9L?kF72?T`8Th^ez z8L>*>dOyB#E^@VA=MlUqHu|0M#|k*%xTq=ls(jZs(IYbFn!&~}&vKe}&3*8`f11SK zF74CZ$D$wh5x(%dOQ>y4ll~^s3VMvUx_OG6PB7!wx`Q(U_q`iqjRxj07{&1vSlXJI zG&_7*AHcqE==Rx*J&O%tv|}B^j$(RbqjxVfp<-Rn@!M-vmr#6MDgF7O$C4yX;Mj3| zyAq2xq_^go!22TSaR^=9BH{y#hw+6sjb}E@Bw*T7AHNfj;lCIhCt`97A8WJcY;OCm z8shKF_Hh@&mbB}m2(w!tA`SI&KgNAy93r*?v%0x%H8vXaKIOP}o2!11(47TLw68Dh zxz9>6@?ea06-L4=^pPOZ_x-c+&awTQf;#vvYs4Se^pv79&6%EHekI5l6yC88GEj3@wsQR&(Nkl6vikdgH^{~n z*VS)WP}A0PQp9^+m}U01tnPeFSjtC*06##$zemi~=Bn%aaeYL-H0jpVkUkJ8Zn}2`Ov`Ukz;$&xuMgMkdt8n4Uvk~uK9t5aO*aQ<};{?J13$BwL zRJ7sk)3A1SZ1_wvlxh^}^kKJaqZO=x8z2EWJ{Hk0+Gia{j@o76FTtF`Tl%R3#yCXK$1{$^S1jfd%; z{Smy^^^UiR`kshq^1~^J*THVSLDgqOV4MU#m(gT=d%dxFWF`psbEtIuFRYt4 zZLL24HU4euG~4RO0tjIpD*!*407uO+HX!+-q2BMeACt^@B1=2v-0~G{iUsC1@{A~K zh0k}FDO;wSg{kV4-kwPgkttY^&Gf@90A_(ntS~@=A_hVy{O0C~&1+?g|2_ZEEFjx5 zJ)cSRbz@>;>eh?svyY|n^$=y}_GRpd%(b!{ZRdBr@zjap?`&iWup;hKc)Yxa>w=`j=ILi$+pg3TjplzYvSy&4nn!WWI;56U6QQq zwzL*JE~X0u%k7TX9}g`f{1i1TJ>3FGML?r$<>K3G@vbAv^DDWNn_e~@hZKhqoJa7L zspGqK&GhdwI9^@}cV;1@*LMC;v={a~aEOhmm+MQvKaTwaSMQCp&0B`MakDZz zyEj0ln0sbW!MLTlz7*)xP#~rSuFV&xr8Ag;B*jkQ`_O3d9C3h?9dH8`!y9Nui?cxYG!T1jW7G<_k8?CD76V!8&*cDOH$9L z5dn3U8G&|FW^Nq7f?5IDY4yq-i&iCCD z)*j?Xa*MrrL8Qs!GJZNv)A1pI*yo<~; z33S(%?tTH!i&_Rfb++6M5eFwGuJ^-R&b+IQdG=~EH`U&cq8p?!_nrw$+fTf}JT25r zt8tHo#v38xODjG?c+KA45J&^5pw~ii>$LXx(^$o76u3s>fKL$pb<+}cxw_-KP#ZP0 zQwVB0f@rs$D#`hckPHcPbA0u$4vus}^Qu!Pb2}qh86|`1((HxO-QczjXgwBqLix2I z5&?2Z43NU62-+$bW`e3(E9J`)Z!en zu~;>=8SQcTihz={kQyDhu-b)^Aec?9u+?7IH3E&O+fzg_&$=UCR=Bd+BK)BrRqy)e zk`6Vd_S*H-I`LItjJ{x-?LU`W=>zShpAs`qH94F{jkC$qsAWMGBR`p9Ix=pR%tE6B zJ=IOpH0-!CW&FKLL^Tr-YH=HO#%%t@~z&|6)qJ^W#ctUlf~EIk`!qN;~) z+q7q5OD@QF3loY1vIIHn&AW)!&_RX`hDdV+ltlJlr55ZSu9|zNN5z;9usu62ls>Vw zH9zUEtzC>?8++M!`h`+YpA~|f!0jF4snLrYQ0J92dDZYIb<=oYapBoJ5yNhe4~E$ydZmC>KQk9^q9|kcZ`UX} zIoEDI10qQy3Rh%$VBoMGQ0+ z#$!jZjGDknlKR$>Ke-fkOcNj8^DEX<(2;vK|fzYV`km+p|O-x!HVLj=2Y zYbnc_l-_-k%Zpw z-_-=k^Ly>x?8g_p3fGXT-xQbA0k&q>Jz?%<=@72Lh3QU}@g%);Z00{| z#K@*J4rgw|{#t(ftwHKj03GyL@Lgc90V}3x?MBWO_iSUYP(^Jbtg?|<9pg|3K zzijb-r+>pESH6Piu{O|sb6TC}=TXD%q3AnvXMib<%jhgR(?kxhAq6(R1_&)qyfB5xvJs=n_;N`~wBEx!(^_9S4lwKtzH4`dfd zZOWGD_nKRrxQTI_y*zZ%c=ycHHISG4sNxDB>9c(0+gQ55gyE>VxaD%6vfwzYxOO?k z(}zgMe8j!)%f+0!Mh?bzGRfgk=_uuFxcpA9kVHZXfv1c)C#o7N55jWCoS zQHQ?M%eI!ie#18nTVaElWFHChM$@wvFVnal)?yU-l-p9AIV)-ivAb@zFHuM>l_U}} zVppSX-eD857TgwSCld+WB?YW)BO*Ru=T(dKHyWJvLB<-gxvIgxBkFTG+FwLV%tc%W<^2YhD&S ztKRJNAdMYiSdvSfQ`Vy;K3P5RaeRr0YNs2Agy!d^aMvBsc=HVYTrqK!s}+b`s_)i+ zmod%6>M*jz>HUZNFkvF?W~~sKu7wa07WX6995)L4GG~+^3(MYV?=*5mqMO z2<+I>817wM!ZsOnSYjtumeY2iDA&4rCBG~^Q=Sc(^y2B%U(LVIih7oVX6o+WD<%2H zmB_&t9YR@2>AlcBEW?F%{j@^-l{JG4XPGZL&l2yQX7aEtw0-#5B(}0EU&Qy9#w+1i zczv{B!67qTy!!K1f^#q)nPt1kd(D4=f_*8EWJXXKnZ~gf)-!Pg!gJ{B%}B*xeGD?^ zYU2>Kgjr;(p^{?OY;FU)Jn3dWalIvHTyT>#JV8WB#J|CqHMguW$wjzZl>zt9s16Co zO^<$^nA%`hpC7yH%wWFD@NNN-SP1E7j^*xWv;O*@4A_yQ%{lQub$80dofYc3y|ir_ zD@MXF;})aQVe*@KR=LrdySsA}>6@EwHO1#Uz;U7KHF=#d2sXt#8$C8dVV5h6FX4fn zwtD6H8tXF{mEFg5WEnl3FhE z+F$n65+>?TL=P^lSpNjUrJ@8K*^S}oNYXNap@-ZFZ`p?f+mfaK zh3A)e>6WX9JdH3LxSDyI5r5g8l#s7igDhpzCr27tYPECf;b(ZhuF$sB*6Ug@!S3|S zKddvFt#&%C&FcJR-rDub8-!W*VRy@Ah5EgbldOErja;U55J#){=V~n!US9*O>O@^k z?{G95kE;F$H`@$t_TpquxPj4(-Ug<6LO~JtIXA?3MG&eQX0hW2YB*vB=mu7|4@;98wuCkvE$RdR3yHfR+*UwKqERHjj}uCCSt<=W}dkAVhFtK)5j2JOv8nP7zD6ios7gY z4w!M&ZOV{m7|0Gd#E)I4*|rHGkLa1J$pDxk`ME^rk#YoAOfhr1M%kDZkYF={#D(o~Eg050 z3S%r*+R>wl@78IZ`6G85U^oo2EZIR1S3!deQN*n$KfYmP3CT!d)zy+e}3Z!v&u&VLbDfqbiEsDMI$aNp~1{O_{VLeF*W|3GzcUa z{hRw8^Ti*6Jx|DnXz6y(yQ*|BS}EhEeuSMIfZHdw7*^ZsT-M`Va@32bo|C8GrUs4m@p$xxk9R3^$mD{wlbqxi>S+-a3 zhQFgyFV$JI^jjKU$jmn%TFrI$^k`!D*}pO!w(6=cWnf4nK`Ab7S}F_Vi<=P1#(|GdBQC7KMK|JY|-eM%)>Eq z`iK+7(m#v zKNY*N9n}?OV7&Ml&%8@ITqx0k2ZsfyF(A<$k)w~DSt@v1nI}C_EC!f2kEVP&K(GB= zeKIa71%->JPS`qx6D7R8bv$YP)!0UpF83|fV2ha@67&f@2G#soj4V1)KN=UY$6Z9B?_J1V} zso6){7polG{L+^a%D`xNN4fj{f4dBlBzt6w4S%_YkJmpxd5^{uZ2hnwj&-D@!UWv- z9pdDip5y@ZgyC-0Ii}7e$;p^gbJI%IZv@w`zMx8}UZPZd%MBcNx z{d2aS@f=Gty3Qh@rQL*^Cj9o<{X1bk7bOd`Vvph|*~tZhdeFFLkm1|;rT1@=FZ*ZP z4RyX;Z}DF90+`KN_R3M`*7MlpBC7Z6e#QAV&(g$n*yZrxAq82WG*m@91;Ly>PVqY- zw^Q|h6uZ`IJBt>kQXx^?Fif@DwK%i_q;RKJM_iB-_jwU-py39wBd-~(CDGrw4uZoY z0WqWKfukaH+s7w9i5peMSA=+i`v%I!#m@bjVfZ$YgP^r+p3R>pUhfJe!;j>B%wH_< ziy$442SCq*AQjQGoqr?#>CS&QyiF^MSSM_`c6@K6J82toI zvQMo(4k+iF$am{-?R0hGfLl}%;-7JrO}2bOp@uXO1?j*=3H67t>=W4=+0#u~1hZG} zGD$bPlzoRvU!^IsP7R0kCv$ zcNO$z=$>aYXX8qXoHHh6Fck%1<)`=3qy0`Kf2Ou1Wky+LHK9sYu9@r?f7`hf(Qh9K6r`72;lGD?6OGD$tl_oFkP+Knf&Q* zz0VTtkDNu2B8-(mJ>0XezT_EzsQ8CABkKQkD}nWY|Q*WBt%rH+@aqu!#_b=fp0ihG3Ib3OFblr4EQBLS7K$ zythw7FnvSg7l`+F&Avy(UfR*tL6h-?)J-Gy*fk6-B>#QyQ_a^$aD+Iw7Vq?Xm!Xzp zV_R7&{Vn@A&TTR6?Qz@b9pPEV$b^Y0*gm_z!di7#+oh8EQ;StW zZ>%Ha<59@oEpje5>a!Vt3BG=_i_9SNfazFA(H+6EIbf=R7PWszrdOq*o|NBjQyab( zJF>#RF4k$%EFQ{vnVrgs9(i1^drQh1-fkUyOf;|;su@Yq3%XP>JaajgdHQ+JoDwMy zaDZpP?f;>02od(0i=Zdk__LO-DfEUdBtJrk`By? zC6~WU7)eEIjL-9U{5WIuP^=Lk#{D}`b6CaUhpCT~f;%t?lyW~t%}kOV9v2>=b=+R2 z&2oB=PZ<6Rfn-LDTG_hxkg$_}kPOLCslTFN4-&&4GKu|Q>iy%+U)4a|h+;?^qLHfS~QJ$kW4Z5P7YkkF;?#oCF^sLwrQWAVH z-Dxq|^vcy3ycj>18E7xt2tKb<%u)Cq>mKA-@XPTB=Ktd5+3B`%_1ez?!bYgD`1~y9 zLkKWtrmY>HG@$$Ahn~pC!Vg0esn_M(E3iSrsZc%xS`ZkRS&{nAe8ko(=T6wPV=!@O zm!wv8i@3U$#ogkWN^&TYOJ(C&yGk2oJ!*BVPmH`M!olq)bd<|MEP3nXu zz*!-LGeMOZc>w4`Yx-tJFl=d-a{t*oGZ9R+fZM6box3A)StEE6Dm?r3891ARmS z22w7e2@cK3+^2-@vs1(q;8VVil<3Tv8Dgi3?1Ru-)MF7tvo(B=?9NSy41?3}I2hM; zG(SL)FdT->KXKWZaf7Ip(8T}Oe`5A}#PhTy-&GiPik9(Vvd;5~@o-oRKGW`~Y zF=lnLtQ}pauZ%uxPX4i-R03W`KW6JYtH!Xg823T660TlC6BrbZE*PK6ISf^u(Bi)DeoVuw3~V- z`u6G{tF5uvY)>}ritoiB7$b$4bYAuCX6TmMVYWM#4vsd$Ndt!B8oa?iqUK`~ zr(9jLIHCr%^5 zwLq8&y#73yH?DIeU6~g~!(Z##xz1}im9LTSv@V}Mpkg08>HS^^tmGVhJKAQvgUX*1 z`>l5LTUl{9F1uqT6=FC22-{-NGH^h6USnL5IHhz!n6}X?qT(W^8>Icl zSbV}4Dy3wB$9SIbRZUW>FqwAa@W!HjrNActDcBghM#DY;M)%3x|R+4Cb95IVi5(07=~r3+WDyYq8@rp&m@FT42or=WDM zT%Q@{hpc}!@*|qYnj>*Ic@vo>T?@Cit6^N#RN7#L@jvXbG;_*lanp9lcKGX>vdadd z28%F2)IZog89It#e)9CXLP;AjhFL#Ah`GL>7sK|c++TYQSSG}e&X9uUd`##8Tj}ql z<~~*IZ3GCWoAG`kn@w_h-zq8c&34i1b-m}AL)|D2k)~p}_cA!t)S}d18Qb15dlqsJ zxTbu_FrPSXOy%|8c%VnrwJ)1qpRG`lx)8@P9#V>Ap*j3CTaXyTEw)%eI_=aV$>_A+ z5^|UPM88t+<}D4r#Ni!mAl5Q#P=9*$6^Uf7!T0SgD>FeXT9Z<#?{XW`ijj-G7H0B* zd(0pHxyCQdZvp;|!L~U*AHzsD8r;vM<0&{^s1*k1rfQo0rm6GH2M=^GhZ)8H(REV5 z6}h5T8H7R5tl&!#$WQ-tXnzbcoWXIq@iXeae(*0H$fI*Cdxb!HwTI!XKWwX#dOEt& zY%t7Q^SdGd?GKs@HI^!y(5$1A1{xIpc~p++%pfXkv(! zgQ6}Ic0-$_UkQL#&KTuJCA3}AhWM^u(&JW+YPWp-nZ+!=DoiW*CbN7IHxBoHYg1X* z{5G8vvUs!9aW80Oj2<2SutA|Dr)xFAfRTK8uz zx*<36&GwFV>e%TF9XimyiM}HYr7Z&}+VPAVI_f{ZJ3|+6vV?b6LrYhq%jb;wm+^+nw!X=|CyOrrF=kiMjk4_;T6^F8mfhO%y~` zilVl=?jMx>o^#9ZSM4)9-KXq=5SKb@{Q{43$bpI4hE9wf!&;c9&*KW{8dUGzKTPbu z(^l{pk{TJf@U?f$$~!N2X@uKjF@ZlNUDh5u5oZy2Wb^&l9bA|mSfqp zcX8o&8!}>Xo3-J#rID`EJsY|SyW)a#p^d-5{i{;<9Ft#5K0e}>chJr8lXd|ex#Z|YFt zwn#s#uc^PiL$g>j@%CUd5Db5^!!P>z^@?=kr{brN`>X+VA^x`nsX;G8X8v?O#*GU(r^@%O{jgi}?MFS^>EXZ|aL1T*Pg+^--~a#>^9W z20z=aQLn{!_wL!SCv+~s2K9G$)&`!coi55GLKCzyZbi>$V=lu)BIi~=2v^sI*owb1 zm<_bq+GEm+BkLK5&R?L>ePx^xAlkLY8cxDUxdNJkAG0%yEH+u!91>qgooG+scj@}x zNQpz04JNPS>g!!z-2NHWK#o)FnTO}u+2taBTJtkK_s#50@@1ilyCl=3VPFDXJfM+# zSBPP*)D`|eR6MWRu-NU^16luNGI`^A_3N&vPWWVYhw+Q{{MGdMT8)>J_trt=vKCd4RBdt%>_7euKC2zXC36~a&YUfS-&|vVa2S4xt1xBv9u+bn~Z(^ z`Vkix;l9U0dyAZ6Sr49u8?1jjfHFi7jj%wYVo4VFzGK_mOYC7~XC;SBoReXKEQkXR zt?|Oab8p$Lhz>A$ODBYPSQvXbvOG41q~G@!28fa^k^+@(jIWVU38T$o_>T;Dxs8~| z>An~@@p;D|#d!CPVR*-+hwH5L_d>6a5Jt9Z_&$injq+~$?rV@!GqCn|!v3#h(A&a; ztLqxYEg5!XuZ&6#&t6pvr3ew?MeXej{#TLXhW=1JkPorHoDLF2kej97(^{Uo`Sshm z2uk3f$z1zQo9F30;*0zKO7I##HN8&-a7~qFxE;LE)CZ(F>zo(K6H4_qfX4Ee*cpcl zAmJP-;WrkLMg_YetFlrB09gzF#?+&wf9L_`rtu>NDFu9mAME{u+KC-z(-* zdwe#c+stR&SLn|W4zO-Sdz(({FJwDH4booJBd5`aW|fFnx8grWaZ0C(mhn6$HUb7U zM`$u_LSkOOP4d{$8rQjYxL2~g=`e>s*8+H2PWw$g#d=z(m1Ri`>`MP`E8k)dFK7V} zv6*y!ji>3^f%IB?VVN6vnFHj6474?#&|?vo0|^Ua<~^j}$B(BGB?3dH2M?}hmry2^ zy({36Ahvs^Bj~j;{Z8OP1u4^9Hc+gbo?^kXvdn5#yrq!vvRTN>1nkaV5@MdBa9m?T zGjq70%d5YCc%hMS_GtvsLq@}zOl%*d8>9Uq@%~J?K3aO)Nt}Le(X(K(O;61`ka$Se(VkR9aR~V@x5=LFn zqE5dowG4h9jt&3J-@U*g5Wk{^qO~sX$v0HMziLE5a>5;x+YB6E>{owSGi*P;YY19z zqAb_?_=G~GDfGCwzv^s4KT4NQ9oO07u#&_HezRhQk^K%aw596emjDIdkgH#6m7jW!+2hksRr20cISgm=33 z!vubvY|YCv070?m3jtHlUmS3G{Vk3Ci+tda%s$#QbRyy%~ic! z4>!G68)yYCchq9Q34lRAUyw0s;6k_1=-Gn%_0VVUjN-li$a*Yn?1s6#dLu$u#+O9{ z+Ud4N8=bALJD@3Z~)Ap72u5TcsXjy*mX zZ#8a{Le>0d$)J^sceec^^kC9XfnVNhe}3oX#bTeQol4`N-%*%C2_7e87>T&FfibT- zRztb0#_%K1(y^j6snOyz*`1JIL^C-e78+)Y-hE*aN6FWd7{0$v2Qkv?bys0yV83VZ zjdpL@5RtPFbZG4Ys|?m=VRmf&W?Oo|E#b(iBss6Aqv zSU^2088s*mr}Td1WRJhULNN#=xiNa!a5qX;NEyZQ2^#9{Ot)~Cu1nx?S@{{p_%jmk zXK1;_ZekmG6`E{S&N^GzEcklHb2;7_vb96}Ba`)>pqvtZo_m4>m-wxV?({Chv-{Ul z2{g4fy0k!k_fMpRT@ABGpFR1B#)eo{27FxQb=)}DeC7E`R(-P6vQiTBq$S7A@>*DU z>fVhIEu)6|^9~^-5SC2C@1C_XIwIiw`M)=49w*+FNVE5m6&>|n zJ+yl`y#Ed;7%XF0mxNRhY*7)_dI8`sh%~JTvAuGqo0qeiV7*pD2O?x?ppnBnb?cXL zFcp{EZ0i2P))nMrXP}p7L@+@ka*TN*E3Zp1J>lO)t=~=1oqB4)5PR^ZldK1CS`ft~ ztccuUEpYnR-f@v|!4rLS%^G1%mW^$rztg#XNejfmju1xYqAphB-ef1pc%U4xxY`YK z|35ylfgNSXUx|nInVFiHHXCv}7?uWzQ}4XsL|}qt+0NwL_jx`zT(413mtRj{S@#jX z_DcRfZeB9O0I#(9Fk38`T=jSzV?w&+oE)*Trqnm{BaYx|KYFY+p1y#-4Sr9)U%h+V z{L==}M2~bj{5r85Gp|h7d+ozVp8JbpQ18X&JZj8C-b*npizLM{O5GMfwP&Vz!V>W6 z@z7L9z*}}$AbK}85ngelGB-jS(*_Y~WMrlO24dL~C}FMa5LFEij6W;q)1iXk#@jBT z$@f^FSHbizj$n-;Vpr4!()y)}-_jY{GTC|awj@FHk~J&TEHBGjl(;^FVf+{V4XIq; zcztF!qxGC&IKUNC)3L*-#WKS#oup0LG|X{Z%v{su!?WU@@kWF?_)M;|``uQ^VX_;) zjSf%T&SZS+&w8d9!@D*@P7T-(ga*IUn3tV8qGMk}i} zIDsH1L67IJZDITf^l(IeeB(JH2ve5#v@a{8(|bKMzo`>nBLKmU&hD^%s?dMXG;GNX zN2Np$A(y`yYosH;s4(;CYww-%Sn=)g*^|A0PbIy&t>NjBA>9)u(o4b-T$9Xc+ZXP6 zJK1r&HMe{|ZRW0J9@S*&|BFQ%K=ymyMMN?kb*LT_HBOFt!$9$q30}}=bQ~YY+rgaI zkrzT)SwMf$)H{7%2eK614`P@IkobIK{; zy#>Yn`*TJ+BJRt`i+hn9*u7Wruafv5P_Kfb!=r0aL`r7g?K`u+y)_59x5uRWw$AMm z7z84c@zMmp?;W1RlDB@{+bcpNqi?`70)*fdoXFse|T-GV`h*yVi;~sx!uCI8w zZt~5n(*m!~z3y&tBsP=5#-5x;wGZjqL;(ZY-IHr$7SLAUp*~#hrQ*r6Zm%N+n8sJ@M|sAYZcqLG?u%8o$OSLs{Q4;2a^64pWn-!oh*))}Y0XD0_( zH|)J*0(RX#+O3b{dpr9;dNX&WQa=AK+S(r4Qj7je} z?+Z(O`<+iZ=q!~;eQT-LYRxNqg0BA^R*UU$g{2~V6KBHyV!dEOZ=9RwSu$_J{cT~d zyh5C6;qHbc$%B`XGZNBY08cI&*UpxCFwLbd=QQ;?!MXJJdiS`Dc`=pUNunDgUj3mL zK&$Dm8`TQk4bbf~CwP$Ul|hO!Xoh7~+oznUc)EK%>R`ddW$1=C&Ehd5A{5o-UQm5D zNMRQh+P>WC@W#Rz5eHtQ*E740^`_|@cJI05mzi#z%no0=WFF<#dV9Vl)8nIl>T43t z>C(nGI$G>K<#R8{exE_{H^;27JGmX-ypp|6_uq`P=0hxcz*5yB4ka9;j{hjWl@P}=#ZXbi&^9_}DLvNhW^@W4*T#?gEK zIgHCPA&4qobo#2C+#SfNW=6h^XE67LmRDax{uke+LkGicN+-xAhGTOa%(3B6476Nb zs=epeCdiuG-yia6z$~5Yk7J3QXWM!R?e$of4e-bsX73fOCS-j#XTMY9-i>q!ank0x z&FTAWL<@@XphAP=Oh22>>p;ys$0s_wRvMh|4lg_ks-j@JH{4KpIAr1ZQD@9k^~A7- zxpQ}8j<=b@gwq2^EyjLS4!f#8^~dR!$n31ShWGE&YL1%?;o426YQG6qMt_ubeV}!t z-ya%8Hl=}A_Z_4J5Noh?_0kbg}rf6e#YoZ;L1m}qH^LdA{{SykkmI}X%BXk<( zNYmmRlEdML+;yeB`B(Rt=kn@75yh`j^dGIyou&gMk;#oEFw)P+wX?ixO`@>=gZ`(j zY%GcPoOkc6KbvoT$A4AFpvL~a^T-24YW?9EdXn&488zz2>@l}wy>21-HHMO&-ri}#A-O5=xN&NRX>RwN#YpWA^`>a1<2JLsU`^VW zr+OjehG6jhF*(D#A%df{ketR-WZ#qb(@}L)nP+Si9FlGv>Al7chyhT4zRZk+rV zIvU!4t#bUxZkZ1+M$?Z#zao>(vl;8W?xzQ)T147+4Y^E-7dH%%n~jDQ++PSqh^3*+ zwng>3;xf%bl6YRbO1fYq1fLI^>le7*Z4&tJw|?hWh+T841F-k!Q5eNHRN?&Uf&>~M z>`tRBr>AIGo}=4`g_c8Qa+(~l!NuV;IWwuCdOug5w~L$aeQ+RPXKa|fJHE775v?eQ z>6T#(7kP^H>Km0*IqBQdcYBBLZgmli!h1VvGd9Do98d~{*j`q$%5kJKUi}SUj{EhR zl7;d?-$nzMWdWX90VT+}3zO(Ru`$+3XRN-wip(~M-cY|cc9b>!M{avg#&F8E7rOmr`YHyytQ<2cP;k+J~KOYxzH^Qv!<(~sR@*ciRr{(xF z`AkTB$IN8ms-pVA-#ypPU$fEZXyD&c$BNS@9b(f$0lTN$FltFC#B{-8qpQZ2ESlqm z>gJ^;VaK^#co{7>(^Yi?&Z9`l+>6#LkwW!$4t24teMHd+L9BmB#Cq0RFN4!r#`cE% z-ko()mnve;?7L+dSFVd_LTUE;Pvq!9#(W-V8D z?1&lZY+m7=!roS7j*nOGr^v~II66~5Og1XM^LoOsQyVSD;g>1=u^=TVXAK;m(Gu@fv9M{STe@Ig)(&ciepJh2^zhFfm&QZ6CW zsNr!XDjGgyBp=Nr}oqDr6Ry%xQd8+4F#qW~)zX5&c zJV=j~FTq&S8}wcxv(e}F>u#fUWE;O0s%v_2hhSSbx!c2G$qbMLfXAtMoA_~~K5IEyRS@R||?u*IABXzPW(jjCBp8lKpAClQ|s%WIUi(qQeuN z6R^@VeK138vil|q3%#;)3{KAmhB{HmDFspa~U_oVDMmatUlV8%F5Rk&c}7FPTGYH zJXL&b&0`kj@LMMBS8#E*oNtbFxp<1j@un^9Am7%)n^Io;40=-?a*bc9AM?I79+UU( zWxGrX5G?*?d6xQKRtwZ#`0XbcWG|G|oIC58hTKg&GMIP_(r0qnF~4}eIf0{7iCMbB zdUF(NbYkxH1$M4NHpz0_rbl?3M`aSF}Rg<$|B<{C&`ep?#+`f z`67lh7Sf8qJT@nM$${%;Z+89M_ScV3TsyqhfcwWx%(qA&P*!gryaLiSuioS zV;3kCLd?z-Js|||clyB3_^)}LgNUfUJ~Hp)SmOQo&EA4OtVdb-c6Ym~l@X-wH03@H znRIr|x48Gy{vCC#X0;trG_S6yq&R)O>eD9iEc13_9Np?KiL38ILx+KTZS!$d?nG(E zUOwsG)3#|by#l%A=BeBR(R!3yn=**gnnc91Aj>g0zLI1K} zI>qd4@W+vYwDC^XVgiX_iipCgr=}SDyJRl$L$A-v?}IqEbEPg^e&hVW{&6*|lYL*+ zg_h*|-e|47B>OE5L^yM}AEu|WU#JO)K~Q2?5g`5|W+VJGAFGht4XVD`9dj4vd(hwQ zU7;koAd%e6o(dQKr*;kf1TZ1cK%65UQwN9&Lqq2o`#`I{ zZ-tzCpV?q1jCqeG)^MHi8#UzX|!o zLSEN(^SD~g@{lp+9x+V=>Ny54cNyXkMh?b0y4*2hNTTerp5#kirf*-MYisypn&ac- zI$t#Z=a=x|O7`}RN`Vb(gb3@U{>_2uGf;g=b=8l*pXm#?>OwAVCareMckeRLq^ zd^*yW<4=cDovRJI(sGD%@ipAtX{uLKHJ%%cpGPj9t2tD=_uOYy`qXrLjhE>8)B{d^ zHJ{1xuQ(lDQc)#0p`e8b#EL$pZ8&ChAo-6um5r`;7Y6XS+~h7Lv5InJm4<}nn2Kk7L9l||JPGzkT4jGd90I5x-f zVC=`fO`v~_F*5gi>;%2AcCF2Nc4Us`^l^1p!yI~7_|zG~=+JTyhsDM(O+*$yA=?-E z%w$gQp?^_lCifI|96igV*#?zfq&`nZt|+*texgGSutHLOp`s=t@|f#1;ljd{&c_3t z1kc=DXA;y?A{k-ds(cum?(q-NoV9f}$do5O`*_xN!kw?LI~kNtqM*t(Ue5RJj-lT5 zb&}qr)A#VLBT;w2(_^Q*P2C?; z$F6&8Xxrxz(&9 zcRfy?|Ho=_GR{$V@2j^tYqhRJ-`(JU7;c{U-au{hrs$-h6MR|N4XP)>jYXTeH;5wPgY%L_T8A zBF=XCt7(HGF4%r{@!Gi%uW@yx+=ih2Q$HANV<(=xyXzfg?E>$prwSnRmu~vSo?@=D zH+F0CTy**5D&BP1F*`p}xjWZQoO62~pRJ4ej;|MK@KlDs=i&a& zUQ3cTYqRg?jRbv~KU^Pu;j2VUa2cx-S`6)T1&+(j7tX!17eY=e(1!IA+>6}Bq<>Ec z{@gh8HCV*I#oEA*lZur5cJH2E#RuQ*?@7J0)=L+Dd<6j6-4D&_wF$aI<1=$HwaT@g zZSm&J?ca*KM3%4Q@p^1sR4}-h86`P4eEf!spxIU_GZ0yj`c6g0R{q&QI}!d6zd)OxG^oBF!`;-BqVwJbj#1j21JpFQYeU~93Y1H9zH5&iI+qLLMU-fyMvZG0gQvYVuf`^^V& z>h}=##Qnxt4wE!y+iqxaKH0g4_H_xfWo)gAr@^!7d2|UEUmD-QkHjldp3}JuN4E72 zC1ZMs@mpSN4+uI<3>=IxUh%T&7Dv_v^n z&0ktzUkq-`F*&1~j6a$6eFkMyq|tFs-xD%}`fcu+uNvF&*Y=!<^7+>1wpSU39{&9( z4}f6y{K#2a?ivHL@NOvM9Xv<1r2A*RwAwsqIJ<43o-tL3XuVHt@=TmN{dE}3F1eWJ zdbqy(T@LU#8ye%x>)Wve8(gli!|~K&A2CNxbCL`(K0AMQve4+KKNr-vR3~xjHnl{_KFEBfbXw}y zoK2pfwA6mh!1Pp4%Zb9al!v&zoO=$Q51z1M-MyXHYBBMPgwoiu5a)aDqJE=O5=tTQ z4SmxH!(Nghq1rPa2v3{AXs8aA@gppzkb*D7wU)b-`DRyiS$!xY-ojxtq@aI0~ z0o-PL-DpS7H!B#?LPC9DmPz0iA^mCxi%ns$!v0zWJNiOqnfrrYRon>{u_^q=yesst#mZIv z{QArjj}w!AxU(x+{#g_<^ziDu>U(G!ofZI+8lG3~*m=X~xegMjanHhJx_o&f$;UX_ z=%MdQpFfqQ0{d}(-si&vSetdMKh!54z4LkYx74?H1RgY0rK5#c{rO^<5MSJ(oR%}_ ztFMeTbR5BU_1Yf|M0%fj&M8~#_OE!v?ZF-o7vO39v0i3bFY57KD|@}alUQ8yg`?36 zqv)8(!%EWHBlXq!v**~m?Mn39uGQ}>Bk-c&n<0V~j!L)jg>R1Aaf4?+f9RMF6h(*p zIma(eeYK@NY`fn^Y?;TV=X>LGc;gHDB1cR;Hb}c=slJ(^8pO6^6K2%XaNnw}7GQz? z#2|)0@n+`|g{8UZwMsvmuGerpA_(sIcL5-@)BE3!8Uzor5ybsYiyRKeYlSg@f_<=O zE(ts${oZBW3~|fGx=IST2c-I&#xyn!&fL97DWs*hM^S4 z(I_{onj`T1^=yA-#yjcCgcaY$C%{oQ%7zzU;Mw})%ha_-8hTCKRdj`<5^c=05hReu zg%OjASt>KP8NnM+=3^Dck#jodI=h^<3nWnZYYp0*GrNVnWmN(wqCp}JldpxX(g+qK zqi=WlHX6L)>EEEseClRhhg2`Jf>sNk6|`b^;<<(_Z_v9o6{3$lJ85NxTqhk~?dy^* zHv_GP)PZ)G@iibkAXcpSf9p2wkiB#l<8Ka8(q;sYY_>+oe;3yOO^<|ic3TGbbjN9E#nAf5-8@N52(FthKachG)Q1~( z8)8S&c2`-+R7nI^Gl#wJkoNry<(tCVDiQ_M5rpO3VS>z3_sASC3B6-3jkN|*ZL)}XM^-qj3b`Gf6b zhcWU&Y8TplrLW=P2NY@PkD5TASOxly@zmCb=F^|QmvmwxzAY$jmj}eDE#eO<3`!FS zK$EX`hINtVuZ`aH*jAPv-F>$+&+hVuYw)wdl1Cm- zrvvhBSEQC+;xbWK^i^l9v4Mg^I4E5T>o%yQAm)eYUVcc+98pqe9GgqU9_v*eg}`0n zUi`kpz}L`RJS$5=61tKu(A(YP1)l9VC|;2LHxwc^_bK^fjxK)$ zK31Dr(r&wWF=Shgm~uVCLywZsGR(+FT*c-4mKBY;H-NeAo<23tFV#nw%bw*7Ikw{N z@9pRjmu9#5eRZXQ4wLYVYaV&!-a>~8@A`Ef&Z>wwUUa$2YmBc!xehQ}sga`3aVYGM z(T9MdGp|Bo6t)yhGnswant>$P*@$0mBZQ~RNP|gt@9f-p(6+R6N?0AU60F%_g2LsQ zp0!U|I7`vNy!OAsa(!HRELIP}j=!EQ;|}gI*FJe?gVdG>@!+{<)g}QqaUXIOApIf3 zX2g?vbpj&99ho-Saqa?O2q=MeFhsY{5^M@&7M0EFI3gL;8+0&}2l?9PKWx|xnCe4Y z5#+eAu@>rD$B0SkyZlCH4Pr^Q3ZEPFxV(QDL}K!ot#e|p#0fxACW*sgTdiF98f_#A z2Gbv!s2oa7X#&_Kqx?T{^$5r>o2(@HD)4VFc2fn@1^!JAYW#dR67JzL z*BK92ZF3Q)eI4=^nRV*vfA5z@uO=0jNn9g-dMNZaNWS*F!Fo2I-aS_8?|lwg?>r* zpv1wnsBJ&9ooqGS;`?Fko)-vHSDa#rmfpu)Pj+@>7i}G=_92$6E{1Lyn@{Py22RzB zrH4>1by*pQ%_0_5|D#_KF5Pv#<~Rr=(Cv9?JdnPBo6 zydW@;mqys`XVGWF_MiZtZA3vrbgJRnUvW-wgI z;a4)7xd^%hf@}0&+w?0>dR~hmqOP3`on9<7=Rgamw|$bHJU_e%J)TJP}nx@_!|{?#H@L?21}oA^n)xFnPG z%6qu>zOE#}z`xGrx}9Fkv5xNLdrU9f9MYN#TC9@@?>ZBBi3YQPz0eotFVtKNE3t-d z*simvwZT^on9WBc8X+Tf#jWVSX$DB2nESB14?l99|H=;<<r!IhCEBZts1o_p@!bU3Yn_r@j#1n@|5S$k%I-6*{(R7X8k~-@Puycp z%{w1#`Ja6&=5cf!vN!v#A8`<5wb5Yao*}qZeNJIT9}IeoY%3e>o9jH!HRdD!6!n4f zLA!g);(fy2Kc*ktjj+ywwCvA)4P2Sr<1G`2AFrr@VDp#x4AaR+Q*L9p1=|pihI0P9 z4q8#PW|w4U7es#&1Gy+7tBV)KYWl?DFdjjEmvPO{u6?$!f)_GbmdoxNpx)n5H7Wm6 zH3&|PEW0?m#zp%7ewnlCZ!0prpU*#sediVa|Dni33I3wuap50J`DFPZn z_QwNtrPOQp_=n?J#3+BOf$M(eKc}^K)>`moEH)8KwDs-O^@0O2c(OeT#+2S(s7Z z&CDHK^^e-WJH&T?sEv8u;=gr+J%764aA384yMQg}x9KL^)Yu8xv2Bm)4=K^uz>*u`CpFW$fj?(C! zvhLmxp=YmmVBG#+ojB|tG#u~acc{15^3tE-Ir)yvo}jr}fLG4D&+qtY`bBq$Nxrq~ z`^Wt(PyPiYloARV|H76W<=o4lSeSVv>oC&H@-blNHNju&_j2m5cV~7<%Q%kiI}V#H z$bhFNQUT@_6me8{9IKou63t4lQlcWg!tu_TM3PMutEx~GDXi8h(k^l$l$D1&s9dAb zb7XPd5W6r--{uA=A;YWKT?&YcKajv2)66LURC&f%D&7emsV?bJgcl{j66 zz$`mX_584_ulw63C+AWXY)L(oZ;94zTat1lIy%_s`0&VkWLsH&(bM4-8JGnCUf zy9#u^el_^~pB|^4ebDgU@~W!(SyZKXu=P!&Hr%3m|2z#d zNkd{`D-$=*dGpKT+lIB=A*F9ji8dp`AQgo~WQ}E(7v?fS7W(DifZl(0POYzvq4WGp zcsu_MuBTr=nCH8&ofKco*AX!ktQJbjg++mF3mB>mO4_ikAIInR|1J3G?|S*X%>D7( zJxopikUl#~QO6p;P0YEH3RU*&{laLW86ooWZ4HYaDQ$tMvRRU0y1V|J#6oFAh6r~|ZGzB9{D@ziM zG&B??05npoNKjJHKbMA(bwrzBGEyL-hNv1*prD|Nut)zEK&q)<_&(fpKeg$H)&C!P z{BpbAUPCcIy_wOJsq;fl>9)T21#qph-qbSX@+Ev9?*4JU=z7|IZp#0u{lDk@Ho%|X zF5)-+-}^N8+NYiKYFF8PzrXbLzg=Y!alK`lB7!1)U75M=tqVl1r@Q{2@H^+mekdx{ zOERoeDNHfUPvT_b_~%ki%nAaUM}N~_gU|9j|69w&o5-`wBhP!y6PbnyxuaapeoMMl zExk^rm~Lrh6_T=|`%3Ym@`hzqyv#L}9i@X6UU|n9M|2;{+i>LnPu<&`zX$9Y>0?c| zILO|O>CaXElKnk43VwH81%JplpU!rDYf`t6y|wgq089_@LYsH%`p^5k`wBTv;)790 ziXe+9)e2gXqNK4K)3?`0%lt3V-F&-#7p9V?AJ=WZ{An=UzMm60{+Z#I!p8CN%`pCK z*opmaAap?yRTR~drB3-^FMV{|XhWOU(Srsc$%|sdbb$)1$T#k57oD-(2=qm8j?2~E zJ&RU5qJ!R$-k7*NVQM)5V$!wa7b6C?Yfnnv!bPU-F3dKUYY=aSI+regbp$*1!#oO1 z17X9^V2Rna76j=8eVW)O-n>c~2*%hYs`h`tvN%R#)bRj5jd|9>C5`Z<-?-%p?9d2k zkfx*uww$uKAZ+=N zPZcd@i_p5Dg_Ntc)Idd!fgSUn_WSO8bo1NWnz{i$qa+CwfeHMQ0SbMR3NIf&YRknb zOt}B_I}^~6L7LW zf1ffczY4$jzhBqPRdb*F;qE{BB9OD>e@lOc{XM$eFScIU_&3+~*4+MI*}osTe_!_h zZ}!V;t_uAmz67&e*OmRMgcCsq4FRg^_wp}rb>{boqmumTbnq6jlhjojzS~Y-9G3QT z)6!UhtLe#e>h;30#>E^N?5fJwnr`((Yt6Gf=O>Y$_&S(S++w^gGpp8=h-it2jd9an z^^1j(eQF5BNS$>o7IU3W^tb((jE9;I?f>dP_;C7kHbf)N!-nAEv5mIqGtIlenzZ3KEz2~#teB#mM z@S%VFeO9mQc+u9Onza-YTK~!dWqaNKr2SXp&GYO}v%Yq}Ubo)A=Kb>jk#`zKdUQYR zyIk@v<|D`vDcXDKLuLv$OV%@4y?6K3+x~sEzJJ}88NY)$pUO=RxhPahuHtc2MIlE| z4<=_VY`m3&EN+Nnyo@nn2Pq=Vb<%p*ZP@v z(8+;EsC@PHU)K=z<8JxSX|U~zh;^v7kaenk zXl`$EGn6q44$I0zS4X2wgR+f!#xIMifBSD(>O=OpU>=~qj>lY8X7_pWK$mQ|dT#0? zxGm^~&ZH{Tiz!AJ@Udfr*I91k4e3T7p zb$8trj!qvaE34(bY1(5cg%Q;=Xr7vlyvpk#8d=v*s4{wLlAdIZ7mk#J5hqTx5q8G? zEB9Hevb*B%CHB@ZD7GilW;ciHvKBH7ZTRg|JSwxpl`|M1NIenmDU41+ck8(dgo6^% z;+Eo@H9HTY8e%RZk{eL;>W-g0#pgat$EAtDo}HGxa)(Lrs%ICERLX+7k<~h_ja3|+ z;tlXCH@-8-$-Py}bVEzOSL}0_!M+CF@Ts%Qxq!B~8R}MAEOSY#y`r@1DhQS9S;P&s zHPq|K<6d0cjdWe2l;c4xb^E)6nQ1q`Ub8xj&8{RelEXz8j5~?G`t>+$PS5)CMnb(U zGkZ}A@s&gd$LU>~)dA-B9ygXy9KF$VzZ>BeznXRKkZLzCp(MYwN9`NdJ0niD*} z+D0Tb(>2LP5UE}m*`&k$dwkp~Vmqm9>RsSBW=uaztMsMnwlc4{a$s!1k+V3a4LPL? zJL_9da5Sk=_a2#7Bd`(XIcz+%;?y&ko82S>q(@vdBM`c&lr z=Qwy6Y$$O`d3&C;lUY&YGfuk1>ZrSEk*i{z*Fd}m5HAFoQo#ZB(@J{IHnWpDd1SjZ z&yAYjG0V8oo%u}lu6LNqlqOkBhgX-^czfYV;>=2xp~unknxj}vCq2}cJuyQe+}U-# z#~{o)F`ALrWNi52=L1WRhD6Z|$13mS+;>G@;)LMFnZVZ2Y5`AdL6+(xsc1Wn_lrhP zB=*^bK#IDPJbXEpqVL_=ir(|p=RB>JX+j!h^Qi(3ycu_qkG=QOqeA=Jhby+fYHB!8 zyRwVKbuq*Be>{8Ori?Im!w8WAAdJZD_3E3Z)`5VAQ|h!2l4+GKnU46>`3)h2t1u!= z>kMhQA$ywL^Q`BQld+N?hXyZugnkrmRvKyw#lN7Ck zLS>SLhqg6GH|A#x9;8!*PkLTW?$!UoW3YaiyjMT*_kno!oSEp!6BzRoIi{r4&3VIu zv2^77yh~yQQK9P|uC;o-+_rx3`@J?BC1MJJhF=D@+^LPYIA_Zp-OX-JVU5D0d5y2u z5yzG~&|>H7c0H_lgsFbEL}GW4{Ys)9;pEb1LhuuMHqBjLa2Bte{pelQWl0o7Hje?_ z*JZ1G-ePYO&Pk5n%8{wfurtaE?iu*dI$_X#_042KoNU=kuzLL~RJW-b8z-GM^Espw zsBAf1F?+MFu~TTwh%#Zw#Le6u^$>G@KCvhDXUL=FIK!L-ao;gN&HU6a=U*F9xYr!` zT00)WC|^Hy6uxIod1!XRT2pbsC;DcYd_`6lLgs6{y5IL>TAP>a4r8wT zYzzaY8GH5dLF_0d>6#9}d75|<>%tz8o`u(qp*_t;USr!{vxTWICixeI z7*8=GVDkPlC)&+T<~Hgi?xRxI4|wr+L$7`fSZHraQw}zLM_4m^rh)!D#Rm(MuX*SG z`e;+P59mI62HW)V>UY6iXXOKp4%F##{3CZM+blY}E0fgmr~iL^!B9Co(`0d<6Zbaj zp`3)PJv3nIVr5o~JD~Yg(x}Jss^?i@f9WbS#`WFDQFeo#z5jZMu$-&-+jxI$IS65; zu3T5XpIE6Bqox>oKD7Bf)L#40-n3^0-9#_&=69*btMLYL)3oX`xCt}Xb%AR{lZ;j(xL=oR)75t463hWrJE_DN^ za#MMzJ=`||Mp*mw@#tl!xL&nBjd|kbv&3KZc7idlBImBCn7@c_0;}KoUP!22YR#^) z6%7r&_utcrzs0ToneH}w$jS7Cv()!6F?n-bQF~*KEj<<@u!mCM3asA*y4QqUx0#K!v0=cU1ftZDuYK62KRJxj$m$@^mvj+J5CbjQ6N&Iio2HbG9-%lK2G|YQ_ z+cvjPkU#YN_NV^)(!Z$dFH*R{hpO9YN%EPQ-4UrSmu0P^hejwLnpPOH?oH5FNm zU|o>fS9oE&v|=kOy<|o+#}Sowsc56zRQIa9gJh!@eQujuPWfF_y_Yq4botBX^IJ0T z+Qklp3*=pn^?c?OoVMl$W>UEuFhuE^O=LK7aR@+rE5fzydAg)}+)x?e#<-lgyhtUL z)?{aTffoDL^*YwH^4OL{ZL1QW8#J>iaenWcbyVvt+e+pSlTIeJXxhDF%do~U{haD2 zak`nEpJ%}ME6k1>&U1NH_ndhiVgy%ROL?KYg`A!xqPuAeas2K%BbmoW`}(YFn^)=N z_0((aNM+-9zj4-e>wRYAFY@R9zxNAU{x<)J3f304L<{$gV9vdI|D{*VtDl~K@cYem zbBr_yR%Z>6XMcw3`H}bH+po(>=0E)9zK82P&ctB#-t}&NugJ#R>NyTPpup!z$j32$ zLMGVLM|x0jaMOkVf0%&(^6OiVKkMKAo_`-p*S|bqhc-HYrAfkt`L<^-P){-b`?oOB zd+7=;ds5NAF28#HSK;*@X}_(P^<``Dt>!ylOS0xS)AkQN)8gTVYtPp=)~{8yaXwCY zNuxN^=V)uKJaFFmi{@WTyl*6X{cGNv1A5G-%rvj1?}7QRiI(38+f|3X{&`=TUnL*+ zUu+b@59iO)JHBJDtm3}uh8_&m&T`U^+Pz|Lg6elvm)BQm($=2iC*OSH#5P6ZH?iIE z%m}Ncm^s_r(`B$kg0DAzXXh`g=IeNu5Kbdb?|o&ADDC~jk-z%4Sd>4@q23h#7fjO8zKBs&7occml{&Krv5`L+5eY<|EvLn8kbU#+I9Q=2-v~rIA3`eW_ zTUu>bp8ewSj3xSd`OhIp;Ld&EeD65U4EKl=<~5iEGsC^HJY?pNcex+kXE}!yemNLnn{sbLrlH zDK&q;FX5jwbsh3t*IPfO{e9Q{|M-7+9ScA}kM=_SFG%7~`AP@i@!@c&BXi~46XUUot!$hL5{M+mhXpWtn10ubnpwVLiftJi+6BZPIvj>yn9 zlkg9o48@JxwtHH`<s;ij^Fx5p*2234SCIjv5cO&=5U>f|R;s&WT*8AOSzgc%8GSk%;qVp( zB4v$pq|K`m#V_A*cYQL5J_1=N(kEsNU0Bqb6ClV;lUu6$9^?2*pGre zT8SdVj7ZS{oSgI9YzMeuas!(VzI3oLYzfI@z34xi95&1Oi)bD^@5hHE6#7Zp`g79d z1N|jKg!8;TGt;5w^DHB;-?kNgs3$ z{^9#|_w8!^#yxty{v2WOgZqETK7a90XZ!y#4@RFz*YY{y%BtT>QJ;{|czDQV?bD7mvI% zOWj)zhj8=k{nc1*&Jqm2_ZMT=X*A)`sAnkHs<;*_UX!OK!V z#{O?2{*!56`yGg6=H3@_jWZr!k|VHi$S^oz{eM~1l(T%b;HWR@`?-c?1Apz6Sj}S6 z$X^j?GyGN++)P1o*JDnxDgLW^oY4?+(HW8B{kp0#zk}vKuXlsaPvTn>q&&YM$gYJ- zmxa>CoQt5sUH(k)z+obPO2+KHdMs9z&GfZAU_ z{O`~BYpfi95pp>a%TTxY zDl`A(o~NkCPIcq^(80r^*k&He=7jqYIpQf%5{WApnam7Up`k_{))HrW!e^L&JZaGb?iwf&XVurHo-ge9K#s%hvUZ&Dl$bm;p~lE78U-i97$Y z`_Axt`N7b-+P|d$@MR5i7Mv|US+ji6jL&10H(TBrn{`>*sTYG}5Z({O1Hh}R*Y?Zm zSkJqw_RTrQ+&gj|uTonOZZg-4Cn*9kM(m;GG0qS=(5kvC3Ktzc#fR1I$~2aTC78V5 z=LVcP!!uy3-hFo&GJ3}|UCw<(Hx^`Uvt^@@=Me>-ChYfj_IKthcpUGW>&nKDY>5c> z(Z@Fw&eO`X0!airte7%))|}DedLf=Z<_o`YJrec2tIsw@Sbm+J370n{)x?*3Ct*Ef zmDY0GX(I1sY)R&;a?7rf%eO0rzuk{26ln{xduoFf9?PH#}}yYI2PmD9jfZtZZc`Ode?d70A*W}yW`WUNaK zLq%P$d%z*)8?1kibMIWeaXV`)^hY|*V55&c__$}yQ!Z!MI_|4G-r0lT_2OFcA2>%; z?;0(Mj2w}}M-#Qk5VJjk&8CUv?s?9x9hvjpzk9(nQ*vhvd($at)E~#8bVtF^Pc}L`sjIBT+MG+@74x$ zg39pS%w4dhXWY9^vrs(NSiCE`eF7Ajhq@iW6w(zst|kjF7%MBo&Y*8KEiNqB|J~iq zUx+!vz-~qz77j|4H2F_W%83iZQuT&@9R5|PvVnWr4%Ec>?wW@mm0cP>bk^CdAKpUW_zap$=Y89HS;3EbMH}%NW}S`?jK9by~k8y{>tWs)!U} zhps0uBGQ=%ehGmPeseTTT@1ds{qeRbxpBMBuI`;fZ;;Cw zc?O=aaTvWc0{6^1e{R`ancTw(zH-~#jEJJ@P3?xmjc2GvOYm z;ZD!guHKqW`i?oNuOwWJ>0H+}5a~-!U3rLiV`-yEUU=2u*JZL5pPCZH96OLB#QjI= zUajjan9c;A^!OUZm9bF`q4M%YX9F94En&3%YPNjOTy`T|yPU4;b`9giVh4qEFExpu zDft7G`pwUf`pLwy4ngx9J&cpv2O{}wWy=$tX8-VJF^upvtNy4)%w_Ondu(O9#Wnl% z;k^y&+~>B{)aj`^c-`-Rs_Z?mNuCuuzY(w@7xJZ9N#<~8uovG&^`nrA9 z8tX}vp}vGXZm;fnLV_DdUM#cme%P6vVNui>%g;zw61s(5JP`pSj+{&0KtA;)nrjz< zSA64rH*;yezMW(sOw)I*JLb1MOtYdNH_5b+GGAB2$1=?+usH2d-N#Np)XAm%aao-A z`up|s=68*2M0@_u`ndXkao)F_{~f>F?;REl-O~+qUEC!X=8kAf=CEt+ckcnevQr&* z|C#5J*&4cTGaaFJlNT|V?`>J_&1Aq8bmJQ@_6@3P9~vMRoe8N z8P=xplUTp5Hs^Sh+2UrcZx70r*{3@Bhc$Tv-8(pw}xiz zE|*2DMy01hWjN_^^H}BZebx+NL(}tfHs=c8y6=B@<8Dg8PQ7c~h?!fA#AlbM{V;#b zkLCdXybpQ*Xdm(*fJvy7{`5oid_C`9uTwpJKB?kARnPc8><1s``Sd^fcH+tZxBY+H z{&)R<9X9{fh9B#;H}XI8a3A^m)Bdv&P)LgrL5ODF`*ZnU{dSxr<#NMbwEw(x3;UIw zg2lS&o2X)Qq`JFw{$k=gG{Z;TKwtln0C~;!>|XoIb?bj$>-)aB`u^we%MGnR6+>i( z%ok*-*R10XBI>GFS^g|5IKrWuNk4M~gvM~!cNvIR`DG3gZ0}3Oxb$Z!zEJTh2l|@B zUy12GKEy6w=X>+tcjMvz(VeOm2l+S;{mcOV$I<`J_&#K^uIGD+7oL(Cr6NP2ALSa| zOqHM=(;YD&y)q+fPki}OH>02Sr^WH@pBtu~#OFu->500ai5$bwKK<^Njia z?;?&U;~boZcP9M4FMnCi#FZZ9H@bud9 zwB0+CC$j5_4>z>up4%wz1a#li*x5&S^To-TNs3*L7Vm!}Z->y2TOJzPjhk_;&aicj(2`^}D!*cBt|jsg@_AvR&sUE@_*N&ZOQ> z)m253y4&29j8j4&|4^?Y)gH;i~4@uK1%$exB8@5Xxi-%q4i7Tz@$yn0#b zaJ1odr(+mx2<;;ZAUz)W(_XH1I-L|wjE1(ET)l0qH8z%aanyR=F67r5&sT0MomSRs z7m)e5_T5tN7w3EV|9$aS`_4G;5~8)Lk5rgZ$7?Xy#8$C;vktO+!;={FYE<7?%VsNV zAEb!rjdb_wWpfX9Qn9?@@A)k&8n!cju!df5%;ELWY<+jsy1r^4CDU=4nV80L-S#3wy|QwW~N9h_P^!&8$bG*KV$v>?f#v2|4o^_|K`_D-cLNfAH#F~ z(b*6EKd$b;j)i}xfAzPS?)JkzI|2X&TEGtf`TKet0}yF}&;IO>fy0tO8|VH*U0!Vs zZX!b28~I)V0g~f2krgurPD3pe1ZfpPsRbk<6f`1>u{sm~hyL4#c>x`!WJDodk*aio zDkV(2ym?z{~c%8MwY|KTwpWLrQ|up3dODxaTzkpB;L_RQXM zS9Qxmb7DTziUX^)4-RBTx>s?HUKkrV6mOpOuy4&L2pn;F?seaEQ$cNyg4WtrS7lr% zxgMcaWCe$0Ua>rcul=!;88&aNG&2#m_4Pk4_RW*`AEm#Y+9V%3qd!OZGERs8x7kZ> z!-P&v58lktBP zKYkVpvLc`>jbeQ67#=@#hpo@ZfGQW#E4T_88!#g= zN>YKMfTEa`qJfAXI1C}Rh*B9WNHGaP5JV*fG*Zw}6HO>%RIn5=L}XzZF$+me076bo zn=a4Mlt*%D8L=Uybd!l($XhASoz#e`h~dg*T&kiXg6t!zP*50(qJYT4s#++eq{$j7 z1Y*#ts)Xr;T!a26^gq)!!uAJpbDuV7r!J95VJ4#>X=bQSVc8iZImm*ni;-Q01vOYv zP0rF_N1O^Y3Mq)H2x2KIr6Meo0IFM9>O`c`2})4prcnhY6wnLK(i%<9IW|*eGSmY$ zP*9>%bF_d=igE-d(}k#mCH0+3R^>OW2%1o(GHX=KY1&#RLMY{S)3yHH_&z{Y$BGFB z%Lr_VGqRF=K$+S_z_JUAm4xW$V}X#UwalaeNGwwtfU!hj`cGeHAh28hLf=x$>EzJ6 z3;!X^c`O(fAe;o&bSQkkN%Vo&^8?d)&2#UQ<8RaUr@ya1O? zTu3NLswhc?z`02=CTjygEGsxtPw+xeY9gW;swAq2iKvJ43EV{L115?E$P9`aR*pJ&we-8vnQp$lO(9frWUeP6#eNiSSB$@Q3M|p z$t5RIlojfo7$_*7;iu2P{u=jhWlpuY`L5R4O6gB<6m~AH;{upfWA@x(& z#zS4Y6|7~n#01iuOw2|RL6eDLE_>MMXoxRN$ZCj?ih?StAtZvI)??7Qp;7*hmxyLk zW)+Lo-}M8@f-p!*c<`g@Z$-wpRZmP0=P*w42zPJ{0_`yeS_r`q%R zZfb@DKiJat*yZ*7a{c;lE(n|b(|T7rzrkM4^I ziV6suC@8w1Sv2jxy$d4lrEsT^T_DYbOh^70`?2|7j(!gv{r<=6py#Jm14*b42*_f> zgyg1#Q4tqtaj>;gL6S7nK}ksAc*&@snFyK)r$zeP{rSVeAn`cD=#-+8rZB`)hN@ny zWo%JYL;(F6(Zljj_8;3n+9GeG^Z(i{B zL9`lLDp4do+0N6h9ZT)^wU;MlRNM0VVY4p1^N{HE*QLw6CHCHH9O>VqY$}l%{j8qGbWG}V6&cMLH$Y9@~z+lM3aO6MGhhW literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7102c7f297296821114661e00e5bf54d0891d105-21 new file mode 100644 index 0000000000000000000000000000000000000000..5aafd5aaf2007937d5767840462fa75d5ac898d3 GIT binary patch literal 76 zcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%pJ@}( literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 b/vendor/github.com/pierrec/lz4/fuzz/corpus/71a24ce771fb7f1a4163e57a478c3044ad42e62d-24 new file mode 100644 index 0000000000000000000000000000000000000000..b80bd7ce35ccaf4f7f087a3d6505b2ccc938ba60 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%<%s|1A```SmG`Qh6V literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 b/vendor/github.com/pierrec/lz4/fuzz/corpus/72f032947602f1be74f01c91165c5118121f36c7-24 new file mode 100644 index 0000000000000000000000000000000000000000..f7f621e0abe3fb320f9ed6091f8a40f237b3050d GIT binary patch literal 51 wcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGbWG}V6&cMLH$Y9@~z+lM3@aUb#axNi;cL0~+2}J+^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/78981d313038119ac4f7017349e50a1cba56b382-7 new file mode 100644 index 0000000000000000000000000000000000000000..74d78e493891c9eddd04b7884d66db2198a7714b GIT binary patch literal 23 ccmZQk@|DO-Y&o%a|NB@5Mg|aIjXlEz09d02pa1{> literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/78c88c4afaf5962056b1aea720509b9f6f286b91-15 new file mode 100644 index 0000000000000000000000000000000000000000..33bb48d49ca59524c6865f326b38abc8e0dccb62 GIT binary patch literal 64 mcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMi1Q~?0N0u0>% literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/79c5ac978f5aee35e123f523369aa46b1d0a995d-11 new file mode 100644 index 0000000000000000000000000000000000000000..a5d3bf48c3046dd8ff77c573984a1ca76ece939c GIT binary patch literal 26 ccmZQk@|B28Y&o&_G6MqxBM>t%uz-am09F45fB*mh literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7adf4aa021efaa953268c817467959fa3c42ca42-13 new file mode 100644 index 0000000000000000000000000000000000000000..5959a250beea437da8c5b7ba9757b329d3e28d44 GIT binary patch literal 25 ccmZQk@|Ey)U|?|4^5tPrXJlhwVE7LP06Q!Q1^@s6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 new file mode 100644 index 000000000..dc224e05f --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/7b8c99ded96973a6e8f523bc1c6ed4ef5c515aa1-1 @@ -0,0 +1 @@ +BZh \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 new file mode 100644 index 000000000..7a425b8a1 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/7ba80199cbce9a2eb47da15f0c62fd1fb8fa67d9-3 @@ -0,0 +1 @@ +*M4883 \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7cdc0917ad63ce7a7c98301a366c31635f0f099d-14 new file mode 100644 index 0000000000000000000000000000000000000000..ce78b27630ffd1823dd1a4a10c5fc34ad90b0080 GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$nZap0RYCu4ATGr literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7ce37ad19bfe9f52eeadda03e6b8448e5bf57800-3 new file mode 100644 index 0000000000000000000000000000000000000000..b4ceb19f0f0e7a81ccec898d3f965f0073e78c8d GIT binary patch literal 1452 zcmV;d1ylM$T4*sbL0KkKS(G)X0|3c~|A2H5p~Qdp|M>s^|LQ;g|L|hUKKsA`6YlAD zc`I*Yq>cap03SdA000000Pe>@o%ZE+&|9wQdZK`RbC%m4%MG;|_Z&S3uFrNr00Yvf zPytkx3ZMko01IFM1MbBD=%4@+NF%Ic3;?8kv>bPxFFi;`@6aWAeqKW_jHKKq5loTBl0MJoVC{aKaD`r6|I>_9? zM-U21B2p*-P%g%l=nSX;C@ZZ12HN{%DIf&^prud%0HT0U0)POJ0HHt>000F508@wo zs-*y+P(lKPiUD5i0011Q3ZqJiAt#e00)2o9%b#m03!C@cI|cX z^ewwOgP}kG00jU5PyhfF00000KIUddWzUy*zYj(XS zo#2k@&yew7MfZI4zGbj5%K6?ETfXnR=e?&s%=R5=*Q$L!xO%M*Oy+NSp7(1bO*@-! zeNVjg!`Ha__?%a};t#KV*Ig4ehLd#HZe5%WSj~3RyPd!h+Oykk-8A;c00%OJ&5)RG ztzZTyDyoWr1qzf8ce-*`#_b&`~O?by^sztE~1O3vuo5Rh`LsGW40~*GGGf zPkZB|RQR@KQ$s-R(QfYVxO>gByB(iRb4rwhNl&iel{AKY-g)hu*{4F9(z?@gEw^V} z*k>>R001Z(;r99-PrD}1S6tohk5Or+g!>WWuW9l?;k?@!?(**4fMbO2WQ3SjEY|`r1R~S-8op4hizH5 zZJVK|2rd%0M72}MN_ly03Lu262{qixapuq!IDEzDy6p7ni5vE zvAVms$OAwqHg4?L0noVH4FKD=8s*Sk7t5?i9^UP%z3b8Dbba^F2hWYOH{EvTcYP0f zCNbRm>+Apk0000!$C&xIS@S)4>^Ugzy;~{NwKG>SO?}u?-^ zYoHD4qPvZGO1tfYRDJWhUER|;dA-{3yPL<#rBr|b$7zpvoxMJNA5aw?>zhca6KxH7 zeeN~f01B<{6~4WFd+yyc)y>^ERz2)Q8e0majit0`DFGT1=yEP;Q&{Xck1STz7;T2u z0ZJMhd8O}XJH_ForBPGT#_v6DbiBKCLidMCgSG(i-E2rb0N1CX>GlKR@1~Ri3i+WN znwxeQcJ1!PQ?Wj}`p3q7?Fqc-TjRM6 zn5%=UyEmMpdvxS-dE2MDX7*z@x!-N?yRB{&w(fn`nmcoMZEyep9RL&n4u-0(==*Bv zZvlY_pIQgEv|#k_Ub-!sYV3F3-F){w(DUYj<|MOax&;6R<#2euGN*3La1^9T%+}iO z?G7oq_keq?2iqmq54P*O0YFdy2J_0R%t|Fb=eN7P+2?uNw>fR*#qV`Zb#{ty4$bDO zS@+O4zTdH@9gy?Rx_gJm2Ww{7>!eaL;wXwQ-&hMT*9zW5v9^Y43I zxLc>YyAMoK?X2w8RUHV{rRmw7cYOdf3(p&a*_F1J(>865RH?AlX}fjRBv5yydcX(UP7O~8Ktd4^K!6a_AsGbIYMG=B28i~j Gr9DhoExbMe literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7e3132012be223fd55e5e7a7fc2ea602361ed2b4-5 new file mode 100644 index 0000000000000000000000000000000000000000..010f13fc267fad0d5cb5034505c94c2a6c84acf0 GIT binary patch literal 8 NcmZS4@|9o!0ssS)0F(d# literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7e9a88118e4c41e61f5c501e6edf9a5bd2432be3-23 new file mode 100644 index 0000000000000000000000000000000000000000..de4f0c660699169e1b2a79be0f8c16f4dfb89dec GIT binary patch literal 135 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ;0d}Sp82|tP literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7f081c89cfb6344f4aac5f813da1fd15f8bab022-1 new file mode 100644 index 0000000000000000000000000000000000000000..16410b7f524dfc8e7a3d86f278ced1f5d0bcaa4a GIT binary patch literal 26 hcmZ>Y$}lu^j8qGbEVaDOz`(%B(4fFz$Z+IPEC5|Z2MquK literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7f970f16026c689c096a19fef1a3282a13ee69dc-20 new file mode 100644 index 0000000000000000000000000000000000000000..42795e94d20f877ebc25af82000fe420e4319766 GIT binary patch literal 65 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`y~85kOrK*B)OPy?2MQczU@ DZ6_1x literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/7fa96d28faf45062eb803ea84a334b607e966f90-1 new file mode 100644 index 0000000000000000000000000000000000000000..28962b057cd816316e88dec33d065eca5d1591ae GIT binary patch literal 31 mcmZ>Y$}lu^j8qGbJf6@R%)r3F!otA8(4fFz$Y7wrdY%CInWj8qGbWG}V6&cMLH$Y9@~z+lM3aO6Yz`v; literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8261f0c1799ca71c411f6d3f34069b25dac8b739-18 new file mode 100644 index 0000000000000000000000000000000000000000..590b0f110e19f85a6617943649ab8c7799a14da5 GIT binary patch literal 52 scmZQk@|Ey)U|?|4^5tPrXJlhwU&j9?kU#SB{{m>C!vQp6qu0N4cy!vFvP literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 new file mode 100644 index 000000000..2fc2c2858 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/82afa534de59025bf1e3358919286525ae7d3347-2 @@ -0,0 +1 @@ +*M \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8496965f7aa6cea3e080dbfb911a7034e6623cb7-10 new file mode 100644 index 0000000000000000000000000000000000000000..8eaecb6c949eefb4fee8d669cb654866f1b6227b GIT binary patch literal 23 dcmZQk@|B28Y&o&_G6MqxBM>t%NaQ89002kW1&#m! literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/84a9bda8369d33ffe0d6f520c24331ae64e9dc88-3 new file mode 100644 index 0000000000000000000000000000000000000000..12276fc7a588dee0efaa7cc1c0d60fa2a0bc0367 GIT binary patch literal 10 RcmZ?L@|9p4000SA0sH^} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 new file mode 100644 index 000000000..15e4658ef --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/86513e3435adaf7c493dd50eb5de372010185e36-1 @@ -0,0 +1 @@ +BZh8rE8P \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/86637b211f4fa0118ccab9ee193c66286126bb5d-20 new file mode 100644 index 0000000000000000000000000000000000000000..32b0426952105e4f64cb7ccfc49a75fbd176e95b GIT binary patch literal 35 ocmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%y9Y7e-N+%0DeRZdH?_b literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8695984335fa005895377a8a60000a921d7efd99-10 new file mode 100644 index 0000000000000000000000000000000000000000..4b074d949fbbd9fa4a3e4cdb3a5cf5f3bf7cb6d8 GIT binary patch literal 25 fcmZQk@|B28Y&o&_G6MqxBLfqVl*p4ed?5e;Qs)Kp literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/86baa53eb98a9a342b0d5b79dfa5c58aa9c1b05e-16 new file mode 100644 index 0000000000000000000000000000000000000000..ef5234f697fda64b2d58c1fe2ef3cc7b8093464a GIT binary patch literal 35 qcmZQk@|Ey)U|?|4^5tPrXB1#yU&Y}g{f%)r3Nz`#`LlmY-=6$OU? literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/88e6e46ab1ec92ce694b8d4c3d816491169d2bb6-10 new file mode 100644 index 0000000000000000000000000000000000000000..aa9c757e55180997f7984f230bae8a871988dbc1 GIT binary patch literal 25 XcmZS4@|ECV00JNlqF6vQ3y=l?8nyw( literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/89216c662a46d50f37cfa08963acad8c6f7aace7-11 new file mode 100644 index 0000000000000000000000000000000000000000..df697e2d3ce0dbd403fac73c5439842628e69bb5 GIT binary patch literal 20 acmZQk@|B28Y&o&_G6MqxBM>t%NB{shmjpWi literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 new file mode 100644 index 000000000..049f5296f --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/8e533f8a1e58710d99d6b7d39af7034961aa4fbe-5 @@ -0,0 +1 @@ +"M@" \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8f0d2862c49eebbcd473a38c8fa1e76288f47127-26 new file mode 100644 index 0000000000000000000000000000000000000000..c7dd425011b7d2e0682ae8c1d8f1f623386d2e41 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%k-M C_6rCA literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8f61ea021e02cc609baafbdf714b9577e4bcb05f-16 new file mode 100644 index 0000000000000000000000000000000000000000..30bb322cbc2626be942b780f730a21460ddf2272 GIT binary patch literal 74 zcmZQk@|Ey)U|?|4^5tPrXEb79Xkf@MOD!@qGz?`iGRkFOV1Ch{b8WdJ!^ZvB+zhI} e85?Mrm>HRx7?>Ctn;9FLmFA^Z6r?7Xqyhk%jufo` literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/8f7a47710904981ffaa1fefa21fa95fd2d818487-7 new file mode 100644 index 0000000000000000000000000000000000000000..107b0ae8668d3187ece858002aac4a35ecf8ddfd GIT binary patch literal 23 dcmZQk@|DO-Y&o%a|NB@5Mg|rJAjn9}0{~cN2CD!7 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..3ce6c4456d67abdd27062e34b6a1635fe44f4db1 GIT binary patch literal 42 ycmZ>Y%CIzaj8qGbWG}V6&cMLH$Y9@~z+lM3aO6lMW;R literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 b/vendor/github.com/pierrec/lz4/fuzz/corpus/90a227d3beab730ed6eecd63657f5406beccabdf-12 new file mode 100644 index 0000000000000000000000000000000000000000..cea8af6ba3dc7cc2963cbeb8caf14a7ad4d20095 GIT binary patch literal 39 gcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^dbTW?t0K()4cmMzZ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 b/vendor/github.com/pierrec/lz4/fuzz/corpus/92197169aded0d5d0407e3925959e922257a101d-28 new file mode 100644 index 0000000000000000000000000000000000000000..82153779a3afb961baf829b5623fb323ec65810e GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~K5sB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axTT%ss7 lEhja(L@zkC1gsy~Ng$K$5hnj{U|=w+0Xh+6GLVqS0{~>oHCq4x literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/924e17974cd194fa756d23394676d37cc3641f64-17 new file mode 100644 index 0000000000000000000000000000000000000000..4cbe3bede9963229670a1324c9a869ffc1ec4419 GIT binary patch literal 25 dcmZQk@|Ey#P+GZn|N8=^=qn6BzycCt003lu2HpSw literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 new file mode 100644 index 000000000..44049efbf --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/92a785b5ea93d36e27029e281e9a34377d81ce55-5 @@ -0,0 +1 @@ +"Mref \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/92fda3aa2adbe37ff690c59939ca1e1b2a8a7936-1 new file mode 100644 index 0000000000000000000000000000000000000000..c441ec798ec3c8cad69852a985bc4e39119df0cb GIT binary patch literal 40 vcmZ>Y$}lu^j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?p@9Mb(bx!F literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9363b81db6b35e8beebcc32d560f786472829bd8-21 new file mode 100644 index 0000000000000000000000000000000000000000..76c0eb4055cb2242bcf948bed5f0d35d550ac165 GIT binary patch literal 88 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V{kLrWtAOCt+QQ&R(T3qvDQ240|W4YE2}pnwuc R7%cPue*;JXm;w_Lc>qKQ8fyRm literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/948b1ce043c82d0cfbaa910b6989a1b35a19b8ae-16 new file mode 100644 index 0000000000000000000000000000000000000000..8ee35db410ce6e2c7ad9fe71e14a57d52f2384e2 GIT binary patch literal 32 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R0o|A8o-osr?3#7Y3cFAQ}6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9505b43fcbc3139441e35bdaaec138e28af076f6-25 new file mode 100644 index 0000000000000000000000000000000000000000..f33bdb30bb4f7b7977781e6abc11e1f6bf080944 GIT binary patch literal 91 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(To@uY^x#2>>y{9T5Nk literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/951bb02c199adb52e9e300e9fc070bf55980b910-14 new file mode 100644 index 0000000000000000000000000000000000000000..812adc7c3481e09fb921605e4d9dace8a04b813f GIT binary patch literal 25 dcmZQk@|Ey)U|?|4^5tPrXJlhwVE7LLasWC@2PFUi literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/955404fe3f375361f5c3be1dbcd28eb9a28f06e4-13 new file mode 100644 index 0000000000000000000000000000000000000000..6b83abdb76df271b5d57995049075336eb99c289 GIT binary patch literal 23 dcmZQk@|Ey#P+GZn|N8=^=qn6B(BP!S003CD2KN8} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/967e50c6c1bc99aa5e7fa07c2de14564f52b0fd3-20 new file mode 100644 index 0000000000000000000000000000000000000000..9bca31c7c2305554a06102f7b3e4d7440e9ba004 GIT binary patch literal 28 jcmZQk@|Ey)U|?|4^5tPrXXIpHV2D4RY}6vb%+8 KN*f?LpxOX6SsFwD literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/98d40a50ee58c05727777e242ecbc0d4e214f7fe-21 new file mode 100644 index 0000000000000000000000000000000000000000..dff3de3533976b04786a2cb40d807de90923d98d GIT binary patch literal 35 ncmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%y9Y7e=q<5e+LXb literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9915e9bb007bc2c1f3d346123933923279f0dec1-27 new file mode 100644 index 0000000000000000000000000000000000000000..d39f6c7993c4eb5a43551aaf1d800ce3d68f07e7 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGboRAj6z#t~ykZGill30?ckeOGO2mph82=xE} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/99cfa74a1fea5d16168dd9efc720425b85e95eb7-15 new file mode 100644 index 0000000000000000000000000000000000000000..acd20c4577e786890e88501f4c7ba950926dde91 GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$iOJ<4gkYk3&8*Y literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9a552bab72f174ede3b9bdb7a663c963fd1463d3-16 new file mode 100644 index 0000000000000000000000000000000000000000..657ce91e0d0754c21d2c31586380da1882ba1adb GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$Z$?#B>=`R4D|p2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 new file mode 100644 index 000000000..9e58f1c4d --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/9aa3050cb38a6ad276cb5e5ca0c4776d92cb7b0f-1 @@ -0,0 +1 @@ +BZh31AY&SY \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 new file mode 100644 index 000000000..45ec57db0 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/9be44693435bc6c51980f30418bcc690d8c25fe7-6 @@ -0,0 +1 @@ +"MrSf \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9c0420bf00f888487d543f42fc48b407c65d4717-17 new file mode 100644 index 0000000000000000000000000000000000000000..635438d986ba0853cec981d2cad9188fda50cc7e GIT binary patch literal 95 zcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMf$s`5Y@_rH$?YGh(yXi#F{1(G%Y QB_iwY+vv7u>`#;c00|Bk`2YX_ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/9ca2a086f1f08c7dec54d52425bd72f17c11056e-21 new file mode 100644 index 0000000000000000000000000000000000000000..b52fcb904e7846b16ef63ceb2dcd59428e1f4e72 GIT binary patch literal 37 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প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%0D<2qAto3;!NWm9J$MG_^gIkf+5mQEAOC;if40-F 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a01e13c3e401957031defb62b05434c65b01d5c4-10 new file mode 100644 index 0000000000000000000000000000000000000000..4582464344334bc231319855bd8997bee60de8f0 GIT binary patch literal 31 hcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_p^d2niHr0054{2rU2r literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a059044bdb0402471dbe9aaaa555a063a6bc1e6a-16 new file mode 100644 index 0000000000000000000000000000000000000000..a0735ef2b06b039a9cca862a54d1d7e5dc1c17dc GIT binary patch literal 38 tcmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+UIqq+n*aYB7#Jk-m>3jTB>>t!3Dy7r literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a06b1a08fcda463f1d51c485b0e7271ff9048b41-16 new file mode 100644 index 0000000000000000000000000000000000000000..f400b22c08ff86d2adbf6b7a632fc9d48fef8b9e GIT binary patch literal 35 pcmZQk@|Ey)U|?|4^5tPrXB1#yU&Y}g{f3}oe&NT8txSsjLeEKr3#NF7+_ W|NjOC2BR7<_5VNZOa|H_kp}=%cs2_F literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a2e5916be780e35e9ecb7c42be52dd5e134f3363-25 new file mode 100644 index 0000000000000000000000000000000000000000..67cfb1080b7f919b7688a12c3330016473cff695 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDqcNCVpF literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a33252a74974fc86df30c311d501a1f363d350cd-12 new file mode 100644 index 0000000000000000000000000000000000000000..c2a9be06f713b696a360271716baa610f261cbe1 GIT binary patch literal 33 kcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@V<-1L?O0EgZP8vpY%CHbGaY%CHbGaY%CHbGaRsSU*d literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/a6dbaac639f3b82609ec27c80fbd003684c28867-21 new file mode 100644 index 0000000000000000000000000000000000000000..9f39c8e439181b414a21d5c19396a4389a0ae18c GIT binary patch literal 61 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz(SPJ6`(!t%uz-am&I@XR#Q=^92VMXG literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 b/vendor/github.com/pierrec/lz4/fuzz/corpus/aa04575587509ffc65a6b0224d24ad1125cb0f63-26 new file mode 100644 index 0000000000000000000000000000000000000000..d95281c298e1efe1b30345159672a9aaf747c23e GIT binary patch literal 91 hcmZQk@|Ey#P+GZn|N8=^=qn6Bz(To@uY^ygHvlo19OwW5 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/aa290b4dcc8198945311c8149fc1252f14555e70-15 new file mode 100644 index 0000000000000000000000000000000000000000..3e939f9109f31dbd3354fa01b64c0e7dcadbfd78 GIT binary patch literal 63 mcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lW~Fqwx$Ld20pplkqr-w7fB literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/aabb8fa4913c79f0a42494ad2215a32927adbd45-16 new file mode 100644 index 0000000000000000000000000000000000000000..3812c581c117632f16ca452fba409c9e6ff61ace GIT binary patch literal 63 mcmZQk@|B28Y&o&_G6MqxBM>t%uz-am&I@Y6#UMghQ~?0AB@D#? literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ac7077c5220abe6cd481318c42dfe6cb2cb2c666-10 new file mode 100644 index 0000000000000000000000000000000000000000..592c47a4f1cffdc5f70790a525d2714f6f0d5732 GIT binary patch literal 40 ScmZS4@|9o!0v0?pNDcr&6a#Yr literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 b/vendor/github.com/pierrec/lz4/fuzz/corpus/acbef0322169a93c7421902883cc8057675c953b-26 new file mode 100644 index 0000000000000000000000000000000000000000..48bcaa723f0179276cf77cccee6203f2daf32be9 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKbq?7-WG0N+4md4A=yt8Zh<$KiFg@pe_lp`88k@z~-C64LXeE0))vR OCxJ}1$6;~<$ejQw;5A18 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/aec95871bc7d87cae16c36a0d30955b43076aec5-17 new file mode 100644 index 0000000000000000000000000000000000000000..2bbc1c02b4b64222258094cf6e370f9204b98a0a GIT binary patch literal 35 pcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}g{f3}oeY$}lu^j8qGbJf6@R%)r3F!otA8&=A0oVJ=?eYN0Rz0FSQ-2LJ#7 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b27fb21ecbe6e77c91341738621ad7092c29bca5-17 new file mode 100644 index 0000000000000000000000000000000000000000..0292f9be34d257c386d44010d47446736e5bfc6f GIT binary patch literal 89 zcmZQk@|Ey)U|?|4^5tPrXLMy?Xkf@MOD!@~F*GnTGBz+WF*7o?G&M6dF)%SQHZwMS bzke?fnVDG_SQ=Ou89-GSBB=n$F)#oChJO^s literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b38ce47b707326024fb24860c4365d58ab9f3528-29 new file mode 100644 index 0000000000000000000000000000000000000000..8374ff944848c3abe63811bf477552434247ec0a GIT binary patch literal 166 fcmZQk@|Ey#P+GZn|N8=^=qn6Bz%r|iQ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b3eaea244bd47b64c8de3d81c7b5e94e421d7f32-5 new file mode 100644 index 0000000000000000000000000000000000000000..6c89843bc4d24eb4ffc350485113a38fbf0cc30b GIT binary patch literal 9 OcmZ?L@|9o!0w(|lm;n?3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b3fd355dc090a732d5cf3b25151f165ea901a682-24 new file mode 100644 index 0000000000000000000000000000000000000000..6274d9303318c5aa7b9c4afee278a9c36cd113b1 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%&Y}g{f%)r3Nz`(@7m;wM?CY$}kr%aB21Eb= literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b71a5a7c576e5cc5ba23845d352b2af16737c03c-7 new file mode 100644 index 0000000000000000000000000000000000000000..1e596c355ff642c3ef131ef634f44e5566a7e519 GIT binary patch literal 17 TcmZS4@|9o!0u~?*VkrOs4(I`_ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b7815c3b5649d9a367ba99e7e09cf1f251ab6f83-18 new file mode 100644 index 0000000000000000000000000000000000000000..4cf6940c45f769d717e6cfb2e06ccaf0a6598b2b GIT binary patch literal 44 dcmZQk@|Ey#P+GZn|N8=^=qn6Bz=A_a0suJ;4FCWD literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b7a5b15c9e2d4d659d421de8e3b463200f71f1ec-23 new file mode 100644 index 0000000000000000000000000000000000000000..a47008c94c650f98bd7325a6d47adbf2cc51b807 GIT binary patch literal 143 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ`0U~`C82|tP literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b83b3d04ada1403578065d7f10aa7441830dea3c-11 new file mode 100644 index 0000000000000000000000000000000000000000..1288ace233d98353d9622a06742503716db48aa1 GIT binary patch literal 20 YcmZQk@|Ey)U|?|4^5tPrXJh~Y02}851^@s6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/b94b7ebc6d153e0c99a97864f58b26f7192f66a5-20 new file mode 100644 index 0000000000000000000000000000000000000000..11053a55e2cf79c70420e5fe4b6ba643becd750b GIT binary patch literal 35 mcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%Y%CHbGaB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axT9L)s{ VHOK-WlkE{EgWP6R19l?RodAn$HT(bo literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/be06bb3c3b604660fd36b2af8860d35e31c8bbf3-8 new file mode 100644 index 0000000000000000000000000000000000000000..ffe89ef6a12a8b19bf48bcb43af961fcdf876f42 GIT binary patch literal 66 WcmZ>Y%CHbGa%=qn5i3=QOB0BsHpnE(I) literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c07f4e4cb1d0a34dc6899097fd27ee9f1744cb70-12 new file mode 100644 index 0000000000000000000000000000000000000000..9551b7b887fc38e9eef806a4894adbc7e4ee5d44 GIT binary patch literal 19 acmZQk@|Ey#P+GZn|N8=^=qn5i3=IH1?gonh literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c2ac55a7fb702dd9a527b576d99008fe9b4f376f-14 new file mode 100644 index 0000000000000000000000000000000000000000..2cbdb3a8c8b69d9f3b2f1ecb4d3ed30842ee3135 GIT binary patch literal 36 rcmZQk@|Ey)U|?|4^5tPrXB1#yXkf@MOD#&v$uC#P&r?XwNGt*XeCG(o literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c2c3d29bce8aae89fed326832b3e1e1077cef1da-18 new file mode 100644 index 0000000000000000000000000000000000000000..468e64850cdb63c1eee4d75ff6776a9e79e0b0c5 GIT binary patch literal 61 ucmZQk@|DO-Y&o%a|NB@5Mg}GZh6V`+ULaY6F02F*{{O#$fdNcNb literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c321670bbcd985327045dd1468bf2ac4ae7333e5-7 new file mode 100644 index 0000000000000000000000000000000000000000..eca662b7694b7094998f4deeca9a3b1b901b6264 GIT binary patch literal 32 acmZ>Y$}kZxazm)C~N?DB?!3y literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c652c46aba3567521f912bae6dc263b668c34c9c-7 new file mode 100644 index 0000000000000000000000000000000000000000..5cfdce9b9dbf45290fa1a487d46498f712f4c05c GIT binary patch literal 17 ScmZ?L@|9o!0w)N4jtKx1(E@V- literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 new file mode 100644 index 000000000..7a1dbaaf2 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/c6610b87900912d462229a5259dab51ea0aeef33-4 @@ -0,0 +1 @@ +B*M \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c6c37f6c89fe55768f8b3f7b28b99467c239703a-1 new file mode 100644 index 0000000000000000000000000000000000000000..8c206a17cf90bbd82e1cbe005ebcd6b2ff77491c GIT binary patch literal 39 ucmZ>Y%CInWj8qGb>{?*|jDdkQkU@ljfnf)O0)rCQ!*Z42R!)vp%>Mw;uL`FC literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c71abfffdcf530a6d28fd99cd2c3505c61ef0ac5-8 new file mode 100644 index 0000000000000000000000000000000000000000..490ee245d6b8ffc19f7048a59af391cba9e1552a GIT binary patch literal 26 ecmZQk@|DO-Y&o%a|NB@5Mg}GZ1_m&n!4Uv(4hQA{ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c77304b250e887b39b5447d19b9c106fcebe7e66-20 new file mode 100644 index 0000000000000000000000000000000000000000..7f1cf184c1e69db74b083f3983b559de0cf83c23 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULaY6EG!EYPyz{qW&Zzf04V@dU_v4f01K`b A@c;k- literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c78cd8530e6d8a606a28797552ce3f5494763621-25 new file mode 100644 index 0000000000000000000000000000000000000000..5140f6f62cd9d09079e740107343de9fc9513167 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mg}GZ1_lWRULaWm#6Wf)6N7>&NT8txSsjLeEJy`N9a!f7 Y{{{vIqZ%;v|3Bp>+v6}9Xp2N10B_SaNB{r; literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/c790308a65efa1b895bc57abe53e4fbcdb2b7d0e-13 new file mode 100644 index 0000000000000000000000000000000000000000..c2479e6d87397739554a60f77c33f5f123a60a54 GIT binary patch literal 88 XcmZ>Y%CHbGaY$}ll>j8qGbjGmAd!oVQ*e*az|isy|;gRtZq9N3i<^jSg}?BCxJP+*wq9P$wW DIrtTA literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ca5d375d8a66727221d3e198d4ad360782944de7-27 new file mode 100644 index 0000000000000000000000000000000000000000..8c22c4dec7c989c754f375f9279ab19147fa6911 GIT binary patch literal 195 zcmZQk@|DO-Y&o%a|NB@5Mh0F628QDQ{~H(>B=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKX9_c0tJ*n!XTNN|L^zj1tLbEB8LC}!6q{SbxDBDuK^hVG2axTT%ss7 fEhja(L@zkC1gsy~Ng$K$5hjD&W>f=qBGjD#Vj4A9 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 new file mode 100644 index 000000000..9206cb935 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/cb635ef244cb6affc005c63d0bf8b52aecb1d986-4 @@ -0,0 +1 @@ +"M1 \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cd67bf90feaeb1912792508afa01a09fe1f044c6-13 new file mode 100644 index 0000000000000000000000000000000000000000..71ebffbc207bc13b8584d97a7d8a4e9727e3bdba GIT binary patch literal 33 QcmZ?L@|9o!0w-KF06@nBhX4Qo literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cda434677d4bdd969a3bbf84086349f821e39c80-1 new file mode 100644 index 0000000000000000000000000000000000000000..0d66552a94f9755ba775f3a5a30d1ae566e55710 GIT binary patch literal 48 zcmZ>Y$}l!`j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`HgRA-*6u8}Km#wz;#n520K E07-EVlK=n! literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cfe7201e28d42484764264c231663e6372e95ef7-14 new file mode 100644 index 0000000000000000000000000000000000000000..ad5308bbad6312d84f874040858f22b93390965e GIT binary patch literal 32 jcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$N;1O$mR}X literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cff88dd94ee94e1901d25a74e29ad863bb78b1e4-16 new file mode 100644 index 0000000000000000000000000000000000000000..50ebc75bfb4fdb40ad07fcc99111f961cb8cdbca GIT binary patch literal 32 lcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^&cG<_4gkY?3&#Ke literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 new file mode 100644 index 000000000..cac35b696 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/cffc7573debb5af80aaddfa752538825275fd6a9-7 @@ -0,0 +1 @@ +"MM@"©+[z_ \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d0ae058f71e53a7afd648b859cd7485886be550d-22 new file mode 100644 index 0000000000000000000000000000000000000000..8a7600c2c87c4e9934e84d8911c6a12cecc93589 GIT binary patch literal 127 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=QgO3 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d24f23a23508dd6bc93ea6283ed49c8ba4b737ed-15 new file mode 100644 index 0000000000000000000000000000000000000000..3bc8f21001899a43a7937c8ed3e35f33d458be5c GIT binary patch literal 49 VcmZ?L@|9o!0w*-u5{(a+2LOjy1t0(b literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d295ca4c78f7fd3ff10b0520b09a0a346310e0a9-1 new file mode 100644 index 0000000000000000000000000000000000000000..104bdc3d18f289e79d59ffef745a011a450b8113 GIT binary patch literal 58 zcmZ>Y$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C{x KvzUFH8ZrQ#K@ArG literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d3ddffcd038a5646a53d48b684eac5b721c7062a-18 new file mode 100644 index 0000000000000000000000000000000000000000..0702c4f88e08ccafe37fe70250000fd5aade110d GIT binary patch literal 59 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=PC$0HtpWnE(I) literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d4275f1f814a5b24f7b4788d15f3fef7b2be8aef-23 new file mode 100644 index 0000000000000000000000000000000000000000..7405bc729cc0462e338851792d70ec19bf4a9605 GIT binary patch literal 72 ncmZQk@|Ey#P+GZn|N8=^=qn6Bz(TZ;Pi9F;PAUT<14AMJJZu$u literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 new file mode 100644 index 000000000..50220fca7 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/d57eaf0fada8726afac2287cafb7720af7417b16-1 @@ -0,0 +1 @@ +BZh11AY&SYà \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d5c9dc3b5b4e71d902fe4cf5c44b237b104a32a9-4 new file mode 100644 index 0000000000000000000000000000000000000000..5a0cc7def8c4e585e04e5adcfc52b647a09c47c4 GIT binary patch literal 30 WcmZ>Y%CHbGazQ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d7855c38db11bfeeb474a4782f1ea293192f786f-1 new file mode 100644 index 0000000000000000000000000000000000000000..d4bba7dfde6e5c111d70903c50390f914cfc4c27 GIT binary patch literal 42 xcmZ>Y$}lo?j8qGbJf6@R%)r2KCx(Gx0Rw{qgM%Ui3kw4WLxTc?A%lSeGXUah2w(sJ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/d7912c5e2a776c408e7640f10bd7d655a6a0f31b-27 new file mode 100644 index 0000000000000000000000000000000000000000..3df2af3fc89b18264e42538f1bf6b5eb08e2cc24 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lu^j8qGbY*1h@>PYEOplBxOsA0!K*z-);;0ORZy A4gdfE literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/dcb49d3d45d32601fa27208cec33813e03ff6179-1 new file mode 100644 index 0000000000000000000000000000000000000000..a2dd20a4cad4ebc32b9f00cbf96b41c2936ba0da GIT binary patch literal 47 zcmZ>Y$}lx_j8qGb>{?*|jDdkQkU@ljfnf)O0)vuKS~Eklyp{`Bxk_*=C&w!0e+d8~ Ctqe{8 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 b/vendor/github.com/pierrec/lz4/fuzz/corpus/dce9966b94744440d75a845a48c806041f5a6612-3 new file mode 100644 index 0000000000000000000000000000000000000000..de247315cb6fba307228d83d2166c8108552fe24 GIT binary patch literal 31 ncmZ>Y$}lu^j8qGbRA4aVVK{Oq^<3rd^lSU058x4wEzGB literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 new file mode 100644 index 000000000..5f62a7941 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/dd92516fbea2d0f96abc78f325d731053a451e16 @@ -0,0 +1 @@ +ìª` \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ddf986569f89016184b5b6e924d5ba827c9980ca-28 new file mode 100644 index 0000000000000000000000000000000000000000..c80538dd4374026fe627ee8dc69aff393be82111 GIT binary patch literal 156 ccmZQk@|Ey#P+GZn|N8=^=qn6Bz%p2b06T>++yDRo literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/de0acf1136a1e05cd27345ce135ea26abd32bbfe-18 new file mode 100644 index 0000000000000000000000000000000000000000..60f4c4567f35494ba04df43fda31b6cb6570f2fc GIT binary patch literal 36 rcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%#fUsm}jG_z`y_iZ%PK2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/de33e3ef8a5780c7d3458188a423c00f470904d0-15 new file mode 100644 index 0000000000000000000000000000000000000000..57de944141fb2c859d84250381bd99a6070db3f2 GIT binary patch literal 32 ncmZQk@|DO-Y&o%a|NB@5Mh0F628N3N{~H(>B=VRT6j&tyt#k=E literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 new file mode 100644 index 000000000..1d6eb7a2e --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/de501127da94246b2d3aa947637b49fbc17d5e47-1 @@ -0,0 +1 @@ +BZ \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 b/vendor/github.com/pierrec/lz4/fuzz/corpus/de702cd20caeb08a843e0c09b0ce87a74e300415-20 new file mode 100644 index 0000000000000000000000000000000000000000..bf568f6f4853bd8fddcef874115b0e9e53684961 GIT binary patch literal 71 zcmZQk@|DO-Y&o%a|NB@5Mh0O9h6V`+ULXlVEg%XcEDPi*frLRaHUIyEWFZuoEs+NR DdC3!7 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 b/vendor/github.com/pierrec/lz4/fuzz/corpus/de8abda1b9bd5628ca99c8f97237fa885a857bb5-19 new file mode 100644 index 0000000000000000000000000000000000000000..064419b0cea2314dd9a997d13994314094564932 GIT binary patch literal 35 ncmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%d$0-k literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 b/vendor/github.com/pierrec/lz4/fuzz/corpus/def6a9e986daf0b268ef29ef7e821a9f6840ef2c-8 new file mode 100644 index 0000000000000000000000000000000000000000..61307ca8277c078c79268eccd91620319bb2cd15 GIT binary patch literal 20 QcmZS4@|9o!0v04101=!4x&QzG literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/df0768cf0c709a1ff1a93cc0dad23979501c54ff-21 new file mode 100644 index 0000000000000000000000000000000000000000..07995a45638fc772cff8fd750794098f82ee7502 GIT binary patch literal 115 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=Oo#0PGYJnE(I) literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 b/vendor/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 new file mode 100644 index 000000000..dd3288ddb --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/corpus/dfad565009b0667ef2ee10ea9c1286ee5c3ce6b2-1 @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/e.txt.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..65bf3b4c32a4742140c57c59ed46a06f859f9ca1 GIT binary patch literal 43149 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 b/vendor/github.com/pierrec/lz4/fuzz/corpus/e1556049ba9794a15ee21aa283876bf63e531a4f-24 new file mode 100644 index 0000000000000000000000000000000000000000..fe1bb6515770027f402f5e181ccc298280353d87 GIT binary patch literal 147 ccmZQk@|Ey)P+GZn|N8>%=qn5i3=IQ~0efKB=VRT6c`zV85kNQ3=J)f3@nW-EKN-f z%z-KxKUFpMm1pS|9`N_Oh8={VDoFhCVY$}lo?j8qGb6zG4f!@$5^{k?&qL4b*)k%7Sh2pJkUgct-EfII;K289C(42C}H LkKTDK=Mn+{qihY} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 b/vendor/github.com/pierrec/lz4/fuzz/corpus/e68b04a675d8d4192565a808955764c77ae510e6-16 new file mode 100644 index 0000000000000000000000000000000000000000..08838f05e71fa5cd6b9276bc5c69bff991d49ebc GIT binary patch literal 122 XcmZ>Y%CHbGaY%CHbGa%=qn5i3=K%wNecj+>j(t^ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ecbd6bdea50b52d263b4e9cdb96c7ce078d2b780-25 new file mode 100644 index 0000000000000000000000000000000000000000..41a813aa9bd54cdecf6b746f4456ea9f98934106 GIT binary patch literal 147 bcmZQk@|DO-Y&o%a|NB@5Mg|~g7-$RtDF+qs literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ecdd1df7d975c8cf8d015b2f1d0d7c6e00eb578b-15 new file mode 100644 index 0000000000000000000000000000000000000000..d02e56eff147b92a29f530274518474690eb5683 GIT binary patch literal 33 mcmZQk@|DO-Y&o%a|NB@5Mh0F628R0oAdt?^$Z$?#<$nOwBMtNb literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 b/vendor/github.com/pierrec/lz4/fuzz/corpus/eda1ee9cf85f3f71ec8a4eec7534ed2677b47775-15 new file mode 100644 index 0000000000000000000000000000000000000000..f0d2c8cea4be83518d0e0effe712dda49cecf440 GIT binary patch literal 32 mcmZQk@|Ey)U|?|4^5tPrXJlhwU&Y}g{f3}mHY%CHbGaY$}lu^j8qGbRA4aVVK{Oq^<3Y$}ll>j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`HgROgV70J~obmjD0& literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 b/vendor/github.com/pierrec/lz4/fuzz/corpus/f493376c3eda80cbe822ac456486734b72f891fc-2 new file mode 100644 index 0000000000000000000000000000000000000000..b06a853b78e23f1cb190543567fa465eee20fb90 GIT binary patch literal 44 zcmZ>Y$}l!`j8qGbjGmAd!oVOV|KEXKNkN|_gu(v(9f6d5@w&tdZEPvr%lwT1AN38B literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 b/vendor/github.com/pierrec/lz4/fuzz/corpus/f55efbb04cd32f7828e951d067319db00627153f-28 new file mode 100644 index 0000000000000000000000000000000000000000..4b730fdd58a4cf87b4284c6a55189fbb41b19132 GIT binary patch literal 51 zcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%<%s|gS;*yh|kc#0F(prfeiUX00x!| Ap8x;= literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 b/vendor/github.com/pierrec/lz4/fuzz/corpus/f71b4776ecbbe47746fb53d7749751c5c5bbff05-22 new file mode 100644 index 0000000000000000000000000000000000000000..dd1e8e9c061c7a43cfcdc0b43973d53b709c924b GIT binary patch literal 61 ccmZQk@|Ey#P+GZn|N8=^=qn6Bz(TYT09r;8ssI20 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 b/vendor/github.com/pierrec/lz4/fuzz/corpus/f724d4c839c012c7772618e28ef68d478cc00c74-21 new file mode 100644 index 0000000000000000000000000000000000000000..0476ee760651c63160e294c45397e7bd08f782b7 GIT binary patch literal 37 pcmZQk@|Ey)U|?|4^5tPrXB1*!V2D4RY}6vb%Y$}lu^j8qGbjGmAd!oVOV-{8Qmq@d3d!eIaYj(`G#^S=ZDu<;5Q literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 b/vendor/github.com/pierrec/lz4/fuzz/corpus/fac6c4165067ef2d87a23a2530a59eb560d470e0-23 new file mode 100644 index 0000000000000000000000000000000000000000..72b39c999b57d5240281988a4d8ac16244fd3e84 GIT binary patch literal 51 xcmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%Y$}lo?j8qGb6zG4f!@$5^{hgsffQh4#fx!U?85%f*7z7xAJOKd)g#!uY%CInWj8qGb>{?*|jDdlbAw`6Nfnf)O0)rCQLzUoGPL5Ta{{Y563P}I} literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 b/vendor/github.com/pierrec/lz4/fuzz/corpus/fd4f0dc77a022a8140ffe5b2e1a5ff577e844878-27 new file mode 100644 index 0000000000000000000000000000000000000000..fec864e0afc1805e6b39ec2914ccd6ca5b7e577f GIT binary patch literal 51 ycmZQk@|Ey)U|?|4^5tPrXH;NdV2D4RY}6vb%B=VRT7+56$trQ6u literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 b/vendor/github.com/pierrec/lz4/fuzz/corpus/fe002e4c7731ecb4c09c09a4e1fa29c0c61874bc-7 new file mode 100644 index 0000000000000000000000000000000000000000..9bf6f6e96fb9501712d70443440e3c3bd4863e1e GIT binary patch literal 15 WcmZQk@|DO-Y&o%a|NB@5Mg{;XUIlOf literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 b/vendor/github.com/pierrec/lz4/fuzz/corpus/fe78d4faf4ce717d84938010f92ca5e844f9980b-13 new file mode 100644 index 0000000000000000000000000000000000000000..88b3ef7e5ea0c0d54f243afe1d291fcec0bfdb6d GIT binary patch literal 24 dcmZQk@|Ey#P+GZn|N8=^=qn5i3=JUc1OQ*>2TcF~ literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ff3b7ea844eb197dc6bd59d9f8e4a4a5718a6771-18 new file mode 100644 index 0000000000000000000000000000000000000000..eea11f1681947a285ae2d927b29c0d62cdd53451 GIT binary patch literal 36 pcmZQk@|Ey)U|?|4^5tPrXB1#yV2D4RY}6vb%Ad2 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 b/vendor/github.com/pierrec/lz4/fuzz/corpus/ff47856b8fa7323572c8b4a6d8028dcb2663a37a-11 new file mode 100644 index 0000000000000000000000000000000000000000..ed4aac7166ac3db93a890972d9bed4272f79f7ff GIT binary patch literal 84 acmZ>Y%CHbGabe zi4v*+=Y8))kxHV9=+Z<|QZ^c)DhUb+5&$GbN~DoerCS3fAd0GE-#GN7K%|1b-~gS% zs6|yJEx;DyK~Rb+TYw9LswF5?O~4j)AxR=sHvlf`s8FR4O5h#2N}^PXD!2z{6-X3R zh};7>P$*RtPT&iGIuxN)tAGQM_jph$B#0Nh0e#1%Pys|ofF9jQD5)eC;0roZ5|K&{ z0CqT{fHu`ixB<*`0!pf+n}8KjK*clw2%1F15KTQzJfWeDA)%p&MLZ?|RVsQ^9+8O9 z0AU6ufB^u6%i3dsL)hs*wIGO1~#a%7%^;C(Xp&;MzN^d z1yQXQHZ`%0M#j~Rtr|2zYKu{9RBWb$7>!99Dlu51pw={NXrj@LqN8Z7CZf<{6IwNm zM$}YoqT3kS#?fp=8yg#JTG-l(ii*b3jRw(LDx+fsqf!-O+AK!Vud4a$YLFq{D6cGi zFAewmK3saxr|py6CkgwT$KQsFsTQ=KNXGR7=K9AY`|_8xx^O&6^02mwLxrSi z*}-q9zDv5Ydg^m*W^5$8r(w*YSVT0k{_?Aw8rNvv7=$w*b}iWoh>zR8$eqKF$U157 z%Ajw#*CZUx{_N$4UfJbFk($>|bmHUR-N}ratuoQtC_JnJ3sVZdd1`sfMaV zyM=Sy3gW|y`Pa@EWp6&0u%Pb3W$wU{ftE_ZQ^Q}B3ALxbu_X8e(S0fIV^a^RbxbZ% zIJSGwjkQUZ!nyH$g}(E8nJh9x-x#mUY3nNof|DDlqc4wa=1v|+1V0k*@{7$m)4qpw zpb=@obwLM8-NuZZNJ|rBw+UGK#UNLdPQHlW(TTh4`ZZlF(V3m$ya@5w2mrut`;zBP& zN;%ug?ttFYa_;QMUsbkJr??Ie{#NGfu9qHWtkn-JcLX5CP?B2l9KdTT7p_#r z6K_l^CCw+;DYKAs=!4?MW(zaz)f+)(e(|R9Phdwcnq7{^U(lc?*=S6r*gP=o)oxTw zjeRn3+^-A0gX81|mMX;QC$Z0hNtwPFZ>#CQVbhK$JzLz1Da*XiijhRX{=ch`?Adq{vk-e$r9A@ksoQg#SmyPiJCy&1KZ_&=<7A5Rz?dn&frZ!tZP&2N z#hySm1ZiD}MTo7jecOddQczPbOE(l!8Xm#Kg?OQ=g#=gcOOquxmxCNsFJgY9UmiMU zQZ?>J(y*h$zB^|7$QC6OIu4}b)Y)TlS447*ttq&Bv@7D|;|lv@p6a7)n~{VTSXsUc ze<}g}b3B!Wsorq5V{Sc^tj_shEnJTUqz^p?o^K#Mm`Z3lHAh&QV%vlzSV}?sOs0qe zJLGOhf^s$yRW>MojbiyY&98ng91h$V_VD0ZSLu|yKyhusT$2owaIjp;?noi1xR$RkO`cyQS z+hsIFva1A=s~k?6eFQLoz#T31WJT9x|#dP^aA^y zsmg#^;lb8VD1jE$x<#uOUsG^*Y<0`J7_+LJww(HCCLv{N3~tQIp9YmrFJgmk`14bW z`2dQX=vEcz@kQ&z^VSbg^gYH)?KOCcr|?X85iq84#Mdyb?n7q{4!5I7XDW#2kzM&9 zg&mMb5th?{wQ3T^8PjRe8aGrzn%rcF?5uG5-*~DQ?y-pt6vRQL+@TAX@!xa`^wgF4 zb6_QaRkR@_9@71og~R2R(UO^h5(XBk1p!w$petDJRC)DJDswVD%>@xFSqB1y zbnr0c%#BvfNvOaO@$B?|oCC;B1*Q?D`^s^~^YLue4VutJn5w<|_ z4E5nQt4Ecgu-Hm=xef0YdFE++vkZc8h6kw2M)hE2JVOGK2_nC}8xSj%Z5-#-p|Bhl zbmejRXd6GxzdE8R%rDS*2?LA74AdJjDdMx3Kci9fW8EHF?G{BpBR7bkVljT2PV zY#~C+6>nATe^?4T3hgkHDBRg+SX`a%6iz9tVaSjOr)z25?VH?y^sj)S$mmggxM1pi z{oe=F`SDa=Vsn8x=GGzAQ8*d&_>hb#F^#3o_}zVISVpP)*wlK^_rgvcNX-@;MsH_Q zK=}L;NhFdDX8M~c_v{nmig|Eb{1d7?{b2i9Zl-EQs>~e1k3@0cbkWlj z4L@Q9nWa5yD{etKYY%0N0QQjhXExTwscsD~YFIJTg2lYa%F6Ut-)w0W7tb#K_ENEQ zsz&p-ugacV1mS0YVH_|Dnw>9WXM0`fcZn}L*DDl4lb^6J8_H-pwy%xAc{NiW@+R|Y zFxsl>f?LR9YGMSoe1WE+*^iFw0y6) z!B1<=lax?%v#XD5ZowS@t!ulb#-(2=G7WUr>E4{ChWWlFVgZ9 zq6?C+1+F0uOPA;N!l5)PK*OU+`(?34c`9>~d~<4Rhoof3;}L#EQRUv!l|NWg_}Kj9 z)ObZS5?2R0n+|k>abeuf`_Fo3>B3T92T00ze3B~bcrh?7*MT^`6e?W09SLqjTg7pr zXXA&Wm4lZP2`-QxG8rWAMp9Xf*F2$lcOISfS?^;(+e`_#N5QkTb?-g!9m!;1pKm@{ zMfOcb;Smofwc`*zzi=UVG$)b$;-6Je`aViy5tK)|mq_5dodmvnZ*^M%g}a>NG8VU~ zQV-ka+x|b>_GrE5v7g*2ftqda)LATh@bXLbv9#Z$I*{^Zsl{|-P~HMp9BB-J5Do9Q zk5?NT8-pt2l?Gzm*7mMR=RoGU^_BIssw7IFuM5x7K(vCFP_B1Cz??UCv{Jak%$YQEGwkXopR0{ESWzQ4DX}QK~3{B7wa}lN6Ajo@3{VSaX%aP-zfYl74 zJ~r~vcn6is*~vYGW~bP7)k|R@_1h9>5Ro=nJZ7j|>V&YzfW&6At0EaSb?s3=(5OQS z16ebWWlu>R76HsYs%(`o9_$Vlzk1z{Dmuk^gB=|m7Eu^u6M-URVO2noJVi}=EO4WQ zVvn(%(die$?LQB=vsO=O$;Qdl5Kh-UB(e_)iP>Gp&F&o6^sy7p$?vv3Lp>+ycP*^D zeW#_CIyD39Z`<)_1M=z)i$T06=r%+_;qZ+d_#~EMiudaK{jn_ z4Mgc=W9<94Wo2qMG*B5sJ8+KNGsk1y7LHUKMAYgRL9fqxxgz?(6GXS(4!P^NW|$YL zid6AJttJ*ovw_6*lKV*m8@6Pgp));G8n` zv4(T*m5XzvwCN<#3}KQGY@~WzIYZQG!IeITP^BlBVv|?N&q~?fLt*-4^p8S~uPc`Y zeL)?b^FhbB>9rq_tmektFmw)D*D(VKn$MTmIzhb?G6P!sd#r17j$K-(a=dd18B>dO zd$;MG#aotnR1}q5(wawMCFjZCbt{ME@bMOK`h^y$=8r;5@=ur?NcA&n4-RZC$s3$~ z6N8Rzg|jM^?;G(?Zt3QoDc_odd3UF#qd@kJ*JO1kR)q{3JqfaEtUb?0Ub)f_UP9Nd zfTOcuQ zcu-(9G|a8WPeT};n1SroL%4`=rZPF_J-LHG_-NHE2jl8NiD=GnTGL3 zm71Cft`^88mkQ&{-Nct_nl*eue&AW;RulCtmiTW@K#-)D&oyQdg~HuQ$WY?4jSYO72i_+i zddNlIXL0?#bfxNzMrqAndPEhQb4;_#!ett;gHxG5Z0-H;qa@gRIyJj|_}?o)$bnuL zLIMrztEP}@71zWkdN0;sVpo8S_pt;HJidE#8W#bqVphqIT3{*8w#`%=@x4&Dcl7Arzm>#{6Cs?9qPFUGT+HXAg zd?8`g3ybixBc6herQ_O}h7&|{TdLZ3=Jjq831Webj^agnA%PREa71pLTISyRi_X~! zc8tE+kR+AouCzCaqjrJEk0@jbGXk4qIjhY2>lE=VV=q$E|H=GkK;4XM0shU!AOqrYl zZ)b$lY4RC;Zpx_#g!Pe;GMi1sUV@eNO9oe#eB$Qv(xtFw+K{K)Ah+r!dE-#8Rj9J$ z769ghz{!UM9pf zSqAB9d4029FjJf}P7G$#yz<$xVXzcnQ(%Gj5r|M_z0Ih4Z+WAPRR*99ad5rSOfhnY zA`T12k#l3oYZrUV=%y`%O>i!^TkUtRJj-2QU|7Plp)HV{u=4rTt^By~Rkf3RupHi- ziFeX9caA>Y7}kX-y4reVp_vUt9AHL4p#{p~!VA6Y_iXZkaWhTey)|p+t7JwVCljWn zg{ymr4hO7<8cT9q210645g93Lpnmj>E)nFeTG^2%0y_sn^js6vu3{nGm%p+Qo0^kTDv z73J#I40%521fC4t+mzUWAukw;E+YL%9e*;=nZ>uhH$QV~ym?C8G0gdvUBe`iRbDWd zT_Xgt0$h6PEWEKIpjqUum3qxWiPWbTPSku0?ay-~6w2C92Z+-M*m9+r_WRT9^IT$2 zo+2f~g0hHq_WNp)m=_(dKty_*h9-pNL3fMR%7 zXdg^e$BvS1(bjpkMAU?ONXJ* zI-uK^N4K@dlyI%VriC(^2=Gaz&xmc2HP^devvx0dULV$gz^`B{*}!CCmiN0y@p^mH z>!Ad6p$9wO=`qObGc=7b(3l1=_Hc76$`Dk`PRF995WQoZPnvs-ju*C^yF&A>{fiqR z*De~fG6>QqI?jqyUY#M>)D2D%zC22ILJuMd(1vr zEopDDo>ZrhjxDsm8+}{kn)k2K+`=tkDL(QPt-I?*NP+v_;3Ng&d4Etb zP7<<)&B8t+sgQEBGsMCAY6g5v2aqso(;Mvv;KUqjOS7F6W1iOGff^TytQq!qOt_)< zRm5CP1&}vdlR_^$g0G4PZI`s1k#^%jJgmJpT-dMZuvEzmTzg*@qc=c-2_5wGri=q% z6T_Kh8q&gBzTK?r?g3grqPaL`cDfEkqD(4MlBSx>Z;HtV2*NIWW({Ikhvb&WdxB%J z*u$1|XXSp@&IOq}V`&c_VL)ViX3IO;Y$lU)n^jOYkxaZjV`V$+LzIdx7B_GfrnN35 zO#B@Dka2@$>rLmr2iP8l#zO%eFFvHC7Ap(WjNC7_kX7ZY@QHmd9&XOUoEh<}bMb}w zP!T5bASg%-0g1c7jZ*@u9Tvi4CNrVp{Z}XpNsTh- zOn%O6;_!J20%ASVHeTkW*mjuP;irC^G1g7t%TjV6G%+IFw&6NK!jyXzbPFTl^@>Qi zuC4E0ji3>qr^KV92a{Ynytpvhtt=%GOn0j~_lHAdO^Hg+i!xD1iX4F4z6dj+t5=S? zKq_+z1WjtyUXg%_^ctOzFTF?65k|Jjy?XXxk2jX2ywj5}=tru3C)H78%@Z}r#|YFm z9(h{7<@i4uCL9_3J12X2tq6U#C5G_q{?KHj$-AQ8Y!8j5(NYyJO5pBG@=sz^44njH z)1_oWPS!7PidNJeE_0|C?i(6$*De|EHkOkCO3B=t@o-%lz)8yrUPCK27FK2?{zO$) zIW*pZwpR2~Rml%82?oThJYyPDtn_5&DRQhf7i)&;Xm>0fR$x8I1qmV?N>kOn_iox{ z+CPRt?!~dI!v;&V(vCN$JM`KMJr#nl=BCDYk&1(vCuw3mpz9a3S(>aW{B?#M0 z1@+M0+G6hDDwP|u^-Gy(cv+=2Cpf`#TFJN3Z3}IwtUQC=4C7-@m@sF;BY_&43?2>` zmx7t%CkF%_W8OJG2KCkv zSOR&lvZiuJvBo6zH6THcU$>U+{K@E)Q_pjt?Ndwc-;48EQ=xPADy|2Mjr!Tur@Rb7DZ-?ROOGj`6==* zeI}>F0x(WKjiLvAHwj~5yz1J|dUVE}IaThI@0hW{Kxaom1K9P286W{D2BETRF9Ctk zJFlB&r8B-+_SE;Q$1&(;nJeX02fJxa9FwKNTRJ(PC6vFKw3)tAtdiGQbsrfHoTp)1 z-$#L)C~;l&UbWPH2M+lC9(j?CdF~PGwYzdQHcp(Nw0<0LdzMoxSM?4+)dB?j8#ij;QFhw(C{)c8ib(oT;HpD%K@6KdOa1^woi{quQHAl zuxg8_VJ!GB?W(ZCA8BJ{f}->30FR{@ZQ<5@9H`_oDa*~hg;?iuA_NwjNeH`Lj2ggZ zi%wO#zKNOgXyF0-*r43v;9+x+MYobJAz;4AKQFhg8+34|ah(Q)qa40-(arZD41BsS zWT-5G1A+>1^lK}vJw3&`DQtX;=s{bC2RLC-#4T5o(o4e$L^IOx(L2|@@UEiRTFg-s z)tJ`e>Gm~Lqdw;qpOM1q+HruGv8N$vmh6%RF?uzzHVP|;gNu#nAd!bBEW}>XJ;q*{ zrX+p=O1l_N&p|J$6$%)sJuIrtfXeG>>fR;r8pyVVK*^hW$FL|yU@&n7m=jTjK+GxD zQPnz~=KQ73BTCLD$d7nLBb?>KqTU#+RUiKMTGppS4fzPmA_5!GaG`TRHD065i z+F6S+)b=Y>EVs_;aeHX3fblq(OACT0)ab=dCNF3*{xnHc z!@MUs0kLU=SMAYO+;b{KZRUsaCA4JrbZhoFZ9_-moku7+w-U7(WT#E>2rE$QC9lisgX$806OqY&voo zxm6(e@4#b9_;rBic~(S%u?Mi$u=kFOhi{nX~VRP z(KC(;F)DwdUVilWx!U)((lZsA=qKC^mw!s*m$)X=+ax7spgTK#+2&lT8}vFm&duu3 zLh!cTRI2U0A8!XmIj^77p{F<8!S3tFT)VxSw5t-@V>F1uP4P0xbvmS)r!T%^QB;1t zSY{UzqRb`Jor-)^eIQs4+wjwpu+cKPid8$AZc-Y7+e%aA+%p-JnN{OOIL`Z!pRiCv zj?~X`x20%ra-Y!f4j&naiP2@3%P!Z6mJLn1L*l6mR&QeCjsr4X`hb=l+AhFR)UQ3m zFtEClSc~t9V@je0KKE!>yR;s8{iUnPh6mIJ9fK}Q<1*R2f!A`jaBZbrlJu258=>!S zDji`r7HQu;Mh2dSlBf!z0bwnYScLJxWvGl#g*Y$R_+U6wW*G8fK*e61@ul`e+eju} z2R%**F0olba_U49f|KnJT_*2XXbu~!p_sM><%dCUpGp%c(r--$SK7!~$b$gB0k~k` zapeWve{NQF+3ua5I+I-$z@9n==qbp0IF{)HIUHpZXbE~V6eR&1`8oB@*Uc^N(Y)RV zyp)lZ_H}fZpkTJn-latp@i~G-u8n4V`|o>^2fiT>nrYyQ_aev+hhXFfL0((CIbmYE zDCLOTjYKd#%y5Hn=y+AM^_3eGD(q`Hc#1BI>h3^OUte-B39}XBn0elATb6V%-xB$N zhHJ<^)j3|;NKPMFZZ}-1HO^Hmt0+6-@wX{IB)PzcH(-QBsc!W;=eP#^e7^d{o2xaI zh0XDxj+f5-lbEnV6XIW91qidzR3_lip@srHWs>E*sAo-l*SJ@^b?L$h-PgR7EeJV` zW*;~xMN^QpL=06Pa)q7`FBa|K(8)^n3)7-xK88+5RjV5kLdR_arF2aC+ia|gP${J{ z*EN9f)NW$a?VYbP=U|8zI;nC2Mf(hhFEd8b z9j$GCXrWABUc3{!24P1^)C*`yq7djLW|W&lRLSnN)b~@MdU$WgmhuYmJ~ijDy{9SW zA=iS5MGrqd8F@>Brd>XB6)Wo{NXQ`q{TM_--q59+WXja?&GA))B3mw_1M0y-$#jk6 z-d!z6uE=2FQ<*O_qDXiq!eCvUr^9!YZH?@p&C(GJIDb8&*p#cMkX}e_$qADaGiAD@ z8@Ht0p566(m5^qNDF9Zh6sG1sJnD}D`5}Bsy(CK0`L6@oV+S^r>mi$v!1?lrFbi_R zua`GkbX(2IeMdw`M}koY+aYVh;-V6@s<(7;fGJ{HfmAT3R;DRne%s5oq>#@N1F@Ss zQa(0?R)hsy@fmSe*hcmhPD{lk&zsgxzB_fBHS%^!`q6|_vv+}@ggrBtWIjB0$fDp~ z_Q<7Zt+*TOylNt+{d8qvb4X2tMVL}Sv zT7a?!&6sd|h}{Z;k;4?-E40Ock0k+D;-(_^z2TV6o>^MW5ZFQY6oAq=`l%9U#qG@% z3p#Nbi;)^ADst|7)qh2#!DW+E0b+wHA#wb^UJ!mJ5DBta%Vxv&JA07*oWe-3B92cq-oLLJ^?yecUx zriL)+sxGYJAkYA`!nY|+TVPUH#sbWQ!Y)LW|0oTpBbbq1?ro;DoG9X$-i!PCH`>tn z`E7mI*wP-pp!M$K-yyjU%SuAmM9{?&u4Evz-TGRTx!Of)r0RjG_17;*XSuc(a3(#A z>AhlgQNxO8cCR$bXJ+s2@LvI{vL;eKw0Bx+Cb;=$Du)+rtJi|q zM>S}O(yzKxnZ4X1uvk)o2e}9HQwY4E#hy>S>B@6cLQV|6DBWn@QbAbQ=3>3~KYPBK zi9mc=zSI`>Mv*v)ByXpZSsI|M)LBJI`*_}8nHOBm@5E~lG#!t-i2O5aoK@o4LwltI zQHB9e2R;Vz$2sMXcFLYFXjo|0=FQ48>)#4<(VINyG&Cdf;4wx7urX21A*%K?cTzJb zqS2yzEJB3nm$o0c0Pm}JpM9R26rC+y5J~5t(D24f7(~CZ2%VLI-w6&_p>yq_n7G$cW@*n>~Rl#uH=qEQ2RSb3oi)E ztpf+8oDLh)wH`x5N<%>%ZMVLfE{Our@|G7$DL%6Ijb*iYp~qc*k*zJotC+L6X(-Qa z&fml&WY>&1w`bmSIihfnLH^O3T=^)4lkZF{`Y%${3qDHK@l){^Es^IbzL*mEu@F5f z@C8YXe)ibRm@T=#-L83_v>-|nOM7{V^nlDZzWhV7!iqgdFuB&6h<-lA-3F{56ygb5z{;ag-h-pLJM8KK`>UE1T3rFCCVp{ z3pK{;-s0CCfn+l>bL_*~R-{xdK62Pjqd>+EYQHKX(rJMEA$(M1EqW_UfFMr;>`W+! z^y-VlfZ)(gaf|exy2lmG*g( z3s06P-umPU2FbMsWHpt7yK*6i+E848ljI(Z2ETi# ztw#9S7_)B1N`u0DNR(he>xNiBKwar5R3P)MYx3P(?78bzy-pLQ80;a>pyBn}+EM$$ zmUMy!9-~*kUgyx}UbBAy9$$`Q*P zRhUyoIbiBDL>9WmkQ#EeDwxY##E#0;S)Nx)4wYp1wqb(%F5QZ7?3zNQ)THv$3>>91 z&&p3ib9@Vkv6w5mxatq2d=tZKQR}!{K9H{=YLhc%@|JsWR76799TL)KY~{S<9pfE{ zb)#i5Vw1jK1mJ~K+a_(*8{ZA6r*JjkoX$pKlEA$1{Z2P%Q}O_lLFLuPxx8C7$18}9 zLCSTJ_v`Zu^hD=>su*Hzun|vIZ0yb(-yGqn2gq~=Y{a)s*}s!)?*;L zTe0pCvZptRVOTxczetS2RYejR1veJ>wCB{x_o4vo5oUeXMRrx`Jcv;SjvkEWr5n|5 zidN;hrQrtBMp51%e%n>4NTHag0sR|8wrSba4%uNB?G&vwrT^*Sqf13T*dS&sGVvYvQ#5F zSH^9cJ}V5d3PtD_>CUE$RalBG|<-F#-zjMVVo>EVe6*=Z0g@ z#7@4^4!$|UcJn!DT(_$Mxss=s%d^G9i709W@oG&Kst!_AaX+frB{ph{3Q zkTAF~C0x%mwJgHHigo;%vUzy67j@;jb31JHSei|aAnQ{e%Rhc@aY`rR+O9-mp zAzBuAc4JO#VeaW&6v^fv3kq97mBU=gtnDyjOT@~livBfw)j8dv_Xh`STMj$H4X1Au zUTK-MBFGmAAqIVH*h|bHbi)KM$hHGRrk&iwmxa0;)ycz zZWUN2r7DCy2_`d-oRSGe*4pf6BAW)mX+U;4Md>G67A)xemeq5dC={1`mr>wVJ{vm( zx3mJensQSIbIXeGX(Dm)B*}7BiTe_X(Q;yxLPwUIRkk%)Jk}Ft&nOozfGwu<-cL~i zdLn2}vVFHn6>bu@**X=3Bezxk2rc*7@{uRZD3XjL3tOrZ7;YkI_bf@^3x0~A)<{?z zoUoCTTR*T4y!Il;WXLSPN!4G_seV)2;>1N__a!7OekeXVrp0!oEE?xlwFE66{vv~I|A+*)LT2&9??fTT?q zE85c;my4!Y;8`BQB;a(l@-m=$O=@SlHl6OYi`FI<;lf7ehodCp!Adx^;IP`H6Pd1< ztrM04Bf{=ggV?FYa*_iJCh8) zdf2A$6_7fttJB-`g%=Kb3TVBB3`yY`G`N)q^`tpgXsd=(UnGF`j~tl~TT;8PBXD8F zb#*O*9<&@(n(zRv!@5UD9VTJ@~k~(P^Qwyv3} zyysZoz&{3kdU3#NXE+03=IQm2hv(wg6L-=1u;~IgJte<+$)@ZUTYI&PUTRV=P)pz8 zI{K}&6SCpTpJGj5k4LD;$`L$VqV-a8L~^w2;=6#$Oko8w_#KKlv|XLlkJ(M`VedaJFx(_Y>)NUkHD^$B zSDLNUK=>C8f=%C!5mb;UPgaYs9Z9+4fJa~mlDa`~M!l?5{b16x34~j?jKd&DBx$R3aKqKl4 zdJ3!>9-U2sxx%*cf^v!sw-pFe>J&fPa&WZ&J9=Wu<^g8>r}3}IE9B+W~_ zX|~cR1SYqa26PpO6`xzLZfo!h>N&0FfPymL=P261`BK>$&976&tis3DkU`!xp=iCBVB&r7A+Qe z7JpX-*CB>!wTcg@g=0W{Af}~_LF9J^8Eg%yS3*THeDp5-&ZI6n)vVbao+N(l(40E* zO4BrggBtqWIjz;|zMl;@Xn4UhGB$9g&V@3`B66>p+-08YxQO7%&6po{nIJnZGPJDE zQv<;U{ZjO7{0Tm_r?P-743!L*ykLaS0@Ci4O0Hjw87Y{wGIA9}u*G6^hr>%=_G4k& zVMW(Z6DpjFQ~`TU7L<>b2;nJG*9tDQTOEnsDCqpVbGt5%Rp&`BRw7()rZIXJ-IUz;?c*-}kQ@g}Vxx94OE(sLju=)xykkd`ijH)wPn?jBnyQ_2vG* z%m+c?L)$wKYriT$5Yz;E32&#p0BQ(`B0vz}LxB$jN5QJSp#VvYXLak=0UUo#)Phf- zt(?yHk^mrIP50XWR=M@ZIKKgs?+k!-)DVxo5e zy#0oSo|SdF)74WD#~f%SC?_c=(^fbI#ipY!Td51&^Br;ggM5#Yni zS6a?$f|8@qgrP4`MGvIPGusN5G+S(T1~iXPgWjOOUM@=Wex?=8aAAL&%~~ zCwiP^T>DCdN$Zh~v96t~vkrH*wHx@cy!#D|v)=(AnVG$n!`jj7xy5z%{yd;bU?wh59Ldj2jA!6$Hj^Ylc4?(2}!52NuXi zg%vOtbB4~XG!u808q8##Z+tke_J(vXCkJ^BsBrR^swq~c`5uNE<;Z|lSZMZD z!XSIGVb=N;O8l~E>N}N(mZMKa-eWPq5H0(CwpG_)q^k)IRRx82VWw|O*@8|4aCPK6 z?C!=8Qm-0puD$oGbs{2=d?}p zbny)|%%J$Py*kMc6nG`lUTU5O)b(bDF{|X=BzfevQ?@NC!0D0XR$Me0;sp&)A1I>P zi#RP2$sOwsacagQHVwtzOSl)%v{$Y#!E-txYN$?#WKR!hpmt((%Q>!-dO~M)vxlrN zxXlv4_mAAR>X{2Kz(hhEfW-mO=b27T<721wCOw^lT62_vqSD=j_+s}dsF*;2OKcR6 zb6Pq`aZ+r;y_i6h1cG-p2ZSXSBom=5^Hj;xUB0fYPii8Ec2to`DeIwwdCp7T&PYAA zHQIp5U8EI8S1>|I6;g6l8A}gp*Psb#b})4xWx0#PYbORC=CjI%li|tI3J$Cm&aI>L zHa_xBL~mc86moclRj^baCe_abEDo-+T5_1uy{;96**qa_Dnt{gwbZ&>g{C&uQLlcI zoopmn%x1rI{?#6nLt99uHyx^FV}(L==KRB@}nI+**wu z^{bYWY+0K@Qf;F~3~LpmCX7k6Xe7mp291hByF697Zi7J@ewQ6)uajYVM5v=w5FsM@0?ii>P*v21FJsL`U^7~5(Ua|BMh+j0?IX> z_Lv+-sYWkK{zmYoD!)QWOllJo5YmUiBG$mLRl!~1`yAE%6WU6w(3I<|;fp01=8epQ zaT|e7QaqQcPOzol3R#@pjbx247&7q6NQ`tCr#6VA%4D~iG#TOTOVCJC zJ$1*aUEW$t+KJ7}Gm&^qA%lJeozEPSXOcD68CW1j)r@)_B{yykIqg)$$1hvj%Z%BK z+lMzdtry;b$h&~=VDHo5LDG7P9L2Ull13Eked3ln$fNdHKHd`II@PKdI~krAlJcX* zlOl?|5fp=6lInuAF=|&Pz?ahQqcyEeu->yDA7NlbhOr1FRH5@c*0wTao4sjye4_+c zb2QE##nLsBSBGD3OIs8a{hgrmf3Z z@wH&Wos=NV8KQ<=2dkK)!!6N!mcw?NZ5+3Em`{}Rm94D#rc!x8!;c@PXhnBVb|4|Z z#{0*Yai=&d5VD7(A|BTCRQtBw@n_h+7M89xN1tA#cSt<7;x##1t#pP=dXd}-^wKs? zb@!DQwt(`AH!7&SQJVuOs>P@&TNICTnI}xUII!f}nfv(S;gE@ZjWx=Rr2OwGJGmZ7 z7KNKR<+Q5-C-`Is%h%(yLWXZR-LrD6)@jp|jxCeMI8Qzmpe}?y#JNPnV-7EZdHqyU zssqjIS>E>tk)+%)+{~hMVdh2JFmWi4**;~fT2BJrDP_f573irD`=+HtxqWv8X4=To zDhuKCd9POGlPj|BwoXM+xhdbctDG|;R0SSjJ6pr*z+?)(>P};UJwHt6uu6R(f$6>} zoLtHrHPbMF5h{IH-QA^oUkQ%KHXAn7fjE0K58aEAyq?mAwB{ETv~^_pUl(F*r2Ri6^f#ZXvJza(Wta)DK^EivT7}& z#kMLkXp3TvY+_14l!yedB5>(fp3T#v-EHbn>T>2m^b+sce-|lp{zuIeFIImP1Ox$( z9R;lodLoHc5KBhEVGjG8Ps=jpkU^t~vFr$t9TUE(=?pPh?E@lCXAqpTilqa0m+bEPI8*z!y+N% zgv^aa`ZzJ#Av+iw9<B0;hNx|NKdboK}!RIHE3npf41ZPilqzN?V zu-VTAQ85jasgC2ei*#Gfwj_>pn1RctBU9Gq9Uyv&i8sZyBSXNDp5 z4`*$}=iI}zl2t768%ImHXHrKz*;a=B!lv6uFqqG4+oFO)a8|`WS#uqwk9BWbaoszI zFwjwkvThx(G?$vVnq2J{!;X-$4i^h;1Om@1KdPqPm2<|INAp}?PdU$l#xtp$aB0xz zida!~#mM$FMM{MoQF>iP5-{7*LgwrSPAH+ie@-G2k^yM@jiaYb4I7&@-+in~q}-2H zV1S1-yFknfnRL!LQYS9;uOqQGrORL|*H0>`iU!w>qK0$58wyV0eXQ$*jJepB*Q*Ayb6waRLvaJ~%Y)}wvp(^&H|?CF^Z>>~|jmRY4Py%meS z8(4`AWbYZdb$Ek#Mkc_{i)E&X9;)_7eHg0XlTgtJ-ggCBeW@rwE~bHF5_hOSbz-y+ zsFZ8VE&8cO=@b`Q$6bO*>M-^6%P#YzXjIoQ2!=Xtq3pdVnI*$Gw_5;e8X41FoX(yl zEb;k-Km)QM1b`_3QY55Dt#PzlMMl(CH5C}u6&9$~8iNLl7K=uTqQ;9#BE}uL5;LlDK(<8v|!dPjbhl_7A+N`v_{n!ts6$#HpbN&qfxO`V&4s~ z9eLKV*7%s3QZsbeYjy1B_TN{`A(+yYh7+ZF#}S4_H4J}}(^V@u`tKsns@$=hP8yL8 z3A|<*ZHO8>N7v1H9&1WF#{*%5!N(dCxn;MtfdgWUaa{-EqTA>LZJ$am&I;i^u$wS2#$S@ssw$y-iN|RB0!6u~JF>cOg7WvUzz-p0V zHx}{v=Sl?j2W&{^g?YIq38B;mqTVWl4ViS)J$;ht%7jomq+D%+!?hvpF|y-3d>_z38<$D3rN^s+2atUD#(&I^r z{1P!h(LTUKWhp$?9&94nn0xA9Nj&s&6^YMLiCG3%!VHgO+V=Sfa>A-SE~dtTqI_b& zYh~hX)dC?g#@fabX7Z{IIM!YBXDt$G$n;7n17_nYwoZS~W=rUEOQ>9-RuK2dNZlMdP)bymwplD!xODKXzcIZBckLAR!8C?nCZp-6e1 zY9w-a*%`6w6ed1}iQU6eRwhT`nD@5fc_*K%dQ5q-q?|B`s`~cRP1%fcQnHcapnU%s z;KMVy9=Z~DO-Qn5KWK{K_jb6~?IA z+l@h^QKF);sMa<#Sk{Xbq}3KRk~M>3t)jM#uS-?O6~BilV64*2XrZWuq91F^a*eH5DGKUY{R-Z+DZO z*~%A_W@B8sT*nurV{uC?R8@u5c$2LAL0gxm(o)w?3|cO?(CxYIQb%NRKLN7P%chM~ z=HzK#MoZVBO}xzLc`M9wJBt`0tg;zz#g05``~@WGPLz=z7OtF927R_IfWj?UGanMK zd*z)CvXD{8Q$GX*P~|ztv$2-R4KSC4%JoAtBQq2@DI|FfJ0{&cTaGgiwq<(7c?Bd0 z92zl4fRIo#=HE9ss7`g*bV+vluwWHUWwQhg0!0gy3JXtn)S;s!j@%uiXllJo{@LSlzWZqh}Rha`J~lnbB4T|Q8|@phXluNN%)7(Gsb z6n;n#OZriuXD7_5H&{`d2;&n~t5~}YNI@WGY61=#-Q~KQQmQV0S;+aXAdc(KS>6Hx zfBBLEP+mV8G9_C&KZS}cH4<58qQ_5 zhh7*$Cz2d{0Yz|>-c3kS#^O^5V&&e6@({RO;U|j&PTFr>(sxk0VQ zibMu^P>&iurmN5i$uVL?gP1BYkmmFnD`~c3d%|$d|bB?SoJ?D2}&mE3J}P{Jm9GbS;;h z=6vVtMKu8dsHfp8yyj<#N>!4f6tZK=7f=s)Se9*mODBAkk6eSeWXyQJRqCH$LDjh8qx0e#hkI4^kgt z=A1M<4bY1{&n%Hp>g(d2H$)Gd^LPc%UAefEAagE$Mw>Yke%hOwAfmYxXaSUUk0UY- zF#ARc=%~q8&*qrnnS`o`$8>m8V7FT2*$g+$@G4BI%iTFs4|!sU9~u`=9_1OcxR{KQ zN8Kz8H4$hMTnQ~3B@({PD@d53?z87j};E9bm&D`f0 zSTeK(PneGCMi2!~3ze_(rTcmSk?WIm7Hx4oD=P^1IJ;10?!L%OWQ;M&yq;fGvvx;# zu$p_I)t4z)u}$Zl!!wj!hnS(gyKlu;?q^`n9Ezh|@vGQo?U>q}i+QJUPJxFO+Ku|O&A1yf|4H*>c$0c*a-9K_G$iek` zhZ}h;>eH?bF9m$E2f1&Xwvdlv&Tls-Dll}z%I6DhZZ4^K=@yD+#`E$tY-Ed<6KqF==jVS5M68*j&OYS{{h;XpeIkQp@2 z@ggD0v&wm0;N|2=USqr=O$|FIzPKNzF59(T7aBl#JPj8o%|OXXQ1h=e+wLyDH3v%c zHtG3KmnM1(Z2T&x`qW(_kBRe3-7IlN{z_$jM89@vN)G_ekfYOhI0ap$y1lqiB29f| z(G<#@YY= zm0j8KPl&_Z`+b|GXgBtf^{{j&y|UOscs!nx%zY{MG^iIfrPh(X4ME|@9)a|o>DMl( zEF7%!g@gNHIEg)|o-FKm6;(kxzjX#~`-JX$gt?lX)^XO{kD0OwM5E8Q&6w|Ns*wAY z)^yZ-YtCf4l!B>qRP=6Mgkx3Dw5qDW)*XRQah2&5f+E>$HvH2LR| zw(EpJN@jiJQ85?-rBnAs`h2j8-ZN)NE=f+hWGlMT=r8#ab;IjcD6ZRyDDWvkg(ID7GvWqR~+p){RtcOsf{7 zYKpKy0FWdk00|NS#N|lSS+)i>OsP1fA#8}}Ek+i*Q4S1kzq35I%|lCzcySw%{+ zwUa()qxEBs4j6IAniFn2Ql@NL4Jo!4F(Sw}y91zEv1o>r{Hcw1D6c0x(#4SIe z#AzEt(KO1Z4Yc*QEGfI`x#%_4x#KCm=#rp}v{}UES!HynRq9mBPiD0GP5iYc z8nD~SsJU$}-Dx&L&tk?Fx;_=Mcc!j{GdQ9#+iI@#SWIKNud^9~L>-tdXrzsn^rD$G z%{RQ07_{V-6m>`2YJtb(M{5L;#B-Ui=ZkzZ31sRXGU2pR-OY=Ii>?Fq6i zZye@Z_WLWy3tA8>QYnKDxorNOlF2a!L-O_!uLx@@k%K0uAg;%(4nwXpwCLkzYQ(A- z-04Bp4NwT@uJpH!cTJ&Dfsxwv1(fYZ_{?rSdT|or-L=sH<|-qZam?{1y`7R_x#Sp+ zT@^YCaGJ8cM5zZ<=8~3gq1Hl|XT_D3WT`)@^K^-P6!P(RZ6n)RuKEgGUUPiO!a~J=s!b4OC+y@=Ih*9Zmt3S*I@G6IT(y5K)f}gG*cE z8Q>3<6AI@tN^Esm_k&}G&{{|~t7k}$v4pIV9Bt^vbk-PbD01K$mIV<9$9gcY5nED* zi!Y~c_iQ?VKC|1@M+mUIM_uH*&Pc`EXU>)hLGZtIcV(0gL%~jY-w2g*Uyy3K)uhxP zp!ZU1+|KEQ-7?72;uVTh>kzAyVb1DQ)9lw;p9Tq=5!N47XZMvYgRXsQ zw-RJZwXXMay(d*GRWvlvyRm!0&&;NyvPm2w00|I66-L@N!dk}I)flAK$+2r1)LSOj zF|1oriqut#*tRtr1+7N0Y*Dq6(Y6aoV_G$0v~7)&+BHd4imaBl#j#ZujTK`WqScKW z(Ws+h*tBeHTWHoaV{BSBqhlJyt<%xv=XKfL=I-g}@3|=n_+1U)gUvz-%w_x?kz$&% zuCPuPDGk8MnG9p*{s=r(v3k%*g_5o4qKKWlPV^N?4wfwH;^k@OOVZ-Xu_{@Hqq0y* z+_>Cf&0}Z~4gxvQ6tT4tc?R) zCiU+Wv;*Iz52HbRjnf3$-6b2E)8c{lm9Ms2(6$Z*a1}y@V^Dz39T0-3QY4rShc2mM zSTN|lO+N2qnOB&@VE1F>gbNnJq&0b055<=-nxo@` zxWuzd`Wl@14ibG#e1;%>C`DqFr5)S~9tAhGEjAFm({@qf*&{I1rL$z0MN46l0mz1J zqS=GGzXNw7I#Vkp)tj@zp?N1t6@z%uLWM?>amNm&9b~-050ruFi=lb-&xQ^#Df7gq z(=U5Fh5~7&8|bZqYfPR=C^!~{jTJnIb|KPt_EQ~`>s zsJqe*FxO;)!W?V_qr{bicTsx1X?y%PV-UnwQ!L zU7G>yQ_aSGOO#6Kyp?@IjJlQy4KGU$4HbuWAPSQ#d8#P>?6cb|q-hS1Rya#lW7PB2zFa4XS`&wUcrJ6)PkSXLjzg3yPs4aPQ|wtx zsU5NGe)e??V+^!V4iO0gkO>5VNRSGkqiQix2E|2+qN+7w zqQ=@Q7K;&VRU2$p#i+@uEo7pNi(^z(v1=C57Bx{+Rf;W8MWbpcHANQDv_`1gY+A)* zQE1vW)M^7!sMytuSk{t1a;u9}TNc@xHMTXV(rAi^qikzYR2l^!IMs7L7S?v?;ylJ8 zFXMONQ<=@0u#NER;uxkf>-Fy>0LlkQdhSq40FCP4C|3YfC&G{6PYOwfF+`*9UJf~d zILL6tj1LSSYqwIC}_mhq{x@xQxT#dBd%?H-elB$;gQG+E`3indu4D20Hj$x0X&Jj7r1^QoUftuPy9Q zjWrZTG?j8i@mm9`#B-fd!Sa)&5_4j_$r|;z;V-gNrs)wgyr{-U-V6h^z>}x9Rya)P zU5G_Px7V@?rJV10yy?uTI4rPjH`4HH(2642PY9utDoY+&8QiZ;;j#Q6$`{&KO(l`S z?0Q`d3+8zjx(_IHM11M6Z-LdfzN-?TZh2*Bl?%p=ZzV=ZRZeR4sc|?d?OZRnCIynb z7bR7e4#hJhYyweewI$Bpuyxg5Rtf5I@Pb&MyG7&Jh3^Zb0NLBc#G(&G$!V3>9Z3V}~*p5Rgh3ju0+R1`5Y4KHwZskK!4BDbkPq4W2R z=zF-r6AbR^ySv=2kK(O_kqOo;l5Wy-dMvzZYg-7b0LSG)=+%cp|vWC))qb+H161z!l)NfS<>%J zs*_19VHY+rN^2+xh74&%zLuV*2el5+=9+_X=1?IX;Nm^Li}UVEgWRbQqRO$0-hAvL zX{9VvhA+kLNTb|$R$OJJYe=+3@K1S7wqsl;lm!Vrd&KKz`W@o&yh8A{m?rlsbOYr8 zg&lC&Vj`)q_*&<&w&343)EfX|?w#ue%S`px6C$3Ay#h}Q7+I{3)1pIkgEi2&-aejw z-!FIY=cd;6HY*zziwQ}#uxgA^RBfWvRYkF?HE7#WsI^f>DKQo+XtfsDv9W43QHV8* zS}S74);83bqR}O>Z5r5(go>gmHr6VlqSi63iv_ASEfogU2B@~E)L_(F*wKnDMYLFp zMU!J=MzL&BQMB;*HoO+Q&RoYBE^@hXa&w%yaOXL~Na4B3%yXRP=PQex=Nyh}isv}V zCmci+NWn~rPFnT-+wuJe<>z0!v&GLGVHd zDG2!EKt&CT_F@oel<1yu5=fP_;Q;_z3n7sc1|zm3B8#X63#38HCMa(#K)a|u9OLBR zhoNczkQ6egE<-voEqEE7ia5+tvNBBAP6ZS%r_&@WKxex7VqQ-;y4JsTskAA%JV6?z zZUh-t(_=-ngYDmiIm-h_7zn_^dL?41sM+|Wm3l^Nsj4Oh_|dZpe6iCLo~#OIXUMRz0{ktf>0o?_TbK={`rW96RZoK?{DN@!xu- zGpAq_tFGc82TXl;l64k|fmoiwM5uT3bDm{w;_r(#JGdg}6?`02fT9B@k7^DJb?yTBBdshtp z8eT^^xaTw^xh6zmaRF881o6enrjgd3Lg_*b_~UPW-L_V;c^+2 z^D>uafcw?%gb}9mDZMPx+ZFq#|6QLWxi3wd4=}>SqzY^#q?^u~@+i0CW!Gj*)}XPm zowBm{fbmx}v>={RhtP1|YW&8T)2r*82-~-+$pr`oaG)_zFYYhoIO z7A?XA^-(ItV~ZFtB8#lm2FxiW6@++d`-&!#@PNF{R4NH7HA4>!Fc9Liv2Rq@MdVi} ziK|5ehQc(X*$}h46Tx-W5Moz0$w~|K2Pjf0o6YG8*w0k^*z0-fetXoAE z(X?ufjT)$|YZ@bHsMak}VzC<47~2&^trkmL6jqB+8(VfRDmL0E(NtAMjcPV46^&@L zTA4tX5+gj(Yw%=yjgg)W70r!3X5JU&WfJu1YrQ27fi<46|A5XcB>2C>xOQs*V< zUuukDvcE%Rb+5M0K@#%25NYY$4gpx&S%)z;huu9~<|2{B8HbFvcb4dA@;w+rlnuMG z{75e;)*ka#7D7Dq0n?Jg+}n>JExD`VWXt2h#E4LzEM8e<(TOus?%kcO?Z`lc>f|Av z*`F}l*i7|?$}1+IvUn9Q5317;#;iongd$gIA``PN*w@0rJV%1@c+Ymkctoc;B56QP zX8R*Ou;H#AFs4cdTd6M;T$@DaHDoYxVrJ~k#=w*^DX4~{IqWeS_T0!0NX#IIOGpZF zc)2HP1l~TFPj#kj7&qk!kx=|pgNW65TuCM;MDOh;cWXE zLmGM_6O?UAI9XUo^}P)yKw?jr~RIw3i@9BhGDX*W9P397$# zFx)t>q70jT=Q#6qwO!#-y=hQMQv{+BS<8qiQNOsIX|H+hZkTZKAMh zDk~Le+QeAeD#>h?gJRe=$yzH=RB9_4EJmoU7SXn&MMbvJ6^vRnqiHtS+M{ZO+A77P zTSnR_(pZSpMxxtMqQ#9=S~ahr5P=_UzD9@KQCu;F-1$m9JN9+3& z_Txh(G9N#=9;U+JwYW+a!d}m2HHbzv0bGYhU3u>C#XLvMu*g#g*W<`=)SJ|B)H)cv zSOyV5yfO+$=Sqf>RSzd$j)_ij!4*nXc>%!Me?Ps?W7(1HED&{ssaKVfASglKVlRd< z>h*thR3ccZvQ4u#QP7#Klc47_vijH_?{U#8B1=03#V6cd3xKX#T$3pGFY5=KakJzY zlrl`p*MWEL@KWaMO-DC+eW5p+7~2$SGOTcMN&>rHd*a3w@(i{FCRx_vy7V-^|>?a6QkH(aQ;&S2OvA)3UjGPS`gXn8XXy#C}GvcPzpA+kWp>$$h zQhK0c2N$!JuH~InjtCy8o(-V$PJCyRo#B{z22U_HkxzzhYOw3s6S$n2lQ@>yI>uL$ zjFb>ZaEKQ8)^co!Yh&QMHk5;Bt1Yzmu*z?sh<>( zPWouhbyf%J&WtU}XNE%2VxXIdctYlPq-b&0uSYYcHA6#ZQ{2i>yWY)t*0U8zD3UZd z6*-IDtnG-%L?ro<+pt9{=9sf%r(pL@I1m!KIVqcKfY6jTypy0p$l} zioTi!?^cZACRk$=hTs}ErWD>osv+cA@2-my)>tJ)7@$pLuDWIjOD@)y){Z5B-?V&D z0DP=O`EbUv_D)O|&17(-FYaxq1xI{Fv4!IS4l(qC;Jk_AQhVh@i2ZQUJ}lw>?^A7VC(Qf)hL8LgWz;D9@= zZAP)8*s-k@8Yt9ljiS&{YNJ~eTVUIIn{lyGMH^IGV#cDh6{A#Ii%GVzXw@WE#@fYf zTSn9xjBV%e>k)q#5q=|j3M=xUagu`A3SRWdZqXRUsPIlNBK@PMo(|b$@j%7>H&V|c{Qb@=V z3h0aK!beqL-;-QI)f%>AME8NgCs%4QsQ76~b6l*vV&zH1l023-69)N&3wn+l!4P6B zir!K7ikxtS3j<4>5c(WuQGuf&_O!g-nEch|meVlhG%_8fP?^t*N82qBPl$7Ve{mq` zoqbUNt?HJClTpsKwI^iI8kbs^*H>gU-X33W^qk*uDeargVRI-oOG9~ceRs@kMIj@N zk<+VI`<>oI6mmhbrjjwKS*oD|S(NotE`!LK8MO`7n`eXv3x)o@yQtc-q1oF^UV%B7 zhZWpL-fAqbc_DT^o3z6t^kqUhxj&u`NK+bc+O9W<1yjj9aNWygz+hO(G7mnvAQAm79^^>+}+$nv~lilb4bO`IY_IqVm$1d_E_kNqWq$X%YJqV8Hc3jmaz7zRa6T_LJWz>YMO@fYP%(^7a2M|#Zp zAY)zvwe5I40^?TCQ1dp0Pthttdh1dzE9P(~Jaq~}=d|t5Q~9VQHw2-kgnOqH(c~5b zMT6DUmNHRs2r{>_a1H_%Oy@y!u!)?W-W}zJ=znm+O+=+iMu#dgRf%F{OWt0Wt83z8 zMMkk|F`~s;nxfdEilb=ON{wq6BGGLTZAGZDs>Z7rHltKq7_4BlR*g|uwWCJGlVa5s zXw?*Lv8xppv1=P@BS$N2+N+C2sMsu2TWGXot&3R3)fUFuBTz=xEsYVhRT{;k5n|ZY z7Wf-nMzs}1qN}e=1bV5RPc_Zl{WC%RwMO4p>OCQ7O=Bad=J%UXG$~cCH4J&j!4z%+ z61cxh$gjFz#m8Qt#hm8ie5M}8eZfoiNt)~ORL#f;c-DmQ zw;a8W-Uom1J|*H__upMwu31Ehd^Pf6!X1~MgK3%AN4+?E_mmMPk7K@=@3p#!W#UCEO=VL(ZKA#azIUKmlheI7o<|iV3XYWuc4W{WR;xCuuf!q6&XWAGv93QDh z`rFm;lLT0~1S^@tpex(>oO~JG@08Wo@0+~u^aFir-sb_E`4&4Sar8fIr_A@>co%Vm z1|rjukFijo*Vr?^e0oZrma*@9DmBeXSwmdD8WTklo{~H!{c(mNteWp*LYjA)ACm7v ze)~(8X_*8aP~Xj`&$r?R0Y8;;qBkK^!{)Kh&Vi?ilmW(G1-V1vHuHei@@Vy$Sg-U^Uj z_Sa|ffSPT$(WCH4J?uqdbu0m+SIc=z`oR4kO&V(bFTG0-?$0iIU&@@XGrXp#@HVyk zWzINI75uu&wNgvj&fqS8T^==!3F}220fa^oAur(%pe%bv_Zb%@+-DK<%#78LyyxEG zu@%Z0Po580yxL%^)mo72R~K+M4dmg(P;pCjfs1l1H0odM2jJGvA6Fw$hAv3B$>-3~ z-*L7yjD97158UrO`*5b4*zf9=$o7et12D{cJiZP%~G?AzMfENxP1 zEwo!fTQbyZVxwCX7LBYLi&(LUi)u8LsKHi{wl!kWY;79G(LqsYsw)MyEn+Na)K!dH z(Nt9!wx|uQ*;{3|G$s~cdgy{fMcy%o0Wb*pID z*ZuFhbk-m(qS0efQL0|RN3!#dd<^liBX9v21Z&#Bhau&OeySf>1fI51JIMf#u#$ff z+tus!`@MfhyXW&~eF@{{eSCL1{P&E8Cr|N3%>M>sCjj|sN(Wluj+ZMCMCW9fV8r8J zOym+!Qx=?-7Cq60hsJ3+o$WjoGl*EZ%Yic56rnJ+Glf#3qLW-KlxEenB^9}KKWB^H zcz5xguel{fu3p$xflr(ll@(~NOI2QcMa5Hn;HAO>fYfQeM=GB=2qjNMH;_6H3{*yC zw8~Fi@_h0P`Q9u!f>|_>Lf-;BVx9fP+C*#Y_GrkPJn7p*Uk9|L@&yGh63x-^p0SV3 zZ2~9_Qd7axqSUqnvqFa6nOZwPS}Bd1X>Ri1XM`Ai&=CD+bq~8RMGSZGA}*9aUES0I z*Ko6V$I(1{aMu#!MifPy549U)IhKKV1H;V54KSp&?(_uPS(aJ)lYOLNGC7>5XtaLI zD5Z3mvq^Aw*VbxqT8M`VSyM zk$3h87c!QE1Fc|jV078~fRSbmXT<4?EIN-O>VS~pNL6((;;6R1?%}BmN_j67go%Wc zGK`rBtUb1pW6IdwBslJ=YJ#CPq;gm%FQL1tj)jQmSE(eaZdxZI!*4j!k{3^heMAq; z<5d1FC(L=wKq%|V zmcx)WB-i14oh>O|OY-m2$TW~Pr;zAK+?r=NgWJfKC7?qMrb&t}oSL`Htgt;T>YsGy zQUIx6CPd?U&RXOIk4abudzUQxlt`oq9J8upd9yvF2a#W?UT0#C3OhZiiZg~VO!lG*Zi&N4mf5B%_VrBp%rPi9mCsIkj|DfpDeBfEReK3xtgQ>WF0FP!>_GXF zL==H35CTV7+cRjbV^%R^RT`shMkK6j6&j;!MPkK`ZAP?hiqUB*g4necsMd(JV-am8 zwlTFv*tRIKqS3b4)fm{=)uU0i*oqAi5v@kW2GLYi8pbxnZKBaev}(rM3uA4f(qivh zjbmChv9sOewCictpu9K3TW(!B*KKWeuSdyV=VoocPggIa=e6Bi#bMPQ?*Nlj0VM)S zhqwYPUH&JiYXtyAhwStQ`m)!K*Kc*>zN>1!2P?;G$*s5KwcGLDF3Q6WAmT)j1PKs= zLBY@jeMACF<|3Tn&_HdxcCFUwP1BsKU0YpW`Dtsmw%xk(_WFSc5Wt;}fFj3WfMNCy z^`M{xc9Rl79{>Re5xqnZ4S*wM!G|CcV2C8Sr||%bI1uqB1WA6N5kcK1jX@r#csvn5 zH+XPCCqhwmRUFpazH_gd*G}5C(ek#r)1_^?c3MeCxfYm7i85%wbpQ!2q=6C>1St>+ tD}YCcB7&J95^e}^m?D6R1`tKP-^daGumFMRsGuTcBqjmJFM!k&SH%DT literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 b/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968 new file mode 100644 index 0000000000000000000000000000000000000000..2b0938aa3f0d3e1c9f002692db98f9cfb92cc0f2 GIT binary patch literal 27 ecmZQk@|Ey)U|?|4^5tPrXJlgl1F^>p0&)N@kpnXT literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output b/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output new file mode 100644 index 000000000..62f54ca14 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.output @@ -0,0 +1,51 @@ +program hanged (timeout 10 seconds) + +SIGABRT: abort +PC=0x5e9e2 m=0 + +goroutine 1 [running]: +github.com/pierrec/lz4.UncompressBlock(0x820282830, 0x6, 0x6, 0x82032e000, 0x10000, 0x10000, 0x0, 0x6, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/block.go:104 +0xec2 fp=0x8202b59d8 sp=0x8202b5900 +github.com/pierrec/lz4.(*Reader).decompressBlock(0x8203085a0, 0x820290240, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/reader.go:271 +0x189 fp=0x8202b5a48 sp=0x8202b59d8 +github.com/pierrec/lz4.(*Reader).Read(0x8203085a0, 0x82030b400, 0x200, 0x200, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/reader.go:188 +0x1156 fp=0x8202b5c38 sp=0x8202b5a48 +bytes.(*Buffer).ReadFrom(0x8202b5d68, 0x882042d260, 0x8203085a0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/bytes/buffer.go:173 +0x3db fp=0x8202b5ce8 sp=0x8202b5c38 +io/ioutil.readAll(0x882042d260, 0x8203085a0, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/io/ioutil/ioutil.go:33 +0x1ed fp=0x8202b5de0 sp=0x8202b5ce8 +io/ioutil.ReadAll(0x882042d260, 0x8203085a0, 0x0, 0x0, 0x0, 0x0, 0x0) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/io/ioutil/ioutil.go:42 +0x80 fp=0x8202b5e28 sp=0x8202b5de0 +github.com/pierrec/lz4/fuzz.Fuzz(0x8820479000, 0x1b, 0x200000, 0x3) + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/github.com/pierrec/lz4/fuzz/lz4.go:11 +0x15f fp=0x8202b5ea0 sp=0x8202b5e28 +github.com/dvyukov/go-fuzz/go-fuzz-dep.Main(0x1a7f18) + /Users/pierrecurto/sandbox/src/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go:47 +0x14c fp=0x8202b5f40 sp=0x8202b5ea0 +main.main() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/go-fuzz-main/main.go:10 +0x23 fp=0x8202b5f50 sp=0x8202b5f40 +runtime.main() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/runtime/proc.go:111 +0x2b0 fp=0x8202b5fa0 sp=0x8202b5f50 +runtime.goexit() + /var/folders/bw/wf4p9qr50pg23qb4py4028140000gp/T/go-fuzz-build320605510/src/runtime/asm_amd64.s:1696 +0x1 fp=0x8202b5fa8 sp=0x8202b5fa0 + +rax 0x0 +rbx 0x0 +rcx 0x0 +rdx 0x82032e000 +rdi 0x82032e000 +rsi 0x82032e000 +rbp 0x0 +rsp 0x8202b5900 +r8 0x10000 +r9 0x82032e000 +r10 0x10000 +r11 0x82032e000 +r12 0x10000 +r13 0x10000 +r14 0x1 +r15 0x8 +rip 0x5e9e2 +rflags 0x206 +cs 0x2b +fs 0x0 +gs 0x0 +exit status 2 \ No newline at end of file diff --git a/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted b/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted new file mode 100644 index 000000000..4b42bc150 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/crashers/0b8f7fcd1f53d5bd839e5728ba92db050f5e0968.quoted @@ -0,0 +1,2 @@ + "\x04\"M\x18M@\x00\x00B*M\f\x00'\x01\x06\x00\x00\x00\x00" + + "\x00\x00\x16\xe3\x00\x10\x1e" diff --git a/vendor/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b b/vendor/github.com/pierrec/lz4/fuzz/crashers/169b44c5a64fec4d8e969d25d3e4764c9c3b604b new file mode 100644 index 0000000000000000000000000000000000000000..501c796d72a3966f73687757da2c5df5add36b1d GIT binary patch literal 66 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±z73{sw_E!VpeTfjmIiYz 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 z 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≺2F^7r5H>b-$o!1-${Sz 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≈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

$E(liw%9Q0BG=YW$2rY&p5A5z$IFuf zH96JIX1k`BCv`u}U|_Zf96-gI3#-I+}0T2*UZj9)z{jeGbID+oV)X- z>5R*#7mSY4B=LDTU{p19G47^hNS!SZ_4`~6cl7ZF--EU3`=XGp-K$86!Cj6!0<4@2MlGhwXrj(;_jZx4UTD$% zK(;u_kz~!I=TQKt46=)xzs1eBqVf?kEFP+S^*l@*3PJ;<=P*-1|jKNXI zD=-R0BHmx(S7a~$}L#c)@%HBKga>t_qY5D`JH{BZcI4 zA8~18ps9=St-#qIZrLT9e}mw!H)qiBom;b|*x%Mqef|GMzX_~pCUie*y)(N&txkJ> z5XHa0Y5Aq|^);e26Cq@ zaboj>tjdff9;NXGl3Dk2dDl=6t~SN#q~1w;Ubf?YdULy>5$R16XSxk#v(Rnk6Sbe1 znOA10R`fdue>bdbK)2W&s#OPvzk3CFXl~AD1c-~_c^I1&7M`=H3Xg-?$5JaZBZtPAHWB>wR=Q<*!+^`2Lwm26 zbXOSfI{1R$?v|q*OydA5CC`H^VqOzWGz@!sc@UT_NZNCne)jf5C3d&Pn10kTxu6$2 z#w)HGx}Bc=CdXo4EPDAa(|NzSVc$knpn@wpPc2NNYVjT;L`RXuSrk@);oK%O(|Cpn zXh%;~oS|t~niceuq47KUylyuMGOtuiobXb*cKer5YU`n<%w0kbOBWBt@9oQO@zfL8 zhw^leauy%&Ra!P=qsu70Z)6(o$Dr-W{-hN)%u{86{#WM0hG&|AH|=dVpE#?K|kVf)lOsTW#{*69u?X&~Oa=hUZ96$K7>#XuD^#@+WXi5d~ z`VT=0eIlbsl?A9Ho@Tj$JFZOZmqyq;*^$>-Zx__L_tfZ%2Y4{*-hPK4rb`6_!sWt* z9b;<`zBSFRAy)VRZJfdc3!q48?E&VT9{k7jNU7E`VUkox0#HGn&i__7;a%O?#6mbD za2T4D9(axO9Hl!2wceU0t%ZEsfA|jpIjn;dA^lvv<_(ZTI7g=baeI9n%%_mA&4dX9 zUAr+KHaV}CP$Qk%`(HC667d{C&uQMx*(OV=Y)PUl!;B?a##pn?jCJgTVfMMd`}zJJ{+ow$?>(>O z`8u!H>v_&Wwwn&1%ony_FseELB&VkHoos|vHlEAEWFZeN0hTPyrO^-Ba?so<+r~%@ zluX2vMW5)_j{!-juiVr+X$h){riAq`bhTLJDbGHF5k9xF!FeV+o8eR_V}BPuz#H1I z^O!!;wGjflV4}R9#o6B#Jj%8K*&Kd}f|!E^d!1nz1wKJ^=H>{$wT>iLEFbxXk{y8R zt21nAUr`0v27pz>9tlKqjN4*(K^ySpPADpey(C|CPy%aQc^ng7!Z9WPS;=e`0H|+f z;Nqq+`KfV9WhFpyUW!pa|F&v@l=CI_n+T=H!tTkzaavSw>K^x`GO7&qXk#xI8#kCp zPnIWrK^!nUDA6ha6GMwylcW)cngJvWCFNHI$B_dQ;VB6eH!dGwmqd?a*Bvepb(T+b z$k~KT>0}Z^5kg$ZI4Y4Uijd>g?GmpNCIGI*3RRH>B@y-zO@KjkdKEB3`d>_bJRF zCmvE;MzOw{PP6Z~=~eyR9J7r;BVgrYGiqq5(}ss{;X0@^JO4nrGh#u*a0iE#fof}a1NqfeHij>6Qk@;F7`2K8(14wC! zs|R=oD`S)!=PhV-p8-rUY1!%^pi&P%I{As|Hj^NTIb;T{e4xo2UFQ4&%+@d6V-A20f{oLT(sySsb3-!xP_o;OYy5#Y{xJpdhI}J ziX|f$G5_cbvGjLi{zc-9zJ@-PX4Zb{C53rw5? zf+<394#;QsZh%^O)q`&FevM}aPjp^{6lKI)w@MuK0;f(vf2Zyu z0M(WEoMQD7uG@Ve_1TM^2$hvh1(=XE`Xw)*5J*?WnD?!~ogb7FZ||mfWuo43s#-DF z?OJ2fpI4bY^NMZW=pKay-cBy!@$1w$`ycQ|a@LJ$vA+{bm$nv>E6o&1ng%7I#OrCZ zQ0(a_{w4bh8AV=+N*6FnO`@^VtUXM4LV+cUzv*%;<_Ujy8!D^xv)8qV#Zr}6=n~yB z_~p8AA|Z_;+Mf{pbUGEO#@eLZqHXuH301@M#l*N~1@38D+y_b-!IrWC3YmWeZpS@W zwZS~I3DsupYtQ}4RGD2l(7w!?*VQXXzo;9l!MZa5F;kmeirDhH#9S=&T}6=Jt4HsV2tLZuQ<&TE0_;rmWr-`M%29H$zObI{p;&`$UMtO4rCD#YofJ*-wydT_RrYis4j|x-QU&Vy9@Jo>bYd{fI13^7N7QF-^JZNTdP za*IRAq=f;bGxpfJ*OUak7*5L@+VESZACF>2uB*35u8;EU_37}l@-HKtr8a{2+q!oy zNkvI>5754v=!jn=5G}#5gp~;Z2m{2Ae5rN87~Z)nCf3v$T1$jbt-eA6|_66<){l;&2GbAQF$1gh<`0 zOh`LNZXmb#VC`Fn=do3-k^_LC1R2BgIH)o*}4Om>mA#Y z6h4+=!gP}7MF3De*GZ7q@17N89!;J(0Z z6C}0BrUJTi&hxP?fIqOZgdV1KPTv5g&H&eF4-sen#Kd*0r=c#aBosjfAtonc(szR; z0jWY7BVKY>Ex>5ftB2%AWzmZ7V=4eE6Zp$rz|1|y zbB2AIcZ}mkC`&78l!$mqAAQTQ`@2%ysDFugfu%*=Kr1f=_b)AqRK?>2Md2U2jW04n z6^SO~j1yHhk-40F&c@q_u(%qn#9Y!f%Vk61pn7W>6R~-jECG8|{R6mU#NEy09dBQb z1jfE2z0%AgYAE3pn&2t)4_-AzcPT=&2qS1cwt-2ub+%y|H=cAqm$xHcS(HNNSr*k{ zZ*Q&iFR}k+c)n$nm8tM*2>j=|HZ)=1ZN_KADz@pp87;>uGk9W?JmLx4To5a6g3l3vs3l1usIXKNND4{d9$qI}(+;{%*)p!S`z20|(HMB^tr?VOHmZUWe8P$D07E0cMo7(Ccy@Fr zS6w$-3V%|TeVIk5x@3~}bn(gPePYT-Gf~hyh$Gyb*M`s72BlyMXHTm zv7=bYh0gqOz;lGZJ|=ofPZVuP) z;x?{a5P_S;mO6ek{e3?}n)0gdB1R^?S(5`(nBz`olb2Jm33J)1m>0yCjLU6xgYrc( z%;xk1?n#h%94B_2Fb+H>d$xB(fVXI~^Vs{>s&ju3=Mj&gsf$)H8?F`tr;M%2L_s%^ zNuE&-v}D61L7q;d@gycYHI6&2Vm4rJmGKuL(PIIZGL7@(U10@l&JaKpC zOJ#$iuh=2VnLgH&}3Pg z1y`E~=Cm)NAWMra()HrN{hO?4VOFX;#OrA#s)}`_z9*($E}e?xqDj0TuK@*j1?}0| zuYTX&dq3 zIzy}%e%q{d*di%7Ic+-;3O4=0&JhpY(&|L+B}yu_0M>}Z+&%RsUJ*L(u16J8l&KF9 zdw8mo=ULJlHtaWk7)Q!5?jp)OyY3ppl(W%_N7`ji{GcLiRpHL?d)s`I-M-+7zaTUam991kah2J)*Q|s(5(PM05 z@q=^v!6plRaHE)Y8de4eZbL9%VcVL}!3`>rl9ftFS#HmUxoREkMXEoynSr?vUB>9U z$9S7&(UbTgU=iRz`U4G?B!b~a&__IuCE%ZQV_tGl760CSmF7*8u2zJ2MvJX4^4MCx zIoT=z-C&#kcLif@G8sI@r?X|UZSA_qBuBI--@MJ~z4l-=T#|>J|3fc{y?V#=Zwoxd zUKw+0aX5{%XEZ>Ibbvjv_B*CIm~y?{p9{188*N@4RnWnRkOxjIa_vuGY?y9M8GYOT zjw&!a+Rlr*8(EA8A2WHfEfmwh3F?{MNS-u!)kFK4d z0WtELnF_pKSb}>2wl|xsRDsrr`8h%+V#h*C%)su-GGJh`XT#JcR#y@jLm+-pnh=MZ zMJllw_jN$~pgbbfF`n)=yU?1>pmk07*D-GO@;aHk8}(!nvWR;;F+tEii>7RrTy==Y z=N@~ZULgHyX)Jj_jQo5zSQ?Nbky?wq_CVaVVx%S!`BZPjKBU9ur)Adpg;{k3hSxN0 zZ-c2}YzRSig*Sw)D`j}X?(uG9&AfOEj5P0@d$KNpb(t(*D*^woLlnl8gffUZsdQV| zxXM~>dnq<<3EP1CDB6xvaBsGWc)N>nfk_Ce+ps*>09yinkjKShz|<5<65JPJh9A(CgPndTSbhBNs1aw60!w^zg+YRZ zGO5Yv;z6LH<>OPZIIP2l6WwOcAy(zr`3fov(g%rklAGMMKiq;CdWA z$PCtHHtlt8&Wzv*K!Vg*i->xa#x5DE4z>ZyrOckeXfYMVAOplp`Mk^I4=Q05On2ENK(~+QH+ejGh43GC@1xQ*v4gl?Ay>JD>lbh9S%xV zrbyQBD9A^hw6-Pmodr7F_pB}_&?JNt5@Jj#y!4HW~G@I20OfQbOB z0bNy(-po0luM)EX^7hNTuX1h?FBQ%vALM+#6N+45Gdxv+ma$Br6v4Pm?roN=EYReb zwtuCl>haWyvds>f?iEC8O$y6k4ug51yJk$6A!97IsKFRqw{#->*NVP}pOTN9kYDlO(yw*_#h zDbef^|6glpO&rCC7D*YVU&I$W_uEnuD3A}}Uy) zNRjQa6jj)YtB_(&TM)N|o`>&?eMy)3PHC@J+us*o#_&o*kq&L5u9W(6 z8smVYJg*OiBw*^rMM%uisBWval<8!psYvgv?3PxKMBV{kF|iEz;US%QnGep?hgt35!PF*WChMTAXbZ9K0?+9iNUgHM7251 zYlYE#psAc&cbE%7fG2C}=1p1AMr(neSRk$}R|o*(Jv&%x1}rUlkd}qW)zqUgFYkE6 z#W!Oj3h#Kwy5m?m=Y!4hS7mdp?z`o{*PuTWv);&isHesKCoexOE5FGK~4mz z?Lf`Bm=vX=#%eI(%OWIrU5?x){|TFc4lhj<4iP*~3RUfz|6z3yu-x9+vJN)WOTVFeUh(m)J3g!Jbo zxh#~Wfu*+;`eE&H2{lQeU-*ikO19w_Be>dr8B3t<3cIky4lZ~5asbb_Qa5aIXwwPk!N%HH53it&# z4w@ZQQi-j*3in`Kgt4Ac1%5Y1C)pYS4N1YHOt>;fz5YV9IA!a8)mI$|VE>qh7YY8U zz2g)6k6*_zN&P<8j4Vgpv*WQZ+gX_25=Z|6Rj`6X)2{&mr2b-BT_50um9D=KTaZ-T z257n`3WhfR09X@+QX3!&PPtlL}P1sfbjX zZvgi^xtrW_m+Yl=wojcu&ps%njEa7Y^hyOns4czNsuND5@~ev*0ZrC4-KTZqUEJ=q z(JZ!ZX?G-IV$ClD(uNvc`^Yi>3l$LTJ1`9e`V*c*>f@MZ(DW;kS6hbLvA61J-nY={ z3B|LC_;Jr={bwxq!hbOP{8r{lxDoIsli2i|BfJVn0He=kU?w+c5b{hPHcqhwd3{=D z{E?uB?jL4goni_1`y_e_vYt}9dOlL{lqac`o0QQ4M?7bQ-$(V0#vVJ$NAd?NW@-^0unUp5R*Lwfw_Ce%NcC@K&@k z8>?CgQEQcq;B$|2KpZlYln6mK?x`#S_V;1w>nAoX8&sNoNt&Gf?uAY81lzPELpcqF zduFR=Gb4~1%nZi|VlPO3dT@zr51wZTjjHQk@>1dM1q))&W{E8^=iYL5i0ZT#uXn|e z)-1L{J-K0^S+zb&oo-8h;MB1qg*d0n(R4qe%8V@>1RVNSCRSAxmL-AfIr>-!Qk-!~ zqa|XeA(QwK@z@y*B@flV;1`Uuh%dea`^l#;>LcY$#Z=#)yTprIY1lWWiS~)z=6)HX zq&PcEFFs#G8J;QFSQ#!u;NBKNunFOpxIf2}7?`&Vi6q;JG}QjeMx7|RAXyDoC$+_* zD7aqB#A+SBA!ayN5=&3At+QpOw2Vz8Hjr8hGJ#D*r0}BY8u0WrJ-WU=?KK^yFlEQ^ zslceNRr7*qi(sRuvSEq$iv95gVly18Pl^jj@;2gDC58O2Y30?@iU|tbGC+hy%R$RX zt*A7fb3Snbn}DE%knO_MxrSI`Lbr^lePXfvCEhlfR5xJeSMMs>d_ZEVgB^}wIFSX( zarQ}Nzd5CefS@7gQbgy*4M6-OW;a2;`9Q3iJ1+yFpwp}ob6jD}ZU7MJlX!-dap$^3 z7$|TOs40lo#OMhX8>YP;KqAdzXUTtyu_0t0Q8XNzpeu?lAH*m(x|agy8CTaZS#7`> zlW(u6#)wdFaxl4nDib-UGzW-nWVdqhB2Yf?DhBr_I1Y01oDnxH6WBq7YJnfOI)VlI zd1WeGXVA}67o%T?XZ3Vi!5)ilJFe7;sFVM@RWC%xs54FXK#&@Z!}L^?v0N2Axn|{3 zOlK=UA34B4zu*Y+3Bbl$6bwD9vQ;X~b8`9d2mCNI1mkT=k$Ck8h%es$Q{e?1> zx7cyi?P!r~&o`Vp1xqeQH%c;nT?d5BZ*f$KVzOe=BJR!Ww$b9y%F#5$()mghxfLx! z6!PuD=(%R=vfFJDPr2Lh-zK{a8>^}c{{fS7N_V+|aTcrS3PiOVM<(E^C|X!>3|>W8 z8iRYKbT>chBoYbB;@YkpaDjE^YsrvsB1%~K90L>32Wgol@#s*oWqq5 z)EcME+BzAqJ?TNmScQmpTzx^vsp<7(!S@-cB>8{v@bPR81t=yRW&2*$XD{9w2VDG! zWn}Z+Za7wYfmnu^vtGp`o^V6zPBY*q=MAtQ^FKEFAs#xDm4EOcei;sAA@-sHf?+iV zAR*b#BJk4CT|Aw%hrKw80JO0aYu3?R%iX%uh&MZT4lDQoS6U@^@q^?6U#x0AFM#Z5 zgxbZ+kmJNvfeccM;eeT2q75E7y3hJA*c_#3uR^ILbu8wI;J*x~mO^m5oRHx+RCCcF z;7l`c^#vw_PVPio!1h5NDZOanLZ3}nFqO%oBq|qc*uuAqw@h?tv0?2AZsIbpbeXn_9>sFSv5lbJsB^PAE0Vfrv9*(IzFfD+`+=9h<|C?Y zXN(2{M$<3XN+4sL>Tk)ad;Y46zK9$yzc zQ|#Qoh|R!Rx9}qldWy@CG-LEQIx)vgKCeKk;)3J(i<6vNl}Xm*{SgKx2az%oSg)31 z(hG@060OFq+SL0nG3Xxr6Oig(FYdVytgnzm$T|#7m?-hlhaafdyC|Xcc;Fcd$^#P9 zsM*x_R5iHt`shwVHZB^gS}))!j8E*Q?qw*!_?$_5Ij|T_lRaKSRmsjRjtm`!2jh0c zfl6!usfygt<4CZMM2gR=y7QX(HJ!o#q|`KmTof4JzkW0nen(@%nPI)cnLU@-cV;j2G<_W z-o_(H@k%TZPfQwZNuYLQEup4}i2s7e1(o;=apKgQ5h^jV3W*cs>j;QKynUP-X&xcl zEMC9|2Rp{uWJ?g)4)OM_#~bEd0B~-&SgI02QVI0-4Ukk(15$#H*Y69*X_3w9#X!X1 zM}sW`H&Q2=P3B|BMHp}(^&%(MaD+Jw6R&k-w+znS@}(bW@0N zwp43y&RX?i!Kd?iDG3OHX?diAQq{kInC~p+Ue+E~OoYLtxHH*-98OLnnKO(c#NCtm z*&;;2j3>|(c@hSvOh)0%Bg8ks!sF9~i_oP1HOq@hhwDMv*O26>uMqpz!B*-ymfa8Gm8k-MtS$-&K7!$V2d>4KgL4_B4Ur{ z-l}AKaG{h$ZJ>sNiH2a~ex#5DmEEO_RVD!~;-K}|M6lmu%_Gj3h=98z<9%DSsV1QL z3E-cAj-Hny)9TxDJ>uM?0CBG`C{r_rM!gWAXePyznS=l`o)W>2sZo!bb`ssa0?Yo@ z|KJMX%fP+jJG0#1{D?p);DBN!u(TETFpq7F4hlv1je zIlu{y1~2a3CUNxufnPV3X9|m{p|)8(g#u4^QEs%W|67h;V#sV__Qg_Rgy0KRAK;0e zrq(pf3I{L669QUbo6yr~EUMW`xUVFX6;Xjc#(GdMqE6MFL7A{_^2}B))b|iETnRvg zCr!J>z$7Zk;$sN&fE`WTcMw`9ykV3Zu?arcU7gj6*oh#^@+>**{sb^ryTPu~jWOj( zbATtFMz^-2B~4G6)9AIlACwjRF>q}ho@3F-Na^Q?q=FP@W)qbFe&&W{@CUQSBIkb8 z3nlIq8keLmtwoV6IR(8+n}(!bxKUpN8b`GFwe%EQ!!qv+YQwDAFE+1I4;X zhJd4FYn&a4=5qhkk-Ul;twCV}&v1Ygr@P!Y_vb+|TUIGoD0E!Eck4j?f4~?P7<7G_E*{c!|5*)lfTJZ$0W?`Z`W0v^s zCMN?2e+~#x9Jkz3Jud=MQLni(RbV9nRh%tag!1LvLQ@NL9il6#6K5*78z z6f;;0=Z2{A;xuMZf>H1_x=NHRSKJyI@ED0X08~h*n{iN&>!$$qltJQaI21JBG(}!1 z3Dnag4!;A)@$zhRrFHh>C{=~dejE75F_c{Bv8Y5224szV02o5iCMh$}c8n;{a%L0w zg#&JI(l7^s+)c3q=Ua%6fdlyH2?sbCH{qq0*et1{|PiZt&L? zrx3CWef?btvmVN&jzT`Hm+6Nb)p?Cs793yztDn>93m<}vTxu4Mm9=wm6SY`TbW{?0; z(8RsgsGxvO^6Y25S^+4UcUPAHh?#2f)l z$@zM8W8JKm4|oGT>c6)PXGI>+4(Hfz67{TN7{DntmS4{(e}5XK;&e2!ljQXYW#55` z2OgyW6%6`dbH)txoi?w^hy!oOT;S!_O6l^50pPt8Q3jGtPnFD}M`P8&ca(%hM`n|} z)S7dtkRC}OrC*swB!-$$py#&aB}-$r*g<&=Dim7B#)GrWWT;a?8*Ib@7dT}@8{rJW zg=eUCGH{T0eG7nq?qGQ3A2;0YDR6YtP!$B$1cL3Hj78N4`nfH(D$kKq)d@c!3BX|- zuOVg)(3k;IdUmpke3vrvGuu*>E{|^;3jxVKGpIA5`l1OIl*J-J32E*qWl;~lZUHHV zXCP0r8jO@^!Gx-d#KMFv0)6dUr*W+XCjl-4pvlm8>b!F)z%2$uPwDdie4+^l+~V*@ zg8dZWIM3@Gr*5r;OC^?NF*eadesr%yRN`(A33^`|&{yC&lc6er@&AnWH4d=jSTIm= zC`lk$hhSSC9vvpB%Zl^ZkI zwPceqsAu4dQkvs8UtfTnJkUh>v!Tafe<5mvpN489gMN0sgQ)&Lzo5xJo|%}Hov{E5 zaz%Jc$jL)Z{7p}h$3Z{60~X)qL3#{C$vcA{%*g&i{E#jPypWmThI^d^59NZ^y<|Drr2r~H7r_9_*n>zE76cnFLYg}UXKL*nHuj3!}|-A2uUxvom;b5cEQF#pa7M`u?rR_dP{DWho`2 zNH&}H#vJ=jcs%e1lpKbii(CdFO!EIAjEc`BI^CLS2dr3I0IAq41*0{&9!UsmA1!5vo=_}9$TBh|)`jg= z_}G~CKlk8g4bIW`L><*+`R5mK%!W2U1izLsz1Y~$N)AZO-EK<(j=2IElr;q64OI_} z0rcYR6F}WKnk|TGgCCFrFdwXc!MFGno*14u05(!(E<*ond~T^*gg+llLWasm3B(FV zy@!XUP!~fHOsOg{W(bCY!=h-NdR~ukU6IyH9xxpb{w*@T>U6lRKUX;Lp zi4fiIb=NFES;-0{C}>gYKtZ9;<8L4xK}~zn>TEDR(0TB&IJ24PD>VKy`bbyM`A}j} zuXl~)nw~Z*m@-Nzby&x(=tH2VR29jj0uG8$6sB=ZkH98iN?n>zs8OLTNFpv=L^n~8 zq&f~{U>9*?ok_t1Jctmygn5i?NCsOU0M>jUI7ES`m536f!!;)boXNK2e((Py2zuv3 z6-)}YbR{Klan^~(B%v4`_xRuxLGm!-T|{%7)=()qai@pNxw5-$Dn5Pr4Rqq#j49a8>0_ z*KWzrpN8oH{>wJ$!Amx0RF71vb*2YiNgmJAelaUGtDcS)nMZnGBexbp8_tmqX(nF%7XkR_H zdWd6r5)BobpYBF|ug>f9cGWS2XT6v14)yQud3=1#SGdLf)G~B9=hXi7RPC#-x%C}C z_bQH@R*buARB%ZacL%e3)99_+y?uE$M-EFr)bx-wMrupgy$E@bOj&}nqyKOFw9&`J z!*!8jiY38m6DG-GgH`Qo63yDv`I?7*XAKUd-aHxjAX@HiN9{SQC{a<)^2XBAm_$KA z!P;%Q!o8Qc=ZJS?X4~2BnYn|#0+W8Pdwcxs+C)x=Y=(*~+*tH^ZHccq^oix;Q}Ghz zHPOg19`EigmTQ_c$ssJ9&1*@P8b(~$N>#5>dA~wAyBk~j((uSx@72S<+|^3M47L;Y znYaeJzt0<4P|4nJ6eW^u->@b-ds{#JETrLARn$Mfqt~AU8A?(cS390R@y?IT9scJO zE!t&s@)d$LapD_dGs&q_`#iz}ue>IMz)E=ArRM@sq*!IvObvEUox|r%uG1aR- zo-N!6p1ts0|NZuDcx`Un{DjY&`;O<%@t)mo5n5ddVUR)WB+{Bo35lk_3yuvvR$gP zUt%<~e*TlNRTc4Y`nekU?1f3i>y^C0i9t{K*|WLYC+h|%WoK@^-gUWiTW>U|TGk*v z-15%S&B;NE=CJ0iUjNR(-Xq!vRtkc~BHq0HbMd+7iF)nIo{C*7I9oR3kfM?rX407R zeFI^TZFhfHs)H#!s~x|oF=W_07WDo>9>2ojP}B9>j~qJ~XWHYwkB!>z4{NA-5HcL- zPdjB~>ien5&hxaTp1;zf$qP^3&s%9PEIz07YNZHtTsu>_R&EulRh#Zn{kX{ZobfHn zUzKvZTt`I%jnSpskKTAo9m&Tw-n9ASKetB1-sM_Sa+i^&;Tt_jPy zSDNB$5m9$u=e_RTN0-oVa2B-{MomlYOFaWLj?XO*cQgEp3&yTGisfoXCeP(2pS1XWp9;dT!s29JIaT=XS`&ecp9# zBnR>9zvMUcnubSdz5~qZf|7}uc|UiX@vFGQHGvw}b}xQ1P_k_ht9;P@An^Ql&R|z1 z$M~i~U%^*-k9k;$73xcum;cYpJ4u&s`+h%l?rpe>Lh*+*dCb|gvU{dY%=pf4_P!#6 z3s>u8_0qIU`F#F-Z6Jl3{4{j1QF9+#e6is4>WF$l`c1UM=M6untTKZ&tgP1;g0t-L zURmF-8b7se2j;)msn;%eHQwhl4jUc${deX*!pHUHBkAugk-Mh_GJHzzg+$8uokGwds*dt6=SSd z{V?iC!P~i7%lx6h{UL$1F3%sHsrZ@r`G&vo^ILbP23_Q$@7#loJ@EfLtbfWGEw`Z2 z7Wj=;K6Ua_^93Cz{BPxv{JPh7PeKMAy4DlLPs)Xb`Hq{unhZ#`5-gIp?H;e7lg;_2q&m%E>-x=eE`xhm5*`oo6LmJFkdR-6Kf_H_d{}O+zh= zehr!YH<-C}lV0-Jx9+2zSep3p-OK^G+L>FwuIak+4?B-$fWUatS|voTtQ8jPdOF+w z>UWR!F}t_Zr;;8AXNa3TwiWcr`V}#7f8<@Q<@d3rDEY2Y|4jVoizJt0(z>*}6Gw90 z?y5=CW-n^FJUd&NsQtzX;_*ExZ|r@?f0X4wXNwq2Tc%G_n!fGsO3&&9A$sy5ix?}_ zRbFjnht|vpAJtBZEHs@|aTxMgVpi{xS@!7PS0&}vR}S^9x@elZ6K_VbhREzA`hkiu zFS_a_ruDp1@{dj!ue#_pC6S#Uc^IjoPtxwa;5Pb3eU1Ltl!Y(x{$+FTpYlH%I(zkI zT}bl#HUro18s3)n9rP8m%E;%l2FbT0Pb;U8%cgy9mE|J&Z`Y^ew5OM+>%-^~;cD>b z_io_-M1SuP_z(FgT&+1GUrIKB;hObsG>gtZyLZjal}{fIDVZ*OC^TwbkX};!G_rb(ak=GWPQy~VyKh#9CTjf{mA$xdMZ=iUO!6Ox0Ee!X8(tzN%bWH1=u?kYwe9e>j$J=bIhuR7QDaXUGW znw)SFf|L*)*d$*OO_}KD&dje)=&muxs#klySp0nyGSP`+oYBsIH*xwd=WX{^Z4^V- z$D_LO*ED0PZ)Jb!*^au$_?5k77Tip|GY>EP=?s8}o&ph>L3CA&(bCYd7%EvO$s@do zV#OaBrC$i{pNBgM-aS|Kyu{r~?=~+U0#sH!Z33zmQy=`0@tuOb9%0kBYrt67%uO(DEpXZOjh>$y8+zw{`_|dW zo8mP|dA}26OditS-CAhl0Dt_ZfeW?T&bM;TycCseMW4EI zZ#KlRfgFZ4nl~&jkPS-*HtbyR-^?=y8{WPRRURzYJZjPm27UQjnuqgd5p>guuCuhl`( zrMGyjzkX+poJ>0&zjrijc)*M(pOB7ou58*0N_Zz)y?Z+PQpR8NE5r8add}lm()X3j zzgnhE=yLd}`P=@z7VGD7`HN~lcou%wU^brEbQv#XJ#Ivuz{&DIkhn)o`%*CZ=b_Wr z&d;$}j8O5YvX!yDgTdpG!G70|rJT9+o8dPcZ-^^}>OQ*nTiGG}TSY}J;jWp@S0?4U zera82&4Ccc-0xo1OC2|2BM(AChAs{j@2wI`jv1ZM_-f1x2^rb_f`5DQQCFU)ch7I@ z*98!svQj1mZPu^2skIiR2`eS=9T43BrpZPEIZp-Su?U&ctDxFVXySfJE z_Xavyyvyv;83g*i#F7|+AEJ&{^19}G8Uj*n{!)&f?&-St=>65ur6;XXl6R~BoVzS0 zI?&ZzP9SvclPiO%N#9fTX2$ccoQA!4F%Fx$AF^{UsLfq>^gi~NqT=!aO@xc{jVAi- zCu1;9S*}%hA*)8YMoOE`F>&-zgr|=3ElW5!Sg9`@Je+pxnEvBHzm0Uc(c<^(C6Qe- zN-j#r{JP{ade=od9zC4*Iiq8+d@rZ_S)Wt)FaP*<$K+nK4zDF4TH6gjjfUMz&kU|} zb^Ax8x^?^H_j^md8}bA`c&_!7!8c#%p1mq|$BEx4xaUaW`$%uO?=dP@Qwj+_vI+R| z#M4i-p-q=n!pxSyI~QgDdEozW?u)BbOtaUWWGvP0>DzWDKc7F^|2F*#{L%WQ{d&t) zmxhXrqIzCeUexq8q}@FjW^vDN{NAaJQa7=|Kwik5-Ge=~*w(}qpTNhi>e7>kH)!cO z|6P{foT~`i&bY3)+V|~Vtw2ebioEX|Pm|P81ayG=D?R!%E zqRVL5)if|Kdv$d!{a2!m-stR)ThYNznoa*q^eC7?y^7kwm%aX`f@6siiwC~RmW$uj zAGP!UJihE`c!UpMRl$F@rrQbK8=4!5Yxi@zClP^|%$oRD4!1bYN<> zdV;qTek|n8-FWk!_0RRxRrooxj{`BMc8~3RF@0{2?thTy=JVV)*EN zP&tKJSu&>fRc@H+v_^`!d4C<-Ni1;qrwy1*iY0bsp@X>F+;3Uid}k`EdVtx8B{*+>+b0`Hs&` zpB}dlSj~*jRcWP^3b39 z^RKgXgpJ?Eozi!~57a^wPowWvcsgDqKAbt5BQ+kl(0(1#8WS+4eP!k9Zhgg8Q9)hg zmfp6arPr`KIr(6zy!RBYH3mQKv#Vj-B)Z~53z*C);kArg^x-c>KHlo#TnKp|D(rve zcg1q_d3URw=N%0a$&YLvz3+UQh2c?a*tOpt-dZ0FOrFV}cjq~chm-CLqSp!EeNp!b zF<<_DT!uG46yDCaI+Ou6z>)ANq4 z<-L!P9Tjb+*~{$(S&rP{*1H)IZDw63l}D!6R!&#guhn15$g4p%z1e=C>s?Gg@+uO4 zwx^ruQqKu2o%(&ad;U)M%?5en+jYN}ci;NIsWtf8j*H13ak$;NE2+O+7N<~gf3Vj> z!{B09I=8C`CSzQB=3-Lp?&-P|?~glSh*jUirSJXcDVIKRj|6|RkMSpVeY}(U+P=Bt zCt3Ml%5Tf+D&xbgwfglx3Uh7?wKpk_Ib!}suQ`Q91_igeZA%|dGaha)s=M!rjMVC@ z#TT{fo0`g@HNWj;(0)h#x1>M*;?-QwPg6&i`!P3ajNkT-%OusGX1>Fww+3BrR1cqO zJzcjFAMNjUrs{p*nxzGNg7=@O<#Y`X`eq*C@R;!#JkvdU zZE)<4J(Kn`R&R8zGII8H^5-TDso>99LTR7p;J;7f>H!{GH4TdhkB}?3(@1%(p_vmt<|9LEl}n5N|Fb;B9~9Z=H#za=`lEM3yYTDa({j8Gz6te#PyFQ@WVhuaezM5h z;ImfK`tZ?@8y8N=DHe}vMB^P(vc0iJH|gb}MiF)%*%@?BX#F|0YKzeHBf62=;xqcC zO-%~Q|A<|u8x+$E9443aFZL8fE*NrcZKHnbtMQ=P@RcktvM=8zD{-jn;h|{pZ zhQOy!#&6%|Of`KTQmvYAD~i%pF%axL2&z*s!-HD!0Uu8uQuH3R4Lf`^wM3)c)&T zUyW)YxtXJdDd6k-Y{Ra!+nZ6%X&C;+@qHjWel4Jt~_&YZ~XMY<2(M!YJnB~t|j7%V_@jj zo2$s0zuuYt?WZkIM_=i0j9P#ZZ{{oaX-3-LOiS@T?s|xxSo6#?tM5~^y;fS9xBsm} zzNN+=k7=&z_f9IMOD?XF-US_2$7}cw$Ifi$MID|p z5dFuGGUOY2PC?k1nY?yR6{+CsVZv#Tif18zU4IlVN_PjeB>FrNSe=E!ThL-$Q(A?km~mo@LVVvsaG* z%~!#C+M^fzsM6X)Mt99{mo`qDtSYS+><*3ING}s~q2%1A>crMT&YGi8m#c~d5Sn2<< z_mx3$MA4cgXo82}?(XgoBsc_jcLsMEJP;g$!(hSP2e;tvI!JJL2AAc%-Cz6b?biO; zs@MIUs$1uFRo}YZ)ph#FcVazD?WFI9u6&|ei@ciRpI#0#*7B1(QdnpA45l--h$7t! zhqY{ORfX0vpXD8|SUZQ?{Hh0>Iu8x%eNbo`8S&Uvfq|6^&TBc}tbfi-Mxz2LRoabBxwGE#-Mn*B8pTRB)ZWS%pwUs;m ztP*ERP!Tq7yRYgs+1#{r;2v2cgUB{8jvl|8uwhlz~oT|3@1&i<@bQ}9#Ndxgcy zxZ&&VgEcSYWgntv(^;PkI;~!sSK`hWtZXZDFNZ)(6QZilEJ%)X^jyYxNW&i+uj8vMsPB}E8xsGQh64n&Y7tNjd66~kgV`6%?tt*q~>j^oQ8%lF-#9EduvTbrxoF=CFtNX`oU z$4K!QqwhjEoYelhMtBev;`&@8Op5}kw^+)C3gXkd;|q@0MHa0#g&)%la=9SI_2zv1$}z2L7?IAgZbF(UESyR3lEyow=%U=) zG?);1uS=}!Ax$jTO?RhyNY!F3$HquUR$W)#nf>}@l_`>Sf;u%R=^94M7Iq?lC}z)X z_QFIU5AU&eE$uSa`Gk&&#+1hcE6w&6O}g%HHy_)2vtKuJkYSJ1Q4>!;tb`mbV8FQc z`6n*!$7SMaJmz+@(eLpYRrT zuBu^((0cDGS7(2QEKMp1*XXya9uew~uGDih{dq2v=rEFeX5pA+?W*`lcSysTx{vd^ z<*>5h9^NBQIVIWk;+uV&x8us1UdJB1V@nysx8x#ymM(j^TsmilU{{I{UX)_h zzp82m>6Zg1PX(ZOo}O&M)w066yzH$x@~F^B)^KpR#tTyd#8zP{gy_un6UTz%bx)zj zKi;ajJK`PTQ~y_Qy$=RQuMs9(EU{x*jVx4VI_{!F)+pCi@!`f3Q}jp2sXlXkqXRS9 z4#erJs!)q4LtQN<(o*4S=+yit<5Oxn)&O>+QL;l~Nd{40x>}FLC5hzx@bGxCG-<|~rJXBtG@Rr6mF*`$E)_njO7=|(Ft0O2>nU%c& zYBjy(h=cO*`ebIdkB_hKIcM+TC?88I+f_`?0w9}AmX7DmP5cR0JiflPz?H_{=XrBh z>Rn><^|qz<;wJXU6+aFR>Nj6N7ME;ZS{p?W$$mF~b+nprYP-_>_0E+|$?Vo1Ql@QZ z`EaV8Y6F^2N*xWUH3VC-=35>vFxdM8 z9VccF_+ncNe9pm&$7-HLrfX^yYAcqFASDP>BfE%R@`A-fuun_hgl3$VRnfRM+3!PY zk4$HK>!yLN!P_F2y`4ihf_fH-j*Nle`Au7#-n3NG>ZXjjF8=GxRV9Z+K6@2cA!j;ZRVDvF9gSo0ETkQ0E1f<{OXrk{63C%G~8GcOdiOrT;<}c@p)OmdIwrTsU76nHE6MO>AdQpl1i(I(THdcC%72>{&Q&~wDuxtxHB&=x05Xi^@o zyE*r=)80R~Cd@Opbi#38p+v#k6rIVoKFVWW_DK;dV-VatGP9RA!vp5?raPyhoRvnO zjkn1l98^mC$MjtsLM^>7Eq_JiHr`JQwNMo z;55Gl1n|k{f#gW5f{9rT{oPEkAq#%^9)4}Rvs8N2IG8|VTcBl4bGx;&k~9B`_}kU- zeydq=@wDpbN_iSu2!xu@GrfXY$M@%~3EpuXABQT9uXIa;bLeTK&_q&Bc+HQ$K6{+Z z!p_@6x}uol6CmkhZT*tAvdR^+0!59#dEcrkEgMCshasoS3Pljx zk)6acLl60I>Xqz@(~P-)LUH+x)U%1F%v8liDPv&7RN29p?fAph0~`CR1|DDCL2un_ zO*`@wIS7ipC67}5r62BOLyet?m9JU^xL~)FDbqgeE*q$l6er_?D#4VbbEqcAh^}{!ugPM^-ar zOS@CSmqq7bys!hHbgoXJc2LK%Hz1=#O%(SF3;!t?Rq*0(lfOgiY_FqyF6=n1cEa* zwV%crLr#y2*lA9I#t-f?Ph&L<*L{0VL#)TO$p$qd)JjLVQAa7%wO-Xw3X$d1=)0Ar zl|_W;#ss^9IeT*D{6_fWy;$wee^#EiRpBcK#b67y2nRch&jS@{#gBD^mg;wty9hsz zthe3L8%J8S*V^(+r~Tu^2$`@s6~H#Adcq)20)f?cA$k}6cQK7hJPPSIj;=_9UZ}PW zJ8pV zSW&sOF5{4}Gl2``cH74E^imXiEE{rGi13c5Rz?TW-*q2HegCd(qI6vFeDauI6szEnv58enuq8VxEYi%loYkm* zxKxqy1mtOJ{4{5VnH}6fJXSU0D@$%ff-Ows42iXi_n5+V({?tlfuqDPwX*(ymN|LhzVT z->Tf(*xH>)idlH!P^iJg*{{XWU(Vh+%xvYW(|KGijFp_UDBL7~DuVrQ(YUv*Nna?e{9`nyhf*kL-GD~E}wz%raW zR1*RlIdLC+qiU9UAwyEX@xUHCcr=Q7S4VKAxy*AaxINsEe-;a`MtB7d|B~el$?sY5 zjR)h32y7qy7O=07w7k>dA^MR5hA2prJ0H(t_s&=VXUC1VS4MQP-H``Vq&kf|S`WEg z)XqDWszd}5;rUk;8XF~MN(`+QMrLYK1PQqH*7vLeG8ZN%=GTs`S%jXsJ78#Y1*6{V)Q`FCDwRrBmx}&sMwW zf6E?S$EAa)FHIbt%D=qK8pfTiW16Lw4tgX%cXP?+Z0QG-fBdGU`hwHZ@9-Mk0Y9&Y zdejC6@#sxy1K`tUA?;K$kP2`Vo4t$`fEN{|UblkdupoSR8LwrhF4~NH(jsLA*QM9E zi>N|pg=yNke4%q^$dS?RM70U&8oX9gKHd|1tjlM|uFb;sl_;scJ*gaJfwz91w5OEx zWU|nw!cIqvV*eo{y?6bDHu@TC;OP_AYg~t;odcol!fMW+!F2x%nLfqOqRVvvJKf*h zG;73GN^WdqU#O-jKA^FrEYnT|Y>Y6#BD3(M*6oIvWf`5vMoY4$lDx6MoG}zm{scd zo%^ilR-D?S0llOt3pf>hVzK{Nt4_4szy5B*ItaJIx+#%Pg?kxkqScxaq!rFqV2WrX zzB!d@AFV8^YVGuY&&>2VjWvM?XGR}zmht+*4H55~p9#`ln~F~)Rjx)9d+FUO%DF6* zldmK*;Go0x9{Jzs{=%Y1P(}HPq{-*jKmImEHA5U^fn-JQExy~h?&4TeRXU?#M$R*2 zJvCf~mXHVfL0kO<`5;0VYBOV7JKW_G+UDuXZ7HNqFQ}Qi_++oE&(^}yWRqMkR1#rT zzBxdlnBFIp#E_o-P{tAB&d2~++bkQPvM(cc@Vl= zSGr8d*g;aydPg!>$Ak-#UR1kUV=r)MWo`{773AZzv-%#MCGsHj2C8%!2t-tOpW#j) z=E}%*+!qM7&JBrNAgPf?>4kkP)V@yus*kT-3bT(LW~J@X?D}QU)A?AnF)v2`WG^yi z8p|~&4m6H@1O;vYH+=sP>0AB|tMYC#&DEP#ek=hE5#GCkmx@~KWWysZDDu-;zEU%^ z`+-PoizQ3^`T75lgJmHwP4r&VfesUgC~7vUnv3|EU9FK#6vs0BT?|Lyk-4Q>Ps7a7 zQvTldYEs*bg)TE%8K093{y5LFfeBCO3hZ8)+&Q(b#nY*Y(pp}hP1AsXzR%B=deYhH zFW|2trnE3~{B3x?%^dbVD4z8p4T`#=Wn_@#!2U<159xTMo`N<4=PO9cpQ2#!%ZTUO&$M4j1Ij9m^lS* zP6felFF~~=Kp(7?M(N&t)HE;z=oQ?4gRi-dI%1FCJ}1P!N`H=8BBZCH!K?qDF)rT}@(Tf8ak)h>emBLI`O-&<<1MlULtJ-iE!IRzTC|Z0DPQ`X;5tZ+ zbkpdJt+OfFgw7m=3?uf`xB&xc@OS_w$jSdv5vSA zwF62nlo%qOA>0KwVb%)b$R^a1ii?U^acb4IQ@VA54= z7RgMY=X9tvwa)w$R!+>xtgVLT=*)+s3LB~1!G{SjjKr%ppx6}pA=n|UIj(MB?-dONmgC_4Bpv;& z=vvPsoC^3GJUt`ATu#yqHW}`)20od8;zr~Xn4GhEB77e>U30L*L60(1VT;lq@A2hO zf1&A6{!D~XdmtLS46~am&3!j&>&y=b>^ivkk%4o)WkH}sV6ZtBE+nlDD^Th5M=s&H zkETcLi{5(E2?WtXUXItPWx~yf`y1re8gB8pXN44;ziX9I=UkdNOv(s1 z-Njvybn7ZpOi62hYFE!OpOOfPg*}uhf4-3XtJwF&!-vT2HN}JyJO8?W2!bdOA5JlY z{#k$fjHEu&qrxro;kpv3>MM!Gd_%J>-_(U-geBoKePYhdf^6!Xpk5%9-xAWRF@6Yo zc#Rp7iT~hL+wimAxZqW3R-*`V@MH>?!fvi8JE+S?1(x*SP!1P2=Q2eOOJU^k$LvOo zSE_o*RZJs@^`cMjlB~Ak-#%@yljbn{b|XDV+kzN#(HKu;3CYTH`Ex`g{^x2T3s<{> zXjmSvf$CSX^bHQlr$#{U7rvq*^26GO_)M0<_-ALafp2m{d9mG$Wx3KPwW{_zijAEt zn$+Ry25vlJ_)e7DrsE|=9a2YmTQZ9@q&o`X8M`-zzaCaFvx3Jm!m@y6y!2+J&>}!n znfVn|V4GK!?pfB5Mb(j^wLncet2)EtL4C}81$*Vp05G02E7hyqh*f95+Pqj^Tu52x zApT+P)*Ysn$7X{6EfQT^dWSj;jZO!DK~(7_H!&gR#W`1Tpk6_?-8 z;)vW`*O{F)It`+?4SQOqJX@vYi^Qs3p~>)7G@}fw(+Kj9%0ItH^Yk}wuyiRWBy6qw zQ~S6m1cx2^aLw`&?m%nkNNj<|Z;YX5y0IGL;qvs8Jj>OlIW1xVYO$8JcCNoVS$x%unS63S&oWAn0-ZC!Ry=5k{WAIneHeA}W z=X0BIn-4c77yRzoqVwT=)&qhh)(|8C9QA7WVw3Ly)d;;;Z2&D`IXi;&cfudquYI|j zU&Bn=^Xm@U{YM@&S&iIpgrB{`%Di>Wz`nJ~NFVn%^#7qFvZcmEFiXLee*to?e(m?c za6YSAzNq}H`(=&jrQW>F=^$t0K`P=VPAE>0j7b6^T2BE_{t66s#T*tHM~w?}=(N{b zRRgF$30J!jw0(j2a}_AF${h6W3L0h!0?L+d@IxrXJ36bGN)kv%@n>0}>lO1x-}=`r~a>%@hc2x<8Z`XC0--*)3UUN;Ze zAV-}jbNLn9a#jBeEydsa=Eem38NkbS9cgz{zk0i7k|CU{oA&rgf<&Pb!-^6C4lZMq z(+2iTpN;Qd-Q{hGYaOtg@Jx5%U}Ur|xrC7yb6Q5->vBG6lc#B{<4#S zPPY?B3b|wmXbTMS!Nc<1r9R2nCJ{bMsk!I+6>I1v?;MLf`zxo2(>ov|Xg91294}v6 zDPq~+YO(NZMUFHlos|=UUoL(TR_~Lomv<3XZL@MM|@oE9YMP1F)}l zPe{h$?cLtfJ?r7AY%`UQcs3=vl!_3P+Oyu5qIY~HobF=6ag6Y$TCK;-;@@~0IIpG( zLfxU-+xjEc4RV^SX5T+Dn0h&hrn0L2XeScdOdv-atNf1+dQx6MXE=`|2517u37Yg6||a+}maQ2AbOog2S{;e@Gk zh2R|Y%M(xUW?a8%MmEAT;48Bpi98;<6O}=eEl%2b6Jkj_V|kV#R?x~}*aY?5c&$30 zNh}rI&pw^dZ(9oAn3HYFPav-+Zd2(GQJMlvqAPXNU7S2&lOw#dqsMmTMG#-#O%7)3 zaA+4D8(fzDrFx=sa-$yfIY({9W+Lz~&w9oY_9{D4?Je3SPJi)HvWZdf)7AmppAV7} zzoao@$TP%li2mT>*pIkjoZ0M$GO43p0uDY5I($%OBa*q7Ka+mypHz-emUhCZU;Hkw z$QS&b(n}~9qW>0NQt!`+XAh&h8Eo`<89`uqm^fC6jKKH?JC-ukdgo7SL;NQ;kU;rm zm%stwXq@9pXTDd3ZP;dfw&!*ii!g`_FWkSI&+X$`Mw5Q?)?Z(8K6-;gcCqLPoM038Qx^%s z_Y!hmUu9&AhXMr&R> ztZM1lqQ%Lj6r?U|uJK~SJ^DE|q01b@X89Q64osYfMxzbfd|nfs`tmc5&zt^o7|9_M z_Ca8Wj+abn>`PAcKQhbe)Z`2&xH#zxFSw?B<>YE!r4NVptim7qO6;nNGl{0*2i>Y; z`{hK_g{n~F4r2!hNn#c)9nP8YBv%UlP1M34nI~1hU$z`w=II7TzvZ~)g}bM zM>cyM!;0g)a^ldca^bJY+={Ilv)hgVKzE63jZZ-KGflWoUFb!zX~GM1zO63xd{kBO z{_u_x-f2UiTfnZUp;kWdsr>?mo23N~n>J0|Ox1;47>O8(Ca--fg04(cWr8C1 zQBDaVVK(h;`aGlDv_;bc1m5RZFz3L}_72?Q)#WX@g{TW%PZy^8CUN{zg7~P%;?T^e z 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

8RTR?bJMC3 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%0A6h^GU%?nyE(V5b<6vjvmRDo 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
    ?3 z;(q$fSy#E_b-IYNp})vjCJia!YU7&9C~C|7ZP`32`3B-gg_XW8w;X7PPLk%*z4)4! zIhe$2Tri!qbxv+WZ`J%S88>ua2Y-!f01J=6{Xi6nbBRgJVP`sdK9Hyq2bx?Q~ zc#fHVyWRQ2NpJ4e4x7^h-ug@0FXCLX_>j)3l3xoHl<_}ms)iW$A3w)R?WE@Yx^l-% zfA>IPY~dhB9qfzwZKUQX+5e4e&D8JIxA^2;^1?r|d}VC$SBLFyd?(XTgNMz-p&|nF z8xbtg52h=>jKV{618bm98~o32!w$YdlcQdiYeX8eLYX|7?s0;oNwMHjAU*o8m-@$% z(Suy|u3Rb8RnzS6 z24B05pQ?407_ZK8qOE!HJ%$p&r9VFS>Q$J8-C#<}7+E>b8J}xYMR;|d4 z`I}_7|4b2@%|n)UZH&7fYSR2)3*3MzSBhE@e|Cma7#H|1|3jzd@?KvVuQ%;YGvkS4 z{Px{`vTu_^c1sNF^JxIm_KQJPiFNp6+lR)>mpRz>i^F}P@KhVr{Bb2@YGXY7hW6f( zm+<|uFki;4SE%j#qPbh6^^mTdAE;;KkNd7gop<|VYfSJT2V~PSXL~0_u_qnj>$X!* zZ^c5{hgzA%t3~Sbe$l!d)WktOPHF_?rQaC@XD>Ufy_Kv!E#k}UPT=@w)?-~yK4Q3T z)FXj7-tHe4j`2;7Z8wIk-eq1I=}IGZ=Y+0J-mT0D8YCI==yD`% za2BY%KWMAIE zlI1_rH{~!a5ZV$ub&K9Kwf9$`B4Mav1A5XfHbCjM_<>`S&1yOU`-prwFh*ifvfY!fkuxW8%j1op;@S-=l`Kz4zbSWdltjv-aSU2z}So&cOg$gN4a6tp$Dq zqmoXVmF`<0%l$Ca>@=*S;Sri8aQN)IIxZXZ>KOY&*hp%h6q#&Q?&QnpHNP_th_lLDyNz$Ei&JL8IGGiR1I2sr$+No_gcT zq|?WUFWXHT{6sQkM8{jNjH<5Q1+B@BT9t33@Nc1TbgU?EEn_fKsxiABGm~1Wd{1Hg z%4qiMavTfMY7mcSCy=I)@YX_zYMgh+Y5O$}=r5L%$Dh|czkl65GmnUqvhS}_5Bl(I zbDmL%7WjMvfBs{_g`(_}jWPdl zzjX1!v*h*n*F9&1Shvd1MlsyS())KlEwZ^|2}+M?dXNV98t#D=l>N{JS+vJe@8X-E zq$TuQ?oMpsIhe|H4R8<@KkYi4_f}c!h41!xs^EDT&iDLLuI+PEYMYxRhTL;n#O2sv zr_x$#q1Gg(oHdpfyV}Zu#(DKoXZ`!Om}@8+&60=%V!4}cM=8-Db`ye?FJ)h&FtY?< zX0c;}ru9i4V?8d7sSYYSjrQNur&H3<+jz>IA64=XH|NIJbn2H~D3uu!U!{FPv;Siy z@&UUoOz(V4)uXjx=b(7ndU!69O6v$f&+xUSy5^K@C#TJdDQ~pHH!Z{7Qw-pS6YINOI#iT@v zbetV;Qntk-1A^;nXFV{7=*A;O#!pe~Dg%58m0a7+-Gy*u*y8e~OBV(?k-I&05(Nu| z&FzFM7-ZX-?vcBHAhMd}RY};ZvPqG&H{|Vj+`kl==r|R91P5Geg=HLwB&6e` zj%KlPnr=!XZVc1IHQ0yLH$}_`6I>K*cJyDlFMq3rt-Q4Fs{*0!>bPzF8+p<9?p-=; zm|glD$@lC8*m#=M%g(&y9=pTR7d)=g#% z(~_g*xsklAsi@W7Ghy;QHOL)(J=r-%bNg97@x9Jr@4C^$8KsFcUA7c#vT(R2_;!a3#HlgUICX3QbYfSbb#*QF# z=X8NMv`qSx^bJvzWodg#q^076mmDwmy1e}7dF7{uWFqe)#^5ksZ8l6c=ER^eo_Cs) z{xaBEW{#c|*aCe8=8or5$taY4!t0WHP)qqZ6Q+af{&?j=VL3bEN`^}L6qz@Z=jetX zjOEMvFj6HBm->#66LD#Uj4jcWec{z?TaO=I_i(_zsNQW+J9Mfc@w>OJUIBRdPxhF@ za;p}JEd$*7)ZnxdhVxY_@P-#0^*%NA6)g{VNeo8-&>R9Hz9ukD(FToG%V z^JPs4!?8I>8gcZM>zHs5tIo$Jp%?J=Xba$k)f6#Pj==vI_67v_o z5q#x+j?$FA^r|5Etzd0$)NDumsq%xm94)7W=mZ6KQ>S)n7ia2=f#8ysHe#SPSuByF z(i>-9nOP8pWd#|2$38>`cc&kuq?C*2L>$;zczFvbn&l^WNirv_j#FZ+r(JLbU;fIB z?tIxA6kLyvQt9Ttllr?NJlfIj?K8ty)qW}#(c)q~-iSnEY@C)PE)#QA~-@%P!Ii0w&db8}JHbo;T1H4~>T zI+6ve1N#|F+5##0$^nE`gU4D8gVh@Ou3#S;7r)u(=<`oTZ&oq~b*H1!7TAn6f-BMx z3B3xZYTNW+QB+31?ldzc`6->Ci7lqU@??|_-G0I3I!!rg9bDdAlg0Jx@>^l5GNnwhX{Mt5;==?nxUOZR#-hH#P^yx8*^lyV zp9Q$NoIh@#xnT%8!ltIaVl#-<3i}C?8D0Ev*62W1W6+LQ8vl(fF#C;NbX5L#YX>%0 z6ovD+CkZ!|S((#AfI=b-BMDC6`~*X_G%>ka_fD`}Ju|}cTIRKh;@`Mpr?OT2H0krg ziFL*1cABvkO&naHfT+7--`&t9tfY=@bK8vO-pT-YXZ<8n?Df8R$^lv{jxx^>0`7YSA12w8d528hxc* z+Y{U3)xZWiJO+0s|M${nMFU2TG?nHf?+6cKMLM;QV&d1t^qQ_1-V|}YPsiU4_}|pC z9Xu>}r(_dO( zLr+(czYVF1)0ps^wgQC13gLXLXK?0Cs*{*O4B7p<$hDms31;3EKI{>Mt~9 zL4P}y(DUXy$3ahTsMTjHs2AhAo0x;8V~XQM3QU`^TE^IG%uv9i9JOO3Bww_#_xO!w z>3G0v%&P4ZA+Zj1>S5<63o7UPV=+l=CWWZ=4)Mg59igzY9TE*D&FR-R+ts<#cO3mA zJDa5Fojn*on^`__xf4f-XkruiITJ^C7BZ0fAow09edi3BrQcN+oR?ep&kLsf+mq*+ zoxj_x#>1Yc+mex6Fr*KhCuNAQmshVzx)P75tC!a{@TkV?T2u5ljyhO-9Y7yK%%H9R zwN}2Le$8;Q{4Lt=PJD({3}SJOjocyVe$DAv2x~ChaEUdzd>?-_g5{IX)IeBUR(Yp5i}xYiMp)66R`d_@QkPw=m-torro!7b+fo)&&K&{3%-=%e%zdctdzfIqkw$iTS;|zu@+K zNz#Ds?7$jq_D!+8-;u8c{1Upve!TC$w8PqVbV~xtDjc{;97ntS@DO`CT1fvjL6A6z z3uO@S2&E5m+Q_v%wfq$YZR<)t57@38|2ZKsL^h~skY@TErgtpYkQLZ1={n(^g6+uO z?`yETp%@k?Y$-hUxXuHyxQE%6Syq3W3g;?*Z~q&kvdd83yOu=}zgw|k>p1XoF&fL~ ziQuDI*%Su>RmulK0l8Scu)Qtuo939zV@@M0n!m-@LcUbQKsCPvcRQsI#I5n-S? z3fCecZ*89o?F;pMk9KMI8)3#A%rj>67tTlV{z6(^#ch#KWo$D@-piOlVf4ro-x!Jjmd`$>gd;FU;OWN{hKDC{;(y$luE;KX5$9SYcPo%<*?JPPbzQ8S9`r z*gKh;>ec+~7ZhdZ2+ERa544=r`twhG}G*3FUe2Ma$kf7v;Fe{1}wW(LYI1MoiA>)!B} zB%kDuxHLndd~hp6&!EHjfIp(o)V>`CATz3|kxXXgD~0zi@ZaM}Xus-`eyRQW6js+i za&2eS?UZU;ujHy}l>bAMv9G-d7l+!z`|*Bu${v}P9KqEul9uMB z%ArH%m|pD^_+fdY9D~jgMIzjyGkS|#lG#(wru5+00*@D$w*EMtUWjm18b=0E#SX!Mq4O2-BdS~)Q*pLbUn{dF1q-90oi5Y1OJPD?kBmq_wT?2SV-MK+RY*nOpg z;nIW-wzNs3KKj9~-PP}4ytM^n>S4&Z#s>8>FVfYy<>yJsR9e%=CP9fbpmY&_P=XE9 zX@xyW)`Cv)xQI^yr4#ataF#@>+qZh9#5n@<%HR#6{5_cQ5y;Nfk()iUxT#7xN0z$7LR_6G(uXF!H-Mu^?xl8_rHxouT<(> znu~1w>iLP?#1C(v)}ax*1GW~zjY?V}G8R}N5@+0dC%px%RTNzVxv#pTYh>sQ6fCBN z!iFQbFEbpbfDt%u_#-K;NHNkPFIfwJN%cCo>*<~aDu=>e*{5LH^tf+8_nq-se%m|p zyVLE3O+uQ>vI{&%M;b&tHtMw_+qL_;adogo+3vR$&c-$>3$&lvs`i*et?K?OYZ{ zjKe!hI}ifdja|9bJav*v`1oR}N!TTl7-RcQ8%}yf+8_AI*hZI5ep26AWYxU?-7{ZL zB%(I69T4NG=d%53=|=hAo#E^a$v{IhDt&i;u_ysQmwiq_S~f?|gPKo0p%%*8EyFpb zm%xGAY_f>6P?!K)Dv*PYEs$B2lb=PD6aB-={te6IUGsP;7PO!_@Qgj3X;=h(K zG0P9WB`XS(YipZkPWPr^-drtE+iOd4@vUD?cv4~s1I@y0RX80#)fM}v7CH^;#S~g?iDP1Wql5aUgh;01ddl#=l z+(IT~R~hm@SH$Sm)yBpe)Q9c^69l}K*$T4+v(T>AFTwy`kH?z zlC{NwB9konfPgOvOcy7l4NV31`N%8+T&voGD@~uBL49|YC^4R$62lahN|ZhA+R9Pa z6{Brs$48TBdZ_&6FiO&_>xy+L68A529=2cq9Te!kO(cgmP#k4xI|v7*<$|l8u-vvYK>sec&f_aNTx{LbL#)nhd79cCh3^jsdH#?UmnFsU z?M_Z(NL~~6?n?NEQP1U4;mD8@j&d`%e2^ED~>Y5GL_elLpMtYRo;(lot}$f_Znr7dp-N7LkxIBJ7cPkW-Frg zH|!_6Xt^$@{u9|c;kNf2()1dyi&59x5F&MGW+QFIJf*6T6gETacVDJ#uN|d z)&m94qA5{unSzl^!5ygN)$mw2<;sLT<~3ZIYg|{C5u;Auc4?39kMfi715d0b z+YZJdGq%qxQbWJ5Ejh1()tZV9*ECKX>jxI0yF_I#@T|u0$75av^llBN)t9Ux0v6&A zFL31h_Tl6YqQe8VM}u}XDcfN(k?|pHS-Uj@3}B7cn;#ydPW%WptRp1Lq5My>j7-xW zrF7iDkAi3&A*h{u8Z!GgT^~J>jXn$Vct8ugUf)U2M(eR<{)Z{46Z z&-k0@TzU=f72DW#w3*&w;>gitz&H85U@LiU@)Qh=b zBb;kuNLIE1{`TQ+pD{VS0Dgb>ZpH3tM1Te^pfLz_r7=}Tv=t2JoZH^WgS$NWW+#L% zBn&}KS+*@JhWwVzg=U_Y)|{V4 zR^-V;EUe6u-{4|#Lz-4rwaG`r@aqEah6g-(DA~stf$?wNaQIjm-12%cgg{jeZdpeq zThTspe3x2d1aC^(LVpbv?or^*HJ=3v5kUEz`FPD}AELKtB!j;Z0t6VEH$O+^;a+)+5(Q3@{WC;*o| zZww;@8Fy%rur2W7w%=9$6E%T`oaZ-&SHEA^?j>>5cz}x|r2htZ4)6K-uuD7kudOG> zr=!M_N8EPQ>Crd(FSe9x&F5*v;JpZNBC5)NKG=Vd`dw)PeY#2DFJ&C3_?>mv+-PDU zd)yeJLTucT-+^+Rm6=zyz}tF%$Qy1ryI(0j^A+wYBqPi0!<)QUN!j}{@RU*Sc_Zac z059TCf@|d^z-5DFWKe$I$trjE9)d;sx_;HOGkIm zVJJCmR-r&FTx;L?>0LZrI*a#*KmxpZ_7d6{67&?VOhL=LF!a)Rll1Q{u%l;ad%I>3 z9ul&1oR>JBhj>=PHk?*t3$90VEc%Doz~is_?!(@)65KDO?0T$FHn$%>NMIo4JPi-O zGU_d}I)GQ99Ot1@ylh{O-7?FVFNnH6JF!`Oj}2U6l_sfwPi(;B9{uxSuL#@6c*86} zk3zQBdFbFOZ+u(%4zno__tX?&QSYUu%sNgwzP(%J$gSL)vW4vt$qwbYdF6idf!oW#x%S_P4^&I z%N}U1E*!aH^FTGnjOLrV8MU3ZDMBx{O7icwj&11kd3ML9h{nYm`oI^8npMZ)K|?%; zAA=vmkkzS<8D+=){TDQS z2i2KTPUc3>+~aVzZ*ctE625}t+;xh#8tJ&AW@d9xV&22>HXhkwSN9AnqztP+v-1|bwbGm+f=I-e3iaQgnWsO+Cq*2ds4A!n`wl$Y! zo&o~L7%#lTR*hd?st1o7n?mfe8jMQNb6vWGge?%d)TnT)u!m=Jk_$jhu-CBw#_51pJ$XK|xyL*~m6h&9at)Aar{#_mxAPpuMEZVYd zxOOGZ`EZZf-lyd@`dD_K3&|YbysuNO+nyPoWi7>NeWn!O_;Y0~cTdryybAygml29mU6^Yn0Re`7+8TEg zhu0BrDc+kS8nvAXxSh-P2zs0|cS(7ieZy@I@*$RMB?xJ@L;A zQ%I>VLrb)O1EG}+C?NwdatMhT&jAJzT8R@|$)R8TA_0nx6J1n;!67=xcmGf&HiIQL zIV&K~=ojN=$eTk1R>ag7`^^rJ7qF4Thc7w-stiTXssK%X+km>DZja|U>v z3reDcCER1cfCQVa5}TQV4iE#-(<@{nCD2o7Ga%m;BT$G27+ejQP)!uDM0In(xRU{X z)&?TxF-#92?O`HFHL4J}o_}{8!DfL5$g6{WvqJ?f(8zvKmjtkpum| z;E+`z$w<4S+(`fjzXE2MVfl$5uWt5DT3WhIrc4~!On~SC#4`uPLkGLzzf;TtJd3AoPA1>*DM+_{X=uB3Ud4kPUY{h)xBhNK^k#p{{R%2`A9&O-Rpe3sMG|)8R%MUX3?X>NW1ARZ9STIP?fWQo=m@f@|1+$J0q3e&-LvqrN!Q5rj>Hv!xVKMztVCDv&IL!^>3m%@1PW)#pSk zqfdZfRfwQJtX&qa0U+`3x-FRQ}}`~y+*Xf14_kG z^>l#jG_X`1NQl;;nbzBo_Xgtb2b->dw4z^_e39RQDjz{`Wf!(f`y3!y%8Z+n)EKD? zY7kdHn3x{S7`!O0GxZyZ8Rj8jmBMaC2nyMaK5>sD+#DgW0#aYh(hI^UOYttkBEIO1 zCr$#}!zzZ9Da*(0rAI>EZkh6Ob{usnwc#c zVneXGu62F)i|7IqMAfQcE%LZA1>Bee=4FEdSYZn3#0;z|kPi}@iCBWL2(Xwb@}f5A z=?|f_i~#Z~iNcFlbuX<<+&oZr61b8J!eN0qUdHwOFb36>AjwErp%_H~T;1LZsb+u! zt)u=^K}B-e-J1bxZgf6H)DsU3u{Z$q(FBD{9TJYU0Hi#CAZq|Q@iwpOi5coM0D@VV zF!#qXfL6jQ*kz87C664Wn+b;N5BpgGNk{WqWs1UySA*30!3ZiK!sr*HBvHR&5O#H& zg$}z4b%2m=$ibpGsF#^xnG&09dN6YEqT<|dYXU1r>V^n*D+LgjsLE6pEuvQr!h8u2 z9Uu!|@GoXj=9-75}fahQlN7Z9I> zKyDM*$Po2P068QTaGR(D5Xl78j}jtSK>3lRqyWIV|A~D?Z?Ql3w766Z*xx8SuMn4Ebix3)-S*K`*UA1|aJgGF1W5LvN@jw8Hm@ z2}QUgiOu*5$TeC+1)-IWM-0K{j5z4xB0vyU{fu|9h^*)~V-7N_M@kY!&R2%0@v^Zb zhY@U=N?0|pTls=QI1Q$*ajvF-n8y&uwjAL4Sv+LyEkutA=IMY5tEzx-qFvU9?pcGOUdLuQ3>#{mrUQ=;27LJB-m^_ z1o2G~UD$%mzU%(!$yI?w`oj!0fQ)Ef$Es0Fcd8I(KbWN`!oQv+LH-$XCb^6(3^5|X}IE%AH4XD7L6Y#;%a|zf;4)w`3lDwD~$U{?t7F(?bVNFA% zMir2iE_$n3v?y!K!wMwLX&|FIFa{5ifh-|3V%P3 z7l?ssNeCl)h3*xNv)D)EB?P1iRR#uDRO2jaqh1LkhvWeC^dW-GFjqa~&6{fn2y55m z_ot38$E_Iv(qo7MBD$eZstx=}=aDGZK;?4AFp38#$QpjH*CW`BWCwX|NC?6#B^a%$ zCx`>Y5Qr>CN)ka|Ll_yiVvg<4~ev6u_k$1(immI)|Y0EXZ9V)1nmg2Mh*Mf4S| z&jM!%kgdM4Z@Pf~ONdedh@hFM4(uY>JhH|>T`>c3)gw97@*^SQcBnoCSMm@tL;&6- z(1X=WrpZ!OIAv%MY=Ws9TG=;Wfutn#fnvI#nhGR`dJ&|M4*1*=Et=ccM-Xm*7^yn2n$YTnI8Khk0`x;v1#o8U zjB*FPL0epkRp@bVt^(iX;E>s3h!p^oT@e|P=gR8hNl%-5^HzPP)yf`?$VkglEpl9YeAKbgkGhLsO`~tz^~b6@i^~8gzH*B1@ZkPy6^?LEh$f}a3K;6C+dba z_RT!7m~95Q^Y+&)_12{173m_k{pd}6h#*Dr7OX4Be45V&| zWw(+AjpkQw@|l3J=7F9eE+_}e5S>sWnburzphE<}%mw2v)D)Z_@Tw7hCYpyM_7>I6 z72^&E7$9A2#B9z5oSy;GhT5PQB>}>VsxMGe2{z|$kvB;zAj->hR+CbST2;)z@fl!O z9;indVt6yckhK@U1{7HUV&;Mj=wX_uL=c0jOiw5)puLt4Nos`x_(-c=6J?kMFg$=n zY5*(ot#%r82{uQ-frI!KA1#)bh2gQ_JGUPIbxRMFyDn^?=!qd0i+=_H zItx_J0gbc5C^a4Q5&)shFbfGQWIY%O_S40r!479&8=_{aY481SK!fU>aD@EsVq^52*}h2ZiT>?`Ft=-xrB4 zx;~@bU57+Pp0WU0jvyj>Fl+GLp3DFqpFAk!Eo#U`D!COo$gM|fDy!=a1UiTgds_iP z?Zdyg4~>&vV`hRaNm!BU!5YD2&96%O^boMCkSI=Ox3ULa%@j`XCGoHHgjvS(zk?_6 zJ7AK8H`mRmgQsVfc9jP|6v!2PvVN#(K5FTNo`asEl)w`y$F9S%_c@;Zd?_iYQhRS7FuMa@Mv=*FB@ zKZ+ZZl6OQBc8D-K)`h0^anw&uvsVi3=tCpL{qubaJsiY6sr&O|Fn9AgQXUs0LIXMri_$4*T6*Uja-bWt9;2CyESAvGCRg}`gC)gB$JplCEk$-SQ#vzfEX&U=EQpI>D&3J;41f^;qtN za)#Gc79Ve*1aIm&4-%0n9Lh~LPH#XW#ifrFPR#RhZ5ic1;#}JLD{B%+ISDuJCejZU zct}7mrYH?xZl8DBZWopdpSJ=Vj}=hn#o1t=3Gj)~8h#3J+2${*D7BEwv1&_tajEN0 z8b5VMLC0id4~mh$B~^TLzw`2DnJB)`l@i7%$sgcMeTuNCNnv5NclL)msgctFDrppf zrz8f*F%0DhW|-(Py~9^Q_u5tL!#!x>wuLCP+wpTRDX~{G5$jWi)g;Z?G7s3jJt-gk zcN@Y_?lZUUn?9zmg1vQ-pS|U5c}bSey#L-dcPG;6`mwnKcW`_LvNAW&g=swypN41`CA0$|Uqgb2 zib>~(D>?0m{y>T>)>1aR|HV5$ z(<>ruDLgDeGOToQ;UYS|W@@zM9Af*n?C9{xJcfs zjymMO8;|*Nl2;l#%|;uSt&e(mjJ%esMTp<5TU&c+np7?~ylUpqOtg<(Q>bC~U?I1? znHos6w4C)pu8(K{DghD_R@T{a!QSWKNwbIkc1?1}Se@->*cD#p%qLW;D{yE&2Xd#N zs>$OzuQ~B-7FJ>Sq22ov8}DC3@xsM4(~dEv;=HeZ*|A_5FTvF@ zNiAZJlZoV`@BY=AW3F#gAGy&e`nb~C>-*mG;^w#TN|bH?+DP=TaTEoZu5z9nQ)y3yd4Ct2_|0 zad37~y;8caJ^FBT%ySU=L-_i#W{{y;oLC%AKh23Aq^JXKK2eOIx>O;Fe93#QFkd9t zIz2U;r0^^FneO29^~}GTdPM_a4uJ=(=`4&Oe8lB;qWl ze5+nb@uJCK>16*XC!w%^Xsi=Jb0@}tIDZNF%)rUz9{%To%(&1qeC&2oy;hkabY;Ew z)QO7)`F%wa!QJ0ZO*Faufnv2e3`uR_<@)r2>LSGku?NF82>8;OM zXf{5$tpQN24rb&jNc5-=-)3-C?(DN>yH(l&nQhr(Lq4gT#w?1Ev*()HtA=e8>i;E4 z+*8It@!4DXlasWJ_BuynxEVFu?28>X^9`y|pH)Y6kf$v+wYdwxXYT}6Q`l~e zmA8-J%9(FVoTuJ~{(|DSbq^OSLo4&GP0b-yF#Q6pkEw|O?Ng%GY1z&;G&QGrhS_1f zUD@GA`}Hy%W>Y49tOJNW4Lmy_6Div84@*}T$**-**KC|z_0(og_} z)^O1n!8@80JmJN|AA{NlbB~J?K`1v-=C;n~e*2yme z66bSh6a{=Yewc2Ce5ICJBJVVNokG&lFTcBBZGUw;UyW*F;eEdf!>!vgFQ|6PzSa)~e{0C><;JHt7%Z4-gE11LMr^2TJn&WW$ zVE;#*DGRr-JdJ-VN@5u1F-EGy&ZeFkbKt!{E4;k)&o#xze<G(6dhkD?uYJM48?Sh{P>1-2*8vNMT z_mihGp~9p{q{Q*^A%oBC+Ukf36~06_n5e88s9n|D^wSSH$71-rI242jR=0j9@JI6p_Yz*%W{Gv*fGSavMw;s>a>L!}O6YbMuyYlS(cW zt~9^2htEFeqXja6ir(bBGM4}Zzuyv6GqXkM{-iKu;5f(qoP;Qn%Pjr|34tu} zd=)2q?b}d9m`+<@?z(X%S}um7`tB#^3-Ph7+WUB6=fvjYML*>E=xFOR1yd!8t28C` zkDPWPyHV=OzwTt#A`!eBJr-oN4vpFqyv|9;U!e0`B5o)cl36fu>LI`&uM*^$qL!8z zMF1R5kFPF`M-Xjec0l$d<0&NFlw6CINb#kWhno5HKv>6fjZYuQ*2j5FGt-M860p1d zoxl+9s;r{%Sv~A(=Av93Xl^|>@KzcZ`s%vBwQZ@{ojkbsArP+~gL`U64fYD&_rx~Y zJxts|lLBLzYg9Bg8_gBw68Z*h!R+(9>CC>g)bYgS>H#9}82VOYNVaX_S9F6Ow?@;Sx02083ZfjGaGlP0ZpNM- zDgK^2wWrq?wK}~}8)^p9jeff+s%d>N|9ful!5}SZQ3_`owEAsA;YS{4v+j`4y3$m~ zCzavxZEKzF^*<%LkJP!z*Py{W@b?545SC4{d#pGXJqDic@u|4k@)p_cg$~Z2He`-} zDr=Yi)HRh;!ClusJdBD$VkZc_q;8{@m&CM7AFYh|t7&$=cM$EZ3N(lJdRFy4J1?hX z(;VnuFxPI1v`17|Srr@bjaF^aMh5tMi>Q}e70{FI(Sk?=#MPMK>g*` z*DiyS?mqlSH+o3I!mX?fJv|X&Fjr}b+=&W1`oJP9SjW^v%{Dny?M-d$;vm`FH1%7T z%J|lDwEqE;KyAN4sHIBnwW~fO_I=I#?>Xn*JI^ySPbB?*{=dFn(;M&m+~u5m&bjBF zd!PH{b$mkqvQScyk~}bv)%u-D>eg54JGR~IB`E=XpA7sFHYkY(gDdu(#N}!xAF)KD z(e&daAxItkP{3~NM*ItjzwIXk46?|{`;a}6z@Lb3$4U(;g{684tS*%xxM1%jbn^N@ zBHL!`PwLcE>J)sNjOofg_WOZVRYG=PwJ&z8?`3QvbE3d)zM^A1>#EEeNJSQQNBp3~ zTgxJt#a+EvIm~f#m`Bhs`&$fRX5({f2-g?B`(lA0bs`2leoOQcxm}zayI_%Bm`OpO ze5DZ&b#++=eK1QkLH6A<44f#^FyB@hGO#Xd$)&1%IB10T!i64;Gld^CogN#Hpou;|+$ylmkXh*~oCEi5V zfLV6argwRGbio`E9<|p9=>V==h$Y?Z@5}iaBe!xM17h!iVbt&_yEysW!MG77t^r7H?s{1*|0J=je|VW&pfn}xWdu(>{e>~wVI z7BCkX#9zqReMOcl3|pzrzHJ3CM#K@jM&4>cbn&$Pb9e6Z#&uV zSYfd>D?PsVz%9b_L^q?o^(VxyBzhWc%3@lMo018=*<;)IWAPnW(OB9oTOqIrDn@WY zykFMlw+a$1r&92K?5r+TNEPSwfcBun=2mBJmVyiFsBfnbnJm_>+%c zNa9Up5zMlqy<&QCZHyNyH;ndtj*b8E zDCtc8k09kJd>eu`RQbdZE!7Z%17_H6P^yfD$D)GG?xFL6+})stW5~juQ$LMnwkhlS zt1;*Vk1d3R++qKs?sK3E@Jp_fP3`$Vl-d z*LB24NPL_uLRsjGsVr&BF>aRh1Wv7{nqxdIDQ4MCgX?ii`kvKgNiVeVu%vNbEvd!B zlAim3ThdXVk|ni(0gV=xG$yIxm+L(&sfA{Fn_t5X8cS-CTorqbHdF5el@-Z54Y76! zS}TGuR~KPPcQ2HdbZirsB|W%aSkmM!I+pa8xv#UNN8$y4;e$h<@Gr1mngk_p< zTYG_gKtN&?pN3!|I>KV(Gr#qq#V1Y7RE{FdF{P%@dUd@Lo6 zD0!2TGGy#ul40IL$(NLjp`@#)(cZR$8SO68XuH|#f&awgQ>%e`!Oivcz*s z(+ycJf7_2gf$r5W6gs~*ieucpBDmoFc(mFNAjz(KwS1K5z<9F1t=3`_b0pqf+FzbE zT4vR!B1K6~x=Fl@EP`3D_qXHB219oJ?E<5{*!_{@Z=W71y6`^P{XSO^PnCFmY4y6S=>X=KGfhF7sVroiN|KqlNkY zQft1S&0^+zAUEG7$d0Lw8?Y9Q!&OttBPaIa#W3xZ0j+n%T5?m8MrQDPI<&BD zn5xdWf3VIKZgm3e*!W6QXFjUs1{u?xlq@C(dVso4=cia_N4Giwc6_6Cpf8Zw-ATzp zN+wbAm~8PWu*J20WwvYct$GaW{j}FbQXm>Lg{4mxQ1^XDg?9$8LmrYxRyx# zfwT^k#T47+Kab~+q5td?iA4tpjQh_77mOQ@mUti}>OL@IJeLa^om1KqqxPRm$&U0P z6LgI>tb8QiTy~IWT^}N{Do~LzX^0<@cy3t)v+Uw**!RP|*wGL9`d60TL3XMBc*GMW z{;jl2l$AwbL3+}GYEL>ydC(XNHW$aggoZ}bz6r*+yHIz0hM+b+p@SU{1`BOOz;3Ev zgIkyKlU>$jdn*s?66@7rG<#T=)zRF#G?_`(#Z0k7Ze6028V*?L;V_!{gymOYmBwK- zyB2j*xu0YT8?4frA)OF24c2N6!dyOt!}!TOX>nTCb6K3PR|<<09i`(i&Y14zFtQfc z3=)IMw;YC>uqX2*?%HzTS&1@h78Qv;jCd@^<44is1aqtE^67wkBVhX_k+ElN<0w4N zS7mQxl~m~;`rw8n3`b%V?MMp$C5`)<@Gr+Z5XL`tjXQ_4n7J74vE{&$56E;ipyV-` zu2Yn3qU3W*@=)?GGeOGMjm+qL_QL!3ZS7=lV(~1ZFgi4Q2tU}=VW41B3>li|ClQa3 zc!czjAd9>`urVbEs%*@%04$Yzpw`9^T+nwg+8DpVWMh(4HfE+;+}zgao8m+tejtOf zjpT2k#6Ok>gJ(^VSwpGFf+dI#l6X5=1hcrq=f03uE;l4a4CFJh{AQ_e`0%T!w1Awp zI~P4n*6R9TZmlplxt!;PW8U*2>bzOxS{)vMHsdyp$j$-6W*`7t&-gN(-SjH5h|sC~ zwOu;(`7*9kU@*;OyVej!IBqy^+NKmd+7n$rW>3 zGIqt}lkZRs-d9z)T$y(bsM_RQJZ@Wfd&r)I4#dK(1RmYB%l1^rN94i>jlQf%>L6o$iB$ZsH@4#HW z@e{09U+An?cY?5}{G%k^Z@yqy-dCzUN!z-8M8CvGNNJ-i=@Y@~bO3)0SEuJ^W6_QR zi}*$dbvht+8-Y~pSof$uSh-tnvxGHVGH`DGsB+a;bN zi(r;r_2FBOJ(0=7pE==)Kz>w1`^nrk0dSaIIzP&vcbra-Q|&O@S?6;yXRFC{j3JTj zO36Ev@b!R|WM~lV0#^Bfjc{7`sL1^xh(GKl@awLnEM}GBFCHk*Ccffk&;|z0+MUKBgx(7XCp)`V))PdM z--q_*=1bg1){j|s)1MW%o&6==WoM(RcsQD7X=mXZ#=_19dDz(|ExDaNJ(0haMPJwE zb~ZGrVdg@xvmXjOi_;~`^INe<*x6#LX%vh(a-P-Q&nm5I=^8GpI&6`!s=-Z#Ro$+& zs@*0$c4mA6CbcPv;!_gEGh|ZZW4RdgXFQwO0(llIuy({R4o3>OHhXmWW5nJOSQ&a0 zV2#*v$+^sa2fz%l-{-9LqST3p>8*{1+FYQ-9<%NhwgKs+hT zSF9LiGL`Kqcy(Wz0-og~vyPG}*hvv5M-PGjEQ>&v^+EDgCmV}=2SHt|b%K>v-Ug{T zd5TMAE!C;^hGP)7NxYz}9kPJa$p;OLLQ+OkZ~5SPlAUK?UKeDEQO-q=l8!6u2HkOB=^qEqKRJC*Pe zD>spsi;rVmxrIy9NKA;0aW?GV8Dyh`>P zP%ULCxk)zXF!^{Ns_X1Sn`CX=>I4{{SJi2uTB=Zzml6ebKHgc*wCgAKmzzEX^Z8zL zY}#hJ@PQcCmn6i4D8RQ*;^(ChQx-E2dwf%Sh$|V&9XZ@tE|i_M@5FuN8DH9PATz_15M2$ZR>;|RPLpQR%(IEKpyI0B;; zh3oRs7oCBIVgH6>*!c?Amea0yeOoiE*| zC-?d3L@v}PGcH%D{aE-PTPvHaU4;a!B$51%UL74NajTSK$RhvwU6B8-xR`vD51(%W z&*M`Zu<(0*W5GW1zvJlDdz+~!m7PjkT7I%D2Of42jdQ?+t zS2%RGQ8_%CR3uR4LBRQPjfy07aZ{0ZX_q^$i>HcUmff_hBv+By16?W-TFyg7EM8S4 z#6v}jH{dF=c9aOd(7PC95kA1395%huBUw-4~X;dVHn2iVN>9PY;#3ZRAx68X! zr0G1NB2Vk;s7S4mS*nPoGY;kbyvVKkoyAacph{&Nz;RP)Ibnu;29 z(#|Iwez%KjJ_+xlGoLs+iWZ}(CtDJ+@V^odlRe>Chh&zKiu_IC)Qu9qD`l3l)Ov!8 z5jMV~vN3`5?&zi+o5-nX-O*D!Fw1V5QH*QHu>LOX*gZpPhkp(ykSF!HcFY;BGl6XU z*!u+1WA5uFkTT`w{-Fc@HS# z82fEydA~-BMw?S--XZROC-I81Gdyd$%*stg`j$a_n8dG1#iJ}4g&93eMq%(38_<}B zwB!nPHAuQSfXY8^nfv|rqWfkt1pKyz zCK4|%4FS)pB(p%wjPfFeLK44Z5JmV!30k_K+ z-WWs~LF&sF9&@iC$kCfjLn%t0lX9M>}q=+*>zE19f(yN z-Y?*~?9tlv2JuFLm7_-icGp`zt{1Enie6)-;7M`KKH^`ReZ&Y#N`ve9(U;6}{KX^k zU>Mk#nBHwGMwD;2ZmEj>36{8PyA`s?62MDoxkQiQrL;v92e=)@G5%5-!f@peW1~~P zl*S(1D;{ji3fE|lg?|>g`q?`}hv| z*D$-+j}nxYBCS8W7h9?z@#j)KD62V5ML~Fq_N~sIk%=a(_|-O?now5dDtaU34}k?z zbqF)|j4;sf;u*MW?01Mgyrhk2e>AD>9eROemc%>Be(|i~GV5&~E~HB|x=OsLEP`2f z)5c7$w&Q!!6zxyu%x)Ujj5`CpdUAzkW6x9;bQv_3>8Ldh^*ab*@Xl>;YZ6!I*rbLh zXP~lAL1m9a|2`b)AD+~3>kO{yxuI^>VDX3c%m?KQVvA=Z1@o;mD8{ZhD7z&-NDc~RAt|)=6G{%>qK>4o zL2mCt8mApbT{b1i$~KW27bJt-L*k!HHO4Hs$0eqdr|5!aheWD0d(s)Ks92;{vjJ9G z<$mV0@Hc6NW@lLVgAf>tJc@-+35*BE07erg0%Lt>44P9Ic%^t8-q^1~_mj;R7=L4* z;40`Cr@R|%h%aeL@eK|VcV8)on!R#5Vxd~!iU4F>vhp|fSvw!ou#SLuai4i?JR7|( zUK}pRlMRB~oc^qp;4y#geZxrX@@0v;UVDcu*Lq|pe*)JdMap8SH3H-75e~1F_y02f z@W16-%wjzYGC5vzx$rQ+*t6F5p(|(H^eDl|VD`o)_aNKV2#%UEOT25hAt+rZ#b>h5+$B2 z9Yx4OMjNNz$i?M7t|OOsIFT{!I5~X{WZ`XO{*P@%{4I$ukWL@Z@|RiTsL1qYh~I4? z@NTjQWNG(5g%eKhXt7@In}V_AL84=Nj+Sy?$cocQ!phThJ6Yo2OA~@wcGGWpxbW-^B8c-RR@w(=oLoOdx|jn3TrTFeWZ`0t ztjJwVjPGmLn#(?X>~!2CbHlF*>P$&pT5bN;OsG2}di+ErdZoa4h#p|aDQ(z)5lu<_ zJ%b*UG$L0tt{Hkv5hUOrKy6qL0&uG*en{JH`m&-tWMntGC<{wg9WuhLNYx>uzLn%; z>tbK18~YrI3Od#!lM60uL z67M0kpR(Av(q2M$_E<;$SbQ5+G%OH{HWpZIDh9B+2kenL{IXXFyoU0>!N;(Gl)(D^ zXO{7#iRi*{G6;*KvHpt^-zW_N&)OriKBXevS0KJt;-h5|%(9yXRxe5_eYDeKm(7S) zU2TX48Qq?OAG$|~%y?#<%t~`ID`weNbuudzXag-o;svEy!7RI}UoLJ|qB^ab~h3n8cP~bir%bUE%6ws0hq=RUfIG`EG^|1k0+g{m-FFexTF{8J zpuTLc5^2F|3bs^`cwVUmm}NJ8=;Vv0mK|JL@VndON-G(hBjW;jd}Hr8oFl)+d|D`ZFYi7x(Kl-c8J7xi#Wqo(K<)5MrLEzZCOr`CMXd952LtZ#k8in^j`| zlDi2Z8PiBfrTmKwM>~>^`y~Izx%|H?xU`hye@StYe~C|(^3Ssl@GOj!ETa{|CV}xt z3BjssUOaY)$^^Pgdn{_aM#{Lfi%3ZVQP72w??|Gjz^bmt3?|Cque`+zT=zRCu= z>x|O|VQEv8Z0$Wi>_t&}&9aWfYx{{_V3yq!`JkvlwwX@vi1=Xprp)@H)MGkQp8pfX zuS@)tJW@_soF*Jq*ENs+%HKabo!kXpfH$$K^>zW>xGUTax`>mz9e6dSbt+xZYd7s# zR)}hsw;-b>Soh+olTU@Oy#U!ZpLc*)YU9nb{L?V>2Q2*RN^)NLot75sQHo}=C5L^m z59M+<{vhs=GIfX0NfgMkxEYw=Kx;E?i~!%lK}?%Z4$iT2nDteJU}l1Ja4<_=4kN}M zHAKAEK@;rSdqweY)g@^1*eBlHCC=qX1&1pCn(16=I36j5rcgwhI+lOQq?a zo&eG@;aeoC?(il>q&u$S$QcRU2xH4|@#?s7s-39b5zf_q0wcF2Et^*htS^yDF!0g_ ztV>A^usC-~R?q&7>`=TYRh8BBE5564iWOK9stIA&Evh%Hvoh^U#F! zb`z|ol*Ip)69Lc4tS7Se(%jMM7sRhie7P)wS#T99to--#2XN)zgO1YuEHJ+EM_Amm zY{MDc<0e?K@=uTr)})Sfi^Dp5NZcqp!n2yntXl>w5 z`&ZK}&NNHJ@v&`OR_~z2y4N!JR)EDP17EL!yNp>wo_DXBwA5lxtXDmgy=ATc;<(!VOuf%n{$?4wr%S3F0Fyz-71PR85a-y(01 z2#l}n0CsG|Vti%C{LDbA=005+dz>Z8jwCic4Sc3|Kb~>=F`yLvEzixq_uml%x{PF_ ze+k5!NPN1K4a~Chw{Mjd%~b)DsUb9v<(I_*sJipvh~KXx@Ox5jC<{b4naw2zvvCT_ z6kO5;|74|plcm;?6jrBr*Y^^iBWt59?UKjk_SwX3_gq(Cv466y&V}wME_j=J6!?U2 zmHVK-VA!-DB(Qd(5Q2Jd4Ll0RU=p7wmME8hpclRz{scP6B3-Gi8vm$0H2$@<;}5Xo zv36xYn#8UXM9%h2V&e|?$GDGo8jW|f&Z}PiYYXnpqcQs7cf{LCJYEhtX338m1Z#%8 z1Pyt~+89s>pe>kuPze?#0A>O)ychWJ#_{1j|F&pwI}LAbdNpsa#23lor7S$-p&s5? zIlOUlct_BbX5;U01t}9d(Ljg52!_%f(0riHa-c0V(8dhzyLcQY6o~44RC)L;D08t0S?OaI8WKd563rAjPFW5 zzUY{w(>*r^8tZXkf|aGoqdQOp@!k@DA$>5O)kwhyN^_2R4F zFc9_Ow3ZXyR4Q}jBp+%IAOBi{;I*V;mr`i_C2p50Mp@|K(Pg@DGYXDhM8??OQ8q69 zRnA9NIW1p)Ed_2WKFnVbj}ls9Grg+G8=1Blr%9JAU6ncX;=W@Ytg|+);|J)lXT8L+5I6ivYKuo?V7my1-(oWrB5v<(-@k3+?u| zS;=2R#@kO>qwk4E<5@?}{e~TBB(Uz(5e`=ta1-|E;fshB6<8H|lwkfQ`AW_ai?mTZ zj((i|wz1!0_M6GZ`%|)ge2(it$=j4flTQ@}y|=I6a&n7Yt0ON^0_Id#ncQO)N&c&A zO)kKWb1yU|Ht1 z-uVj@SZ8XKU{qH%Bh8YLXb%FEnaDH`k1|?yNqfqkP*9T;LGmL3c6(JzIXd+)j>(BlYUm_=R%7Ung^B@hcd|Axc%*!N%r#9^3EP|ac_5GDA zD$^VfEPEEh+0&kN-~`1i{t;L`YMfw{DL5X@%vwpPEtD|cA;%!_uRdMM4cA`wTgU49 zDnt--gp}=#yVypu#DA2^Mp>#lT|};K?uE!*q|bF_RXwPQO4SfAC-FwI3C!}sm-=Fk zP}jek>OWao)U%otJoJ0ScSzhO6`Zn=gfz*mxG0pKD(CTvXJ-C=17X1&8bx7ZQv$Cj zz5%PeJ?(Dw64+Z*F~Qs`2`5po(hGS(AcSYwZSxp?ky%NtHT;7MjsS0 z2&^nMK(Km1Cz0n1XD{}%y0(#KE}*0}CDkbDN?roQV3j{cGDUd)QultHF@xaUJ&^xO zLNi&f+OEW24H8&G>J`Fv(}Uh64M`1~_krj`0gKf%8Xwye0G|~c0DsFb{@rWx*omjG zc7kRqO<89$lCNBtX48>6%~1xtZOZa&yq!WRxv@< zaQ67@-ZcIK>q?ITtZZ0BkybV%m?nc6vSGN;G#>vh8=TZIwU-!!u4twhx$vG+74;Yl zHS;l8#(s9Iyhw#EmJ%1K7{OjF8P0^|e5USvZf_pEpW^p_!fP(cHzBA?vpR%xA-zOe z8X7FfUrgT&Z2AQ8K#3>IZw6A<0v`IMXg0-!q5F+61oWE>Tl0e*Hf}89=sxr6_}a}_ zW(3>Ai*q*9k8g>F@>2&o;|E$yUr0Q|UvvPotnn0aWs3Yes{w8&nw<=fBtJ9!{&fSR zJ>H+LlK1<2e+7eOtKrEfWAQV|KKCI+Hyd-!Wsr*ED-wj!T3T3s;*LA z8W%S4zK>y_n52dcsL&nQavOp((3~D!4G*aU4xQ;>XCNWLrVye`!0Kka#=;nSpE>ca_@)NlfxvC&uRN|jV zmjbeE0|TLRW&<+EbTddi)`yCl=(W?oB;H&Wrz}so-R&bj~gTL z#d4m8EZ(^!-nsVju~AgKKHY#+PvRYAamrG4?yPR-uA`Ql?!75$fgmTVy-X#<&qy2> zj#xWn@y-SC&aIb^B~$SdG@pIVaq(6@!lX%lEqjRFVUt{oUE(^5#w~ddSUcDnZZlIJ z_AwVPLUxM%?b}0a4X-wct>KMU*IW58PrCx=tUGUr?toYBNAILRDaSGHl>_XkqV>v` z(=klKgli*do5*MQoRT<7BIyuRA9bAr>R_Gi-RcC` z(dw0^&ONjWT}H`JO4_l6X}nPL4;y)^`P5R{XR0;!E-nepSx5Gnct_yHq4;;ObL$1h zUmOCMi%5_!6A_0G_Jv*?QZ=+btA={08yZ;@8;W#m2w>ijAqg6yyJ$TciZEx<(8IE- zhSDg^ajC4fA%I0gxuBt1-Wy8Isv(=Yp$e_Bp|Nfa0W2EwhlXfp#-pKDp5{7%ImV{S zWmU2hkG(M!EvuCsfE~kBTQ{nDFE+`7fZxlg2za^}E8kp3O8~%v03RU0PfdW$G`)ECa}-~@`zyZqS$bwo9M9mZf-Yv5mLv~(Ae#|}``Rj)HCo3s$)GTbV?vH%puvm{ip^hu@^7eSqo+ig4{? z<<5UR2-De8s<8?vk8SNMr5!7TdB}`}$!1zoO7v$8&7{BLw}wr#B;Hldq&#c5%zB54 z^rs_LT_s*Z7Qrk=PbhFpzD*Iw&nLiJg9rF5<9P`^hIy)1f5v0pt|L`jpe_*#fwS@F z1L^uQ+By1z{fk;Z$ajt`Zs&XCcjT3BO;tJ+=%%34164fTPFIMG3e@rxU`K>%5@OG^ z!|n|3%>Ha9`ZBn)qbN;np@D);iUHYoflh)2N*upYhqYstogYwAe(;Rq$M==lG9=_L zDP{Dvq9X8J6QpT?tSX#52`cx%2dO&He%_O636F=U1mwMS~Bn zY8~wNr&WHVt}rE6X#(9t$r4IZD7i@!;b92QhW2I}_svV4^ZabRb(+>&zrZF|@=aJk z(0U7x)5z02rqmLGuQO=psu4w9R!Tfho<+he`-I@wuvDdnm8~V<95afp-4t7%K8&3N z|Ku0j7BJ9B9f-8a`(0_7Cd2w9#}%qRL;Dpd&XGmaI>6*ZB8s6wGaf3mnF`9TJs}a< zKr6II#RYy^iU?%cC>+isMP^zZnp=`+N4qWm69%xF*6^C*yRh1e(4N*80&7GyBa9(s zJV2Q8DrmIHVlP__qDAJJ)hIRzMZ#OIFKjuNT9qhN9RoT3_O4^2!8y8w!D{TPt zmmQ^hRGvhIU)GvgOpv{WZ0YzZSkrZhe<^J#W{GR|_(U{gJ8_0ftA@Lx&K7lN)bn#uND=kR6VmyM8 z-;vry%G#_X!~KpU9>($bk<QdS40%;YS>OF&R?QX8x#Lts28NU&NU_o{+| zN^?6GOdFG`5hPVBi{PYDolY!%T|`V82xvQ0fR8gqE0rg+dF+yZ$ZRVuFJg)af>#p3 zPKxW8i>MhvZBQ1yrx-MLsKq`6qV%r}@jWc*yMj;z_^CUq_`*EAo@iB{y0gya0Tedu z%IGqxZ?n;PLVnmV75O z>ime_{p(d&tIhyBp1#zmb1$l;DJ7rKHrXiHCTr838Tm@yzc(?aJCDC+2Jj}}EwbID zr8fk|-y#Fp#;@_};w1(@9~6V%vW0JvDM!0KcV^5nX#Vrw{v>t#CDX9|L2m5>EZX0k zt@fk6w9hIoEGiB&%DdiP897#p8Uq-DpLEk3NCQ-RmHiHC>%(~8PEooUtI=>7Yg{9+ zYE&b^&}9INh}WGhHh5EONN}Jy$;hVjj9*>#yZOIpm567pMFXQ*qmliv(YgZbMvW4T z=NU|;MILM|{6t5`@(7G?EdXqb3xxN>jx#Am7SHVN;wx?~u-|v=XI1XL&qS-6Q{z9d zN`Eed&KbOEv%C=3`N45SyKQg)z2&WXKDm$>XjjLE3aq57V_1W2aG-cg{2v%-LxBD4-=Xkt+(EfwcU^msf#Sc@97s34TWq!z2GHyR|%7C_+Te$8Rc{Qktg}N2n2*t$J zwE^x|*Ls|(fJ4huPv$i!6IMNUlH~-0y@>Wsqtle{yE0jN)A_plw6aHUtDE}tzPP1J zZ@^7`diUJQF}=xW7`?Mss_Feq(z~%sw&*=V^u~Y^v+2?jWU;}O8n{z{CmtpFc2kE8 zSNF|s-S<;dZIM(nKfqKvL!VhkZe~rj+p-U+_B+L>{(J>d9ZL5EMPwKk(o0-1Y0B2l zjPl}6@Au#D)s8QH@7i;K``^&-bLpG916=Ed{s3Ri$ngMAJ*4N+riBF4|%yc@5xMj zoj5e{Ukj`ynRtTntN(@QC5?9e{3VTc0kr7YnMreSpy$>y&QqJ&Z;>((dK2&TdVlv_ z$!}ah1JfCGA-Mo1D?)F0gwq=yB~H-eIAvZZm!1ssXPaoGoFr!pQYF&!8~9%Onuf1?Y|Zg~;1GW{GFG~iA(;OiN;`?1J!WE$^Nxx=7RjDy>WhW~<@g=qNkH~Zr(qrA zNw+1>opde>Pl`nBN(dESyx>ON%3lW#CAQ>`=4_cs?}f$yA4UKlqN5ofUS#Uu*D$7& zIRD^_4$e_J;Ct6sI5-4&o_Sc#1=H)92jz5o=68SYRsXYR?`B-nHvtW<>zaV*Yx*X@ z_j-;+bjnw3I1VjVn}7w<-aTxWEqj+edcU};Pj8!lbm@(~s!wmRe{xK3($|dMzrS@e zd7NI~?9rPI`@Z^$KCwNo=@L8oiaxQGujQCn+c%8ZJB!rBek<*J$+kN7eH6FvM|`*~ z@4>X@JHG!fuok2{-|@Zw5IxhTqDq2Gy z?fRAA?zA$2N&|J)udngH{Jjh8^-KC=`1KXtG5qn8{uuVTlJhZK$i}eRLboyG0^6}o zcKk23yvBH!*XI}YY5n1{F0E-7^=Tb@ImfgnEnu`ZUf^9h2eg**%48wTS-~YAzW*X- z5*U{cf^#k(*|TTq7xY;+{*o@s=3dZeS@TOdX4#ZQjAaGB@ovBCL}tsL{b>;X0{_69 z4UB{puLd4MZUL7VyXnvK`s=T07j@TPU!T`!R=bNiUVr8LmQh{eYxninXY#!_wgjtZ zVZ;~lv~Sth|G%@){|oy1|92Mpe<8;MY+DTa|CNsZxALn05dVA0b)i1fkJj%Y_UZ-4 zDv*8<3=v`5Q1(ZUK)iqk*6$d4I?H~$y~#^9>`B!u#=GZv{rT@)7W3cv9P=*uJDC5z z@E)8f*-~fz>&at}N1k(bMKTtyev9TmfrSwZ2}WAV1}lH@xlS))dyxG$D2rM!&vCYT zy#AB@X>~S>_|G~0_|Mra;y>qd%;G6aA^!8Zcl)!kdA95imnRUX=!$p%j)@feRacW6 zSg?rfcXhXZ7f_QMF3B~sV&%{1lY8Q9*5rl@a?LJ@y3EL3_}OzOP|M{BZb`PJDe29; z%aaFvX0P;x7tp7#`dMB2nw-|B@6nl@(|3i@w|%}h`u=U2P5J`7(iiiFK7CPVbm{AL zN}s;s|AD@%jK1^pywR8Ub@XLr@3x-QSH@wdb(JyYq&{`^PUl=1e`eG?MA3;i7K*I6sCzsEAi=PB}#!mvx zy77~HT%MtHw0LI>F!Q2@yduhFX7uM0UDXlPg3#yi9)(EA9GSy=7;{J zFBRoa=2+&ZZD3q<%oQ@99|D>r^ZdF|M^z>jO5VndA@?)A$Vc|(qb86FC-{DVrIwFF*FK0>O>4F(0|+|NE->e@+O^|M#`?Kfz-D-;=%hzu{}<{}aUT zIH-68P>n7sUSf*x;&I13R&!OS-Bed)Dr4L@dE>aQv^iBa$l_LP!|@zTThbOb0ORKf z*PO4s;C8FHG-c_#Yyb+qZoRtSV0fK>4jpg#r@p{FKc*{i#y|B1F6~&31|HTb-Cz2HDDx{ab^*p6!O;du1emXEJt~3eOD`Q1m{fNYBqR{yk(Q$C;!mr_pCp4 z`Tgx5`uy(rXU_TkE8};W*}D8T*Uv7$Z{Jq&y9s?$;_PiLzX{G6zjs9ZZ}{E+h(5nd zAJye|tt0yUzWPVb`MnkP|7Pj(`)K&<_}!ZGd(y265Pwg?!(^rr>|ey=Bp)@8k7mVV zr8jFWV{w-LS-LoDDIB#>#+1^B^?7;Zh%PU$9@6LK7e{i;%ck2HFF&+;U(3&^r{|yj zLG+3J9K6YdW`t1B4f4=K`T?42hjjxq&kpJ{Xx-r)2WayD#wbmg=^mh2(46nyC|}iO z)E4u$pC{i}ZI{7y5#CoVPM;vIFEIYTD#4z6H(RsXyRnM*Rg2a2`o5};KkSP_<>?O} z`AgRyzIsUCAMSc6$MTc3opJTe8R!qsJd`be_|IeB{9#{Df7t&W9e-Gk#}0>TJZ$tC zx77~qco6J49$#l`Jf_z1Iv&TR{9}BwjsNR(p!xxQ9k}$nt`0ofudf5Ee$TNE4^2=f3@*+ zf`KhLi>GIEz8jOS&;F_hbZvCwbbTBBV1JHv%(jz_+O`zk`R-EK>*hP*U(C6#@-G(B zhuz0r*ZLO(=ghz88TLPkALiYs&+cvMy6ir>SD)Qe({s%3lwFM7QB%B6iSeP?Sg#qU z-%-)a>_cu&cTsA(6IqCGOT>O-%66o^Y%b&GYUY_kf~&&+sI(zarBTZla8tm0&b#$7({Q2(9F{`KTf%6ZOy`T4bSmXb- z{EhluU;ZlX(Pc`5G=2HIla^zqB&9K?Y?V_;LU!+@(wJdpq^%&GR4VJ;3NaGG0yZB^A97tNah>4MKWL?bWBZZK^K4 zy?5x-TOu{*^#0E1y)aHqZ;*;!-~R=@W~8^u9({Uy?9`=q)OLM(EA7lVy$2b+w?9(T zYgW-)EaZPcZvfI8k)}`Y&>gz;PWerr-nu(-PVXT`Z)T#J-T)Q7!Il39^e#qvBX{f5 zJ8`=%y`OH=r?=(yoYQ-l(OXDE?_w3bbt?T2=uJX;-`}NAul+Y&dY5d~r?<;*Ij8ps zqqp2xHN8nHdYf1LAJChM^bSnbr+48tU3%C5s!wnKZ8@j+4@PgzF=~2KRrGcW&KA8# z1ikQG6L}YsFWrTtCf$If58J6v`jV}>q;L5}pY*|7b4+^jQAT?01WCGfv-*R#p6kC~ z;+f!_vNxhFW>(*Q_U$8f};(_>F~O+heU@F>F;jSm*~42 zbtT$wqrOD{x-rKRJ?&pcdh&27(P74Uq|Z#E^S4EbUTS*%{3DIoGfi&@e*IN{2!?LZ9fB$A^@pJDhMW(90{-t% zuR}1S4Guw2SvCZ3WEH;^{6BJ3#s72k!u8gpTK=EA@PFa|{4!qozlrz{eQ3?wGfw@= zfVV+>SQq>8w&=$s>IcERAIfhpJmSa+9eD4`sv;gr$}7=L>*;q5@s+$ib5W2o6F3e1 z-v>La84tr!At3D-@5Fl;;Pb^wT4~1Inpw-Yae9V9%-0wn$`_fQ`X+-StL%@m?%D<& zj!bzPWK02(gDL&^)$$pvDRY_sKjnNPU&dr^)?m$% z!dRTe!_MJH3YB%G7+0REUQx@LedpA6{XyTpzwwi>f4B3qh9s}&pD*bX zTR@-K@@w^pJ+Ut5#I9t-E{yYf{<(zS`2~0SKK6S4`Jz63)z|6L*JO=8eUH}Wn7*V{ zjK1vyT=cmXoBtNqqp!0s&6mc_rb&4#8X!^}$o?LMf9Fc@qxq**E0}-w`F+4(ALYRO z=T7DO#7w91Yh{jj0x)KDwYP(EtN87>=&S2c7gPZkZmp=!wayKHD4HMGhH8@l~F z@}qIGiXUa6^sDwRe*F2nC!zCZRI`(J@|PUk+q4lFwt>W0N$;}a+-Z&WXH^^r5<2!nfT zU|)b2Gq{@uzIEl16Tfc8aw0T2#~}xHsaVeN1L~Y#A!h;Qw9w>y3pvdxr;H|N8szMH zg*lh^t8)fJP9w@$p~>k0IoDre&UQ^sJ;<3uIVqYP6Xeu|%L_*rW;SQei>%iRL&;YZ zPAD8ykB{ck3DsTj17U3r7EtrdTX2v)KpvCxSC;ud5^~vHxTHxYj!OCB;~} zD?(iOiJgsx{{tt*TVazmks7~qEz!5_({sT4`@IGwFTmP!hrhIkw+ZRYq?b;uX?aLJQ(PD5UYku zD3$j<(9E>>jy50pgW`{`#A^fS@*ge4$f}mbddfI`3(<%EUNjxjw3V{h;51Zxezus1 zHQ)?uv5jQH5y?6m%~Ep!Tnmu^;}9;y!7RlgM2bTwiNmT|;F5~^<(R!=vArLN*9mFc zvb`Tau$O0`A{2jf=dy%JaiQl1`K80)h zWQPA)pt5j$>ocJRGuwa7FY21A_&glCz9^pu85rnK;Ivmf-in0ueo zestXjXQqzcedD>u{cr!5{*IXE+22DydFk(p_3HkDv!e8U&#k}nJo{^YeSbISq`#@3 zdiJ-hxBkwUtnM!ymQ^-(aP=2HLOEe4k6P4rT}l`yurjVo39Sd^m4rlUgyQm?(^b8od%`LsWxuK6?)UCHdtr*T!)^Qn=a$>+_XS840W7|<+G)!sRT zM>Dt$%&TGo$J&bp%gX(EAL7Xj#L``(PpV`+fwSpwbcl8WXHdtG98KWI^8Vi@@NzVP z!zP4#*1Sy28p9IhU|u$iE#(T|ZTv18yvyS@gGL_fzVs?)#;G%~yjCXjd4HIMS1ps5 zUSuJ>p{fU0pp<7*c!vUC_}_4CxpE*6R$&;_ zF+4{K^PTViZwkXdrx~B=nU$BaZos9%lYN;aZGDx+`a;2yp8oP4&JyyMmFrI*dh>pb zQ|B5~`sD5bN4NLxT)PyDJJ(zMGrc<3s952u2QR!-DVEl!_EfCCD#d~e@0Ag`pJ#o) znQ{7H&-tN)*ZHB2n|_tdfqq$n!NHD)7g9R~C%WViU(T@gWLy{&08Vy6&Dh#{2HFM% zdcYRzJpgk+jK53DF2>EHmXy>Wxf)2AV0+)+7U$3Y8pWIwR%aa4nZW36%_MuA*iUAI0kdLxA>A7>C--qn)TxrToR%ym&ujBhKjW2rZ(JDEH@4kXp21Qs} z03zqg+@D_3b`3P|CzdnSRG-g)T5NAv52hUOv7TlkSv}>d4~oaf2B|-6m2xWNDZJQT z9sNtFY*^9+R!>5AYg)?HT&zICd)BmFFW|3ux30z42f=609n8h*FQB~qQProi&>bJ; zX$XCKFO*-k9_r}B#69C*p%L4yyHa-fVw3T`SZArpPR!A4mss3Ds>Db#mxE5*O%Y$~ z?~dI1T*QGP1Ps>u>Vo4>rK>MZ)KC*O7P=rR!un*=)SK~ zz2#FUQYo44n4T&1I^!$~kNDSoq3&TITglF6PRGkvS*$mW(@T>)pshEn(Kjk!uxlP6BJ+wLV``d09JTQ<(L z0N5`NU|DcAWV&xKEsp%o-Y;RG*&wOb6I>RDq&zhw3}p5W$Z1M83ya3Lv7|tx2bNYo zR7n6;vPo9bfK>wJi}NoWmv$bXt1LJ3Ud~m%5q}B}t(~jPaKjuuRZ~qp)!)y6iO*g# zChqZmzJD+AF9wK?vj}B~LGHw&?HKF_mZUiaqby+DQ(hSos`Ae%hT!KBlN$ED9gLd~ zI19!3Q(z(v{x?F22qyF3UcW`febNKp;1K2Da~cAR%gJNw2kTz8q_jjF9y`DSA0xCL z2W0TA0E4--@0^zA3B|iSClYgKeyaT!b6`BLpX#>4u1@SeeDL6W*VFT=5K8v+u zfa4t}eDbPUfa|MRxAFanP89kw<4d*7Gy7Q#=h;jsU{-Z@`$332!zdSh!A7}U=4{@H#aQE4l^UXt5rPD>`P-jwW;0<9y9Gnf23qM};VHUKLHOONVvrjn zH7HgZ)_h9RXz@MpSkfCCj*aBlA3nmGwO#cRwZoqb zludQYK>02RhN3L)JOnCf_%CLP!cxIOoO8uM9s$ORgDgI2I9Z>zq&#!-)zep&C(po* zvx(CHQ)vyg*V543)MzlK)P{c!y!8{*#29ZC=XR)*`J@W_KcQg_RSm0g_OI9h?a*3i z@~5FS>$T_OGy1$JeeW z9Tnk$u1}bJTzTb1KJeo%DK`U^J>^`3>%RUUO0p5Q;w8HE0boIbxZLKlL>w7i$6`%G zd9Q4-KC&cd!f=i*rX9)<3==5Tsjr5N6EKS_HMrFHyB-lV&QcaXX5DU+Wqfie$#9~_sKY9vAsz_ z)5aEC@xedA2CCl>ObQN##EQBTanLve-4Cm&J)rioyOSDr{}<=MhtQ0*f%s;R(m#w= zqOcqNK?O0b@JZE-bBi)%@KdLkulkM9eCUZ(4L=)%YdpphC>=Lu6!~!HaiQ#1AU=wA zlWgL6gwkc%ORg$RDe$~;TvWtf?;I)}E;tkrtTJ#JYZQa}-;TksYm0PEU@ZjiWfRj& z+IkHs2ozWMoJg4zE7gXohf+JCGDhR76)ctM#t*>yf*F|Lx0LVv6HFiUF20X}j&ao5 z)*mXkT2mI_o0hKXWANyTqaAy8uF|-kAnn8hCd%el9_N!U(tJ50%2u%V4=4zIFfsMT zR+!ZYbJCOm(_$3P5H|QcOT-}6kA z(sKhB!w#?oxIf6&oV_@Nc;9|G?o)zIZj2&#*pmE=jB<#ZQ9ccGb2V~*x&@*;5=+xL zZQNP{=#v~^d~I=Pg`?$;4&%Ey(6Z~2uXwN1U+Gr9d`#O)q?JO)0x4^6V= zy%p+ZRXTSGB0g@wgaUGFTGCtM;x;m6m%qiCE}1m@9FCglS}L>^kfj0Y?vZtW|HmFW&u#KIXoaO~kly+pavf#BiyC zVlGebzuseG@9WJ!9#e{qJ?L!a^%B&(TOA&Q#Q3KvOIfLmKi!_M3~LdZ$@vUz#lt4P z!GT}~8aI1Ne!J2SN~d|W*W1hfe+!In!D0}D0tXl4dM1EzXJUxkqv+ulP!j85GcHrD zWZV^hu2*i{WlalP>~62~=&VQ4dl3D=MQO9ebXgt~t%)DtqLdBSAov6CSxAlVsjY+P zC??D2cF~a#;`XSKCbYYC-It9jI@qZEl&W6)mWM9dO)sqaYu_KI>#cn^y`wf|aMiG~ z`_8j0zweLy+KGJe+z`wQsAt0->kBE_uK=G|i)ug=oyblb)R zh*4N}s-rwX1{|l3Gxei9d8g@(Q^7hgPRyn4gGUR&1VyAx3e$EkzB%c^PjzT*63W~& zO@YaOxE08+^u3L%LYG^AOZ>4xFslGCYwaz@tWz$j(CY7C#;Xw0f27F_?O+U>Sx&!@ zOTqlB>Bac?btkh6k>n8gSo)5#@&McDg02H>cP?_zNSTnAPjBQ>%M(s$_i#cxEvhn3JB%_1GuCgIh0%B4U|Q_#x*9~rJ@*1|VJ5&Fgnm7S zxKCPk-3YQCvp%q%NqKIV2*UTqb}zzra+<#I&6=Vod~?Gv#7HyhE5oD@tQir}_TH79q ztDE$^@Ek*`gVS8aO*?`~oqB~mb+Vbiy7K^kFyYi(_wS5YKpa5RMJ9mFM{ zB_-9@Q4^LvhKvVn3igL7xW^49!>3>A#oyT~{bm4PwU(uG3pjZ!e}#e>kfxMn6=eLb zBmc(f^~ipq9$HA=Oz!fA8+<5lXw`5l!p4Jx%Av1bI%z3o-EZ0D2(liqrUB`65?DUR zo%u8#0S{1ozoKAsAnvTp!U62Ajz*0nrXH&Glt&zGWzge+0si7m8sJc%IJ^N3aD^28 zkaVVHF1EUvtop%J4_UtfX^?h#wM3jj?LdNHoFuyHfuApvM-H{n@z*cy7otU zpOyO~ZUoBj|&^*6-70U=cX z5XXk=uI2U3Y&<_t@%p@*d>DBAnDu?`nP7R|d+M2BdET3OYh6nbEkn)#Eob^acPe}S zWVAGnWmNtC5BqD=X@7$fushSK*zVw+B=MzGM}z8mpbp55OujK}(m=cM=Nz4fXa1mR);Dyz$2fJTFTTGNe+t-d8YS_?@GzeIp)8NLPPko> zkt=YHmDQ(xaAjt}jXl+CP7PV*#d+oN)mej=@%z;#AAuF4#sC(_{K8>3TVcPW?7`Dt zi=H|87x!0S1*sCh&p?<4$frh8X^5XN zyuHLb%F>k8U97tx^i>No?PYWG7xQX?M%O|sG=}lW?JY3lwEfVie5B}E{sgKu-yV$XdppKD3w&Gh++NfNIt%TpF!vppm@ z6k-Z7_zrU>t#HLV%r&9QHL=T=&Um5f3m>A29+`MfP1Se|NSh3@^*%n>tL`*N%9jFf z?jw2ySx`YuPE}19fB9T-D&Mp+mR~7x*nXq(m?fCZ`vt1g_nb;<1Kgzc!!K1*8%MAC zwfRyjwE%mS+6v;q5v=gN!&tbGz+$K{!Q8WDqBDCkOo%qq^)FNnZ(W0BkA0zS7+`Te z*3~fkeb0Wgneop}=RU4wVzP-6h;FjVrisend(VG&#|B0UjDPPLV8>^fuJ1i7rwa3B z_c8jS^ae_%Qqqt5UR7On&Fxrq3Ad^NcJzIvs(ON`dO3YcdIlvQP||>sQj|P@fyw)n z)PDi{|CgER^M9e^e;B9FVU7{lKV#Qa#E3tR4>xJLS$;!k&$eLY+XQ0ycLi31$|Ica z8;miY^rQYv(gN80Px1z$C)M>2D}HIs@h2(f`b;9f)=XwD3waxW5E_8r=Ltp!&;ZQ( z3i0(4zbCC8WqBKbwQW2G;J_2t03>|ijrm>G%m)c?G*89Rl#AGps`IoQ1=ul3Wk%RD zdFH7&dA2;3yZ@<{lL#|T;zD8KAKBofKN&oSnv-?BaneehO!`!CY$S0qk!Hm>iN7aB zIq^L`PLArM<|IUamC27)qC6GvPOzDZ$Xelu0&DHdnTS9CMBt0$xbduuEQ?tzPpQr>Nf$8KXB2Yi9_oIR>Ce`#CDkC}Xkl z26MEWK^T|mu5m3XJGiPac0BbjEbFujd{$x6ah`QeX2nsFcLESUB=JaDgtA1a$0k2D zA|mGjN=;9KjMG|BjpJmEH3G1upMw$aE%8DDq9w|LYAHSv!k()ypSx(p@&Wa+d&VtI3r~?pX}Dwf z8(NB@HGrm(vSeGj%F2AnwhXqGBW(+0B~4%?#)HI|W~(ITlY3Yy-)ybKAnYbF z|JX#$Q)#l;Hw?=j=6L)ND$C)`0`9;b4V{D75`jg~qW}Z%eQ-lP$YNU+gfEG&3d!v@ zsE$5hoqaO?W}Sgftzo~pOl=d$kkDx+$D>Tz715Wvm06Eqo7~=qW8`^{VmObM!G4;4 zpM~G7xIzE=js1)00|3Oz$6KB2&U+u?gkBJ4Qzl(hW#h@(NLF|3EY87j*4_hB_b7n{ zQL6+K51ofOHy!K9-2n#f0sWsPMl+h0-`!(K|E&TKlgn?Obxmd&sfeip>A%G9O5X&t zfQ))bMsrSvn%9TO2bm*FZzQp5`6l9HB>tHcWXhU}LX!LplF{)Ndvyx_Kv*CIwv%Jp zM(iKmxwXA)?&ikLxtq^y!OE-*qUealN`JBSpH-y>dmkc}%c@lafF1GbHDO$C+}G`u zo6jtLN$^^b>#=*Lv^zvg&s|vWYKf;xS|}?kS-p9|)8w~dwRPvU;YT~?q+tsdf$@)a z5)AGDFFSJ$%rSfcP9N=L#R|_|P$OrmD;-&Hnmhh|zGV4h`EK;^T;(aB4I-e-Qvm#~IW-79)4B}xD z|3VglEM^TWlV4<=c%DOt7~Mxl?h z6jU52@glN6l%<~dvz)tcU-Iri6`H0JfH&#;PS2-m1pr|;0XR8TbSaU-8?z|Vw?pFZ z%kT!zS}L>ZQIXqkBW{y;pe%w}aQ48*@H$TVUiLBofB9n7p|a}VD6)Q{Fyes{UnnE% zl%@5g?xx_(_Im*=b%p(lo<$%_eh<6i*{i8fbH9$5%GXq4F>U{ApP%uM*O__R91`%* z6hY@03Y*)=6A6@fR~a_vS+Axb$-ljU|GG0pkc>dO_-vFHMVS4MmvI>7^EwJz{Hs=k zrmuZ|nWBEa2)TonDT1EoH1kZjM)XVkoSbfp}z^$!r=EpeCgjagZ0N+-p;Wr|NyS*AB? zVhgcJTFZp6n`L@eJo6zdH|2dS7b37$RF1=i1q?y`@GT_&lR3tN`T&cdzF8gA-^6|k zwazz7R#Rf5WC?}GQ}E>%(~`+5if$Cg=H^V+QiQOYB38URh1DCrz*@Rb7F@nUvfijD z*3?|$X_EVtm6bZ}``eTI?O1J(C-HtYWG#Hw3|qJ&u!>YW!D@>M78|02j@0MqFr8w* zovh@_Nh-?k-o@JHPtsBjuw&+PjiXhUcw3T^%M`NMP03c&kG$ku|m#kbS zFH&}AIEAMAmBq4Q5|5UlDV|kAX4Rx3H$Fr>bDY49vIu4I*VZH%{+vc2XoM$0#%U!e znzdHem`U-Vle9ZBU*Z>KJm@6f9SP^61WXwspZkf*ud0RRJ4yT#Sst>Ou?~j+RaCvr zE5eTONA&B*=R0q%OkoOdo&QKQTa>!9XFTG2CH}CG=niG^mjS}X%K*ldgYX1x++%zM z_W3H|K3~b}JPI6{o(e5D4^K1BPcv>F5?mQOk(d0P7}*$nR*7|DZd=675i!xqNG}+%bXmq;eeICg5i5(T-gaTOqJ& z^eDhEP(HvObc~`kB2EABtp?^pI)#D3G6zE`1{Ait9$=anFGp7xI?&!+V%2z(K2 zjYTJO2)L>lE@qygqa1G}qQ|?LmJF}PR^W^S0OZI=w)EA%9x?ia9=KbBzGQ0$&xUYS z3s%?9V>#7zSp81=Uf@E3m8Djk{Ck1X7Ux0a1AZTgk$Z{#_JjP76=Pa~;!d^)B>xi6 zEkjj2D?(;nCI>BMAmZgEzFRtfl%;ybTzYHDbH&T%&H}QGC&!4YcsR61f5dliT!cdj zhOapePR);u1W(ww`5e3_XT_Irv`emuV^jiKXERnhaEw+!0d^eHOx-dZ${w#T`}P<0 zE&oKUrh>#bN$sGltZdsgFaD{S)%I5c?^G?;!Z$~;g;ar+q}l=I6O9kQ=Pu(Pm>I$T zC8!8}7>ebS610Q@?D$t3d}>ZAP?3^)}Gd{$%cnepvh-7mhB?(wz5M!tAWg_Mn%Ta%JwaZ7m!6D3yq_3+D-~Iy&5f^T0t?P ziZ&a#`iGrW5<8%C*yJcXR_Z%1i|9AUR1A3sWTDUISp z>2xrpkHo*1aUz~&ky%ry$aOk55GwILvIu6u@oo`X(&uC;Ps)tb-XuTZ#7I$fUO#Md z??;Glm$)KBOO&N`Yd(|D{Ys&!yZf;GM2UYb%VSoSV=(-tmvB>g-`5csa$6m4x|jQP z&(FL=(UMq*mc+SAZXxC0HA3|LTM9QV>xK9#i6_Z$6VI9>vwBjIuKN)mBk{(v2xhU7 zvuHgyR|x8(J6VLF^r?FLp0^N`{_~&S_Y#8IJ6v>_hoJsQM0}mZT_GsUvUjIL>&o%_ z?o4$LK@H?}UDDhg%5h@i1OJgrL^%!6vT= zjEA5A&LRZ0VVIyifxM7ML0HW<67M3t5Xx#!ULeMv%ogL1=ed&rrnR3eRf=kxMn?_W z4pZ};YQwB7^`-rN?>5UhRAsYj(wU!(p<0`Tu$#?F7th4Aa&sSHxeWsAPUSefK)_Ad zqxC3qHdA0#=uv|CiQf=Q6?~68kuP0+MB~TVZyWn9X1|%7?+`JdWGN+6DcMSqsBb9w z$aR*JwVq#1^u4FpqsK$EL?f&wnic<$;!2+FM8w&Pi_V0ql6CJ*xE^#gG8*Wd%zNQt|0B?F!`@q~#O9j&a(U)C~$h9i(IxC9^1bNHM7s5R8Q~gJ_S{+gh5e z0%fK1$(Z_4T+1*}ZL+B`zonWs;B9pH=!%Win}#k_$}_Vur4c-T{358WFu_psMm6$0~-v;faM1WW?!q z8TP`|B~J9zPWHuc8u3OPk58c96Rhs*=&n#X>k9s(rK%;9k0=cL0Ru~5g|`N9jPC~^ z47Vg`_5;GsWo%}@W$f=6Oaz9|LiFbWxHL*4?`SF1gmnOr@iEgL_;_85uvEvBOjM?A z8k60RrqLk-1f@<|l9j%U)pe5iCAo^@SrIa82Njt_!QAo^|5g^6^h_-|C2x6`oP?pQ z_?7-*LIa;51FJkDu;$z+$k0fOMZ@{BLPFvK_}wVsxV7T=;T6!2A&*~RLSq#t^cQ`- zNvpU}I;7G=;)mrbj%PKMS!<}s% zYh*)jO5!+4hWi}*G5I!q*H3ihB`psRQ83mj@$+(d$g_sYtZh`}`za*<5?>&TV3srs zlDM~Sc?shTB|~78)pRC9@W&3spY#=YU1NMQA;1j2Zv3~w1q~22w`Z*>qp-D?eK=N+S|fNh-}_u%6mJ<>0ZGK((FH8_vKbazZbuVV zp%Qt4d(nH@ZyjqUjWqdt(&Qz51V=8@Ds|AWSm!K>@0P1n$`Z_u_BMn=Xb7WZ=}t6+ znLQD&Bk_0S5K@+?b?aTdAzVa*aj&`^{nO98H7QQPkN99BDd?*H~chaz`5B zuW|60l-O!qFO1{&FC-CZqYGK=L(a1&S{NKnVFYLV%||em{Z_KJ_Rt6}<3}rrahGqa z0=<5Yu{6ACy#%)&(u#hp1^cu{;wR*ap0dzCIcV_+vCtm5Qu;16qy9eLwD&1Y-9=W~ zgc|$Ngm@!~SCEZS7TiW-YZ37OG50QTHdo*O@EMGz(3#R@^mS@5Wn7yPLS$rcCL@a6 z(DTx7 zdj8Mz@AaCt^Io65_HFIG*4kG(*XCsfPNk{ihYP(HhqFyba*VUIMWX3Qiv6z{hW%=| z>$Na(Ss?g4ao3p?p;&ECSO(kB6I#z`Mr@b$N23lgn6}FZ)|=YJ0c$TAxE>k14ZF4* z3Vv2*$u+5}kal8Xy%|obUU=BxpGp*vbo;x#aoVhm@&7c|+M{ChgkTI2lVoMUQuxQq zD7f7(lw=`2S zBbDQ?GMJtzA-L!zPjIHh1z+(pMwg!ve1#w$K@>)n;SX7|_wx{D-zy}01P9&sfmvk$q7wBtGkKn-Z3%2wUz$F@iK3x)r;32rE zcO$5d;1ayb;RxNJmWtd_ zm$}XFW3Nbt>9!3^mzpFgeu|0Z`7dzX0fN60ZE~VXX+p|Gl+TYdo-Fu-5(Om6JP~}2 zh~U}p{_$9vr?5@-fvEH=*Pn7b>#jfL?5Qg%Yf?g@VzCX1XMbjE(lZas!3wbgHdazSQ}P66ImAD!9z7CJLS+teE7}S2OuDBGfq@4^PoC*@2sL z7X9B~+JPgO+CIuuJdTG8@6+MDom1zOvnK!X$)Nss=1juCy{?zZ^#G`oPxBdHB6vGd zCrlD{-=2(+;%QiSPe|;aF~Am~bUM4fp$z>Yr~gen9X>k}8vA4g8M?Wy#s%uzs?( z*iw5_KSqkr3FlX#6|P&0@@w3@;j7^u2Bv|&1=g0@8cYxL8g6`rg2|**6_IoW%=VgO zw&R4QT`Gfu;h(f!n}R&hdu(s`Dz>|NSi1L&i=0$`4}14!*xJ2S^a70Td`EsYokXA| zKo^Gmi9LAQ;B(Z>Fk*_XtAId1e7XVy`pf*Bo)M(LsR)Afg2O6n@1M4qt`ijdDkjf^ zsF~mAB+qx(SQp*I3=<2sp?`~JsX7!58#=)%O{mU(8&!3t+p4p{kGeXSsJ~e%ky$1Y zIwt<-F-|zkVEUN2h6i`I)O9kp|2){;Ue^rU>l(+zRV{rErSuwt3f+zun+x{yLL9HNU(bThqj6BJ8x z?CB~Le32*?P5Memxrj0|WjqIvXbJN3U_-xddT(N%i< z6Yg3Ut;9BuZh{AO5tBsGOpH*L5M9*cTm)V8_x*;m))17r9q@PNsal!`-ruCDCH+8mDQWiGL zf7;nzNeq{vpWcH;dJaK4f(Fn}!>zmzRP3<^x9QJKNTR_|h0QP!Z@ka+m_1m$ z>iZhw%LM;I7Oy~>%U7IWa%65oJpY^LQ$8y#<@*z2c?poDptoW)P&3L*Q_MSI0O)G4 zWH2W9l(RQ!iX47hF+x_StfPWZ8*Em8pC~R>B#W`g`ij4q`4(Z3 z<*5OTe=GPhi9)2TR`GY$P#@-u#W}LqdaGBSy7ealRU zqZ(7aXfK5|+@3uY)?~G?5~sOpNCIzEf}c2r@hb(NT*)L%q^$Ff-1LN|&Z$X=e=yyA z7l-&WvFUS@;OAvsiAi{0s$~MMk5~VT$?cYKr}~TallxCuPob>4ohudYT&WT(rpD)@ zRHw%8uGkOJ?D-Oo;n>RB-C+6>4ubz(!}BE^io)9$SdixG^s3YCx6zt=jK3o~ z;K4o2O!B$DN~y}N#}^3}=r%i9N(7!1^S*^A{m!LRLr8{5vsh%ZBo9<~>|6a!5 zEW$Sj9ZXPNw85(+a&(Wox4|pwpINP@;gdJhH6mT*BUNyZR$I zaNKTx^aq!=2##Z>^9SsAy2)+ipf=|EUih8)mJ>Wi=K3`0NC!ju176Jw7&(6syg7G-$cZ8l( zV(B?2xL3@|W|8N6AklL+T6)eJ{$?b;`6SqLMx;s48J0#prxSfbFQ40bOf6l9z3@K9}YKlpq0zA)<%i$sqM>kDJ8 z(A!En1?iuUUT12^SJL5MBUMvGI zlSEE^u6@mnrf9Q|(oYvnQRvyM@RlV1sTNJ~mQ7QvNHs}38>T5*+B8MWprV+Z8lot6 z)L?vIYPh0clFv1(1;pJ^0pcE0Aza+Ig@}70#QmDo$co~8+cFhJ(;Kz8yLvk;V7P8-2Xs*2zwX7RQosE);{OIVKDhhQ}V2ZDpAvHz=$ zMR`4o6E^eO*p(N-f%&$j#lS=?arFV0p;j&nvzSYd5H17 zaiV^1Y-8$&fWS>CSsG&0MG%7^fQ7c!2;ynIEhjo+UvYrReRkAp(}N9u_d|FN0w zh$#@y+!W4STg)>}Ofi`QVEQezXQI)b{zVJJd_{5>?n=>hL+--EIHXkDVA@?E_!Nyl z)ITC*Y0A2|3U+tlaBDLrG=-mdEAHXjBKVEs;%d@zA)SGrHnTA$@s#+9@uuPLx!cn4 z+o1p(-feGqg8#dQKibML<2A7jGD5G*bTE!@c)RLs7Y&tbRKTv z)7bO6K=8fdCNfF6i6ga}c>f}}i6g_N`K)7ktbf3w2yS8rNkF@aRsD?LE_l#QWRlO- z_jdH065VsiUJdOz8$)^y>}c1XW`?WXP0SZO%uT#pN%x$?9V7G{w%v8lDdAo*d~8C9 zo4C!=b2jofY52zCCc5vEp409w>N&U3CqXw+_nMPqZEhl=*cN2mL)~+fn`l)Esu<^n zNO!1TA=n+}k2T$)X|*!k#Nk~n5*_X)-e)D--NZYrq<`Ti-gT#Gg~!Wt>&(WuR!i^> zGVp6sjF4_clqF*rKhf0S6(tIjL{5FKopp_(xM@p>n@FcJ-HOe^rWQrWO=siL`fUM$+DFbXj_$bo9T` z6H!epdg6`)j2&xi*Aonf>xo|mO2?=g73>((Mw^b|x}j`6aetS8)Dw-ml&L3f?DF5~ ziCY?5^u&tkT*69??RtXXP(AS|xadul#n2Nw5iCdW5`tUcGCC0a0>|nb1XsaxEP|7` z3Be)+$Kmt+0H1H%9hQ9V#L4hS@37~S;J^&K=Qs#l(!eFz$|Vn8zbk|b!GSh*&v79< zzv=KCiyB$Dbi_u+-Hq&A2o78*v2m#dE)@{`2LEv_`H%Te|D*rN`(gM+fb64*;xy_l z)O1l*uSTZl^+k_#ev1Atcq{3VAn7aO{T=q=$U_o8gB!YSV~FB$DOs1Sm*N}!7V`}l ztPOZFZ0rjuUf?h9~mxo_Qvi>H+_Q@AU8cl=)sZQcNEu`l1*-N9bAfXI5GZ| zNo^!j)9?TTKd3(Kj+=YB7_1dOWmqycGjpgF-qt!sXgDe^fq-1yrV&lS8-8V;lt z2?r=@_GQu>MDz8F4SR~MO=1+caV(?++o4!g=IZFgdIV1{7+yHqJnk<>PN~_zy2o<{I+rfUsB)f=X&55)YryhaHN+U-M$9zU56)}{VmgJDASiksdibLgr|mwC3MMZ)o&P& z?Agqwo_yw3pLH>xrDV0blRg{Ug+3|31KIc#R-`%oPX8K7|BCY;Nya02@zPjczWqnH z*pzkDlxull=kfM~d(V_A;g#RB)o(sb#{0DM#g5>6kzz&GdbP6g4Qt_(>f^sBN zUrtamwenKeFwo*XP&kggIfU5+R_T}f2ahDM?q;tu^i?=gO} z;7++ipGgJu2$60;eZhngUo~$0^;3kMD=#~l<>m&4<|xl6OZqIP@4M*IdH36T09DJjD|& zcth!ensn;+nhvRMr4RH^u63U)!J%!PN-4(H@in-mR#moS3Q}UOmZm_hyh8gNS*^*_3r8He|Hl z^RU<^<4T-jn-mQ;w#k$##%Nz*H%wM_0AWy3uH7Vg(-8QTekIYkA)Fs|B*8gg1n0R( zg0ngX;w4|D6k0d&&5PlB9#hY>$W$EtY=4CDK7v0kM?Wz@_rK4@n}PBC6`dJg`1WlYM) z2wo`uIY>Gg8imtUWl=JGh2KK@F8KCdYrbagO1|_tJ)w124c1fUa&F}W{|ASxUvO*3 z!uFn8$7G=dE?CKrghvl&oZe8~V_dKWO!91WXZvaEYDbB=3^6C(!yNAr`~`8|h?JX} zaCfc}WD!6bGOqTA4H;wmD<;PiwS__NSp0}HF?$WB-?3oWKKy=D&o*SNsuvtG0voYW zjo-1L@h{P2^AMc5Pcd1XDfl{Z<}|67klsd=7~JREM(}Kj!X%&8XFLd)8&UmNl~Lxu zYg@{E_+4iGM{RqV8P;Vk#V*V*>)Oh^qOPUPJO8$oc}{JU(H+_j!bYMj!B+(BAdnst z(u;_)ZWiO61Ro<&K+4fpmu_a~(n6!xsnB=xj3p6px-$ipV=9X3XYY}4HIlQKdCK>F z&67($efeQ5PfJZj9W1*|*BV`mGccR6xdzkM;%IoPf$3VD-Du}g2GiH#?CvdT8b&j*`Rjrz}F@E?ev z9fI2sJPDVv2ZAODZa^>yE@K)6jzBzqMX7*>ii^KS9!$peCh8jpLk5z}wkne;x9Vaw zQbldR2eYE<---bw^Ck=)4D;aeh&y}DRe>+4)*MB@sj_@WoYx%;-_PEcfYx*c=HrJf z`*Z1z%Pk2yNxI|m=hr#O&l7Z#xZ`pG!OoSb39VJ4Z8*_(NYvbMnVVo~qK3HODl@^} zL=4+UnO?PRP4qx*OB3}!7i=Q`vN!bR<{EIz%i)ruYfKV!qs#(4jCrY+#`KLc1V^wo zwRPdqH_9aMGdKNQ!WBQi@D)G$nj3$7_%mr^JE+8Fn#7u_3|xa%!$}6a85v;sOI>L8 z9eM^nhNu0D`rDwQq?st~6`NBqADbAgA=m)cV?n_h67uBj?sLV#r?q}k=>re8mkE~d>FdRlGuAkwa$J-3n16(!i ztYPT^eKCu2A>Q5t7%qUJ7|YV591zuPj=*$GK5-9Fe{}nePl<@$ZLyDRVX1;v5vqW0 zb@Ihqa?l6I3@3!-fMK137?T5H5|~gL%mIymCgL56S=^hY%9mNgKT;Fo{n@vb@U(g&-X&HaF3=HjIm}5|ro)*Ij8%PU&SEa# zf~68`tEXoDLmJ6sG+oH6^#4qbh?!_&meuM^AM&&&k?)3&qBHv%N9#_?#YjqMj?Tb* zoyqZ5?<-4(ESmdH(s1D_O%)gH^q)Z&EUvF{!7i7c)-KpD7Q9P;v7e;c< zwpU>W?S#P>*q`z#9+7V#`0KJig-Hcyu@nb?R#841j_6|%{djeQ-zU+TWK{uC;USYx8Lt*d-I?!|IKrahkARP##JTUfRmPAR(x7T9rhNVtro1`vA3mH!hsXoKoCAMjC z%pmSgcueGcDG5>65V|%$$ZwCc0NI)79!wSL?#dvQaF3+`l19 zd5|SDH|KNpzfU^X>?6U>RjHThTyI@8ooj)8extA{3fhGSQu`FgYN6e2TXK0<@GHQ}ctAGKXwoDh6=3tsa(JBs1YaOgKr)gz7XzX< zIPFa1+XiKK+Qs#rUn7X?Jy&unm#djn>f(q;uWF3{A$TR(x&x90^I1R7u51p@ z{i?yHyqn(LGkMYkCI7;338rf5s@gspI4)Qy)=*UuLP&336Ot~ zz>(y;D6@jw+lS@}Kj^4Lx4EkR_jSv0c6<$fxSG0rJ$FIdm>5S{k%u7i*!v}-sI;MR zL6uhXLF#BqsSb^`btv6|(tT|$QorGjGo?j^GQpkhi%$LB=}1={G}eFBrPIobu+kER zcKqULcoJuY{6fZDKkx)B&2bO^7anK2MFF%qJWf#CNJHj zIv(_M(ArTF&^-f`2Ik zD3g4yYE>{$vwczkyTmkKu9nI{^kb&}q3jD+p70xhboBCirr_-)9lgB%aX=5$bLxZ+ z)G&oGP%q%-uho@@V)Pdts7IQCdQeuYXiz^wG#aQ+$H_o_GL8o7-yR_O8Dkx&mvuD* zbpw8+lB#B97#_2+d4-y{=>n)HK^K0uTy{TcsE z@LY*PBnV>8&1DE;%mJ$)mOv1P3a626ud7vl z;`rDNB98rUAaU&4B}^P^+#e#2=l1+talEa)h-05$gW~u@7bA|3oi0Nh=Qb=`9J3lm z7RNz?J0Ol9LjYey&iKWHo;jCK(?< zkc8kG6(k=EY{d-LTL_*-kbwX@L;}Mw2>_-*S-;fj9IfAa^`zQyY-{;}PxQK0$C|o6 zk2Yw6Q`7GXzE|3SNmkSBv+(7zu}`YV19jxg#}vb_Fn7__V4c8>U^4citTx%`I{(HV z3k+3x_y0LvUjeXG{moV>oOD_mpc}4++wZhD0Kxj&GHHNY&;VM-@5ct8MhIdNoWw?* z#n=^-hoE2Zs0GQtHTAc#4DoPC>I4T`owB9=4KCrHuL6IM-pYl&hj-e9?5}x|>*HuM zv$=-XL^4zo7q8Yy(CpELFF9Gi!Sw7A;IQ$VXES(Lo%%!9(1|0-5I zNU!qCz}aiBqKq};x4Vn>L`f=P?!rL03qMpb3_ByCg$Eh`Oz~1>Yym0Fx+xckRVZh@snB$#iMm%tpEI$bEUF7Cqq1wK_VL? zEq5qeMuj#Jrq5~m^nRT>PoJ*Cymu>u>FHC3eXeKLUF#4*(W?k-D+h;PJ$-6P_j9h{ z)w)tLDWkkws9QotSe^SYQ`+jpF}G& zrEA>HPdKx00a|WD`Gy4XZY}Rpw9J0GR(+&9YCSDRPdiR}q`BWouK_#Ub=IfVS(E1Z zF^yJWDs=Kyj!IW{z#5g&blNqghCED~kPD+HP2j`)$&2J>`h_l5_EL9+nD%6Y8ObV# zZ5pjM(sT0}?mGL^>J&<1)l6TSa)AQpG(N*sP(VL|`Pgc*5zIl3o@6o8o8M7$!JJ>M zr$$$6<86tafb@&$*1YKH^1R`gH@B_Oc3tBHx~YAsg{_riLk>yh+u6 zv*XI&FGuSldi8Fo8V~*HjQHCjxEsOlY!0?%YgPOXCa-g7^4ilf!GEMMO0^QdEi;M4 zHBt00<@ z&&bBFk!0h$NV1V@lZ~yBWMjUTjjW(-%n6Z=o?0GgQNjpGrjZSAHpxb&eusxvgG@E` z#5yyirTJ!Oc0A?VSN-N-*X)9x;o0JDzR@|2EFaSkPX>#h<|*pr`Ie;L`z+UkcM-bE zB~-_koL$wAm+SZiYlslqohk3As=2zJX6bsG#g&k*>q%GTGF^qMELEAVD<_@m1yz>b zd_UEbpGuSRPkrdoXVHgJEVUB&Oqr1Wg;Q7>-$rm3f>{WBQ?!T{KtvZ{ePu>PBT#R^ z$p0Xh1?@?}CySBKB=m3*wBAu=37TyXs{jA7pr!nipw*m06&UP=DX^d*ULN{q&_M7m z^kpggZ-@F)ophWf=|C~v33YffH`gx+c2Cx=HWBVa zA3eK^Meft^2EIV>I$oezUBP0u25>Rvf(mxCmEgd8_7`Yw2A5Je6Ppk$f=@BX%Cl-0 z=GiTTC&7Vbc0>FoaJg`X#?Q{mvi#tTY+(+uhw0Mkbgb27(mbl`ba^9zUpQbx{?6(C zEcojVBbh{^L!9T7;(od{*?;AY;!qJU<6)wA45pt;Ww?3C7^1aNOrVz+kb6&ah`vLOj_nN7dg>|E8z4(lF1Z_Jaq~n)Szhs{Ax%AG!Qq>LJ-j z%~o;OnR2F>L(nm27jicC3*J#WCX>h{9lwJNrgWUkwOVWan4GrDN~Rqo?G;C_=9t-p zoW)w4$~c3$w4=x{_XT(97Pp80RpeF0{8jxGs2J@eUrW$jc{q#PKyaTl7n3MM&31(w zmULjLBuXcLr(!gH88iCbV7Gt?VBTlQujbQ#=7P8V>TkV@vn-1DJI=wAfo~HBj!Qt% zb`KtkQ9&mJAE9?WPrIY%rK{%Zc{#Y_KBT?)7Rc^UF&I{ZE5-b^7KB?(0x}aYm$bm6y(uMd*rh(#f_;=doA%ST=x2;lw95dAFDU6 z#L}3S61bP7e8WWD1uW0-)Rj#3hbR~R%$dAa@U|k#An_|<+3}`Tk=ACcu=x0#fvT5% zJInIFUPt9DFRh{ZXQOf^=QIAA#xsW^O~AQOSm!AibFbT1pWnoaqoF@mjqh<|Zok)8 zy?m;3W%<g4xM(u? z0d`Km{t)9^1<#e8(@cs`@zZxjuK2NZnZQ)dD6_Rz<20b&=37k5Rm1?P?|b=4qsIg&~gMyd9AFnpNczd20mOyVO+1$umnH>Pej zuO0a6-{M^PkOR-Rcz#LuwKkuf%9mm*oEz+bhBWRnwXO|v-6N!6f59l{= z9&-*Ym;&xa)5@aj|;X+RIzzy)ZRG!jJ3b^SRRY6D0(k>Uy(2Q7;o(HU!zez z`0SCF6icuUF!XOz0p-eb#oU0W61xh1NYopXq|a0{0;lho3>l^$hOb*m_;i5!T!Ax= z#pey4DEvXh4Db%i-ZJG2Cc_<1knNa}1_8I0B|O%REb=XJlo6s&REEc+ zntLJe!0jA@-~t@RpJ^>>L>pyXEIJqYd@9=)bpIW_x2bY}(^*r@v*_?g{9LMXg720N z&!pg+da0PKZsu;j*6C}F@niED6YW*7iyy}LCxTBDc1-eF-o(-iCtiKJITrJh)G7V{ z*#YT~w@5!-EZ;}-<%{K;-o$BjFqpnrp5P6s2_vIyuT-iJZy&j0jaNfC(As0C8dhhh1V)0gBzayHHhWGf1@sQl65G|!%+CB zPA~H*m4|oSjCD5Hqevg{|33YK2U^0e{ z3Hrgy83^W(+P^|lhMxBW^#ryS)uG4E>3a(VMGpXGIJKP9>ecKWOj8UI4? z7h;THXi|r_`D%8z3f!Jc>CFqA*?fp`=rMk-(OZv{myO#8cXN$WaAA=)r;i0qJ zywRE3SGFCeQx|G-;4Q`9+u$Gto(t~ge>t;HlF2@FpGxKzx36Ce9qf+dgXB(}BkvsJ z|Bi25??&mPj3f!TQ|l?5fIM*0l28(ge`9{H0#WP@1>352{NT|0UR(u}EdQotP z!~$udDW}_1g@>{gwS!8_uOnn&JR(WAoQ-6$_c!8$4=bbyHls(s5OIT~tzU@fh-U*X zpD=jvg$R&nt%Hx@H!p{oGItuBRcCg*LhkcbxVnvVWgOKV%L$F~ybm%`T}I1`dNiBrZ_WkP7dhChCu}ElB}r-Yx=sb0EsE2) zS=RxqHxH5`>xE>sB1;W3o?JiuMfz~)?KJ-XrIjK5(j!iWt!V-oWc$_|Vl>;^p5VHU zVle$LlgmxWo(OcQRf_euC#xMjf@wE#Qc9dyQRg?>uUe+o7}`55^P_MXO2Kp3>Rb( zZ_ER_T9_~Bv5W`qW9&AA>Blkv^L$<~gTd*&UyrCFPgzHbUmnZw;B?n$H2$tXEj65o zrIGwU?KMm=4|0|ow!d{*4~|S_1m|Jc??vz_f>-z?rRy8cMrw*?@?R>2how)uP4Dm53WqYDkbU_ zKK3}Loy% zt&LDmy^gRmo{IZtIubi(#DLU|dCd7G#VqhGhO(BZ78m;PHAgIB_bZ-{xb%lz>xp})}F(xN|16;_9CA6|o#dQtF8(qBL_6L`518Z76f za+XglVo-0VW%Kyd;n4gI|KO_1LT8Bo!&H?9oRWp6+Aw&G@pFd_eq+!ucns;rn{*SA z?j5|IKy#`}2;#%kd>W-B$6#;xDePl*Flr$`lMi!tKgB>k>afY~r(AKblB%O+QF);55oy0{T!>X+Qr4eTCZi`fT@0+WNa>ceC*Q7Z~ z<>PJ`xNd_DKt42_Y+zD^pWv}Nm%+3mWSBQgbW_=x9pUDrS*bc_7DYHm{bi{<{f3^f z78XMOAxo3IkMZlnL-r;in2Ts@62;>pbl`s4NHf2o>Qsv_+H_J#|GE?<{p;RCrqK?< zFqxFYNjDPwTQN*PGW~1S?g;(sp{U6HtIr;5|GE#jf;%K_O?q8O zzd-iJ{fF^v!M_pN11Vf=p4YCry&Lg%f|i;M&tzY-j#(!fOwVL9ERD`v*>r3C>cMt` zvj=qyx=F)_UC_T73^!>27A})irg{55-=v{hvIWFe-->n~2G3rsY0N%o8F`Bqq5KE! zBQL``TV~|F6I^J%+5c31B_w}bD&sxTjzRgTd(c$u?P#MH-{AzW6+Bkj2qYsP{z&p+ zZh#4u4=?YRwvK93v!GiS9?&JDE#*(*cC?obrni)9_!$G!Z29jU7#m_RJzEZ#7h!@X zb%XspTOMbbEytE}#h}gsOKrdFVy4$0u-7)jA+-&sHt-$Qc9nXnw&#?+AET6o=xDrR z{l%}QUiFPeeXrpp-xfT0qY+5vIm(TN5$gNla+XglePF1*%Q7)o-;JU4noB~}k%5Z1 zSD}XBm!!cpsiKhfK}HI3UFh*&48B^TfJCEW=|;YqDz5*qWuLQEKHb` z{kOvIV+Bcj(OO|TiLcx6)h|aY2XyC5xxEmqI4P~ofSUp#OVx>Fj#LQ`{FbpKgY`tB z468&lQ_V(;#www!c!@#-)d_Hyt|j-`v&BvOE3ip3dtLlm|G=K?NMvx}DaZZ&UG@IkgvJk}u zU6hE45S6b)lP{0Hw8dZ00~re}hUj8_E-(r~D+D(qxCq^~AG#}gzon0C!(RH6Kim5V z!#X|FM=UoQ`2)38ANl=a=zEgfKi0t>R0Fo_wV%17)4NC*fC5?H>IUKH1IvAzpKCR)yFsdY(z2vHt9v25V^e1;L$SQ zq)CVNg>>tKcok#wzVL3%q=?&6fCM)PkWqNjT2!0yxH$adb$hKJv+<~J+qy?*gm2sG zxr?!e2Gh4~0VaQx=C88PJ2G3-TyDIc%NZ%~+m(-(dHG9mA!x*E7#h$Y{L$Ie$IgVA^P8Sk+H6BgSU^XSw=& zO-1NnA|xm#cfG<)?l4$oFd?{ThKg_kDl$+DmPrK!gE1=Hi@<(S*=g9OyT~@Jkf1vG zEf@c%`I2?Ck4g3S4RoChunqG+g*^PMfv&7lXoepE9b#!8E^q0n<9B=O(!{SP z-_5&c-XR9G&7&S<3M(4%ic7(6Q;PA}9yR+kb6+ZWFWDXiQeC&#nO3l-wS)HeZ z^-L1H8Q?m-O{B}72wTcFR^TMkC5dI&wbTMix3S^nay%Xj?||F%Cl{^_3# z-d5r>Np`RVD}Gy~{OyDjyF~b`#z=eMSH@=vK2Jtkkcj_}5k?&q>0ycV2$;3PIkXOf z-y_VJ6hTVvu%4T<<+v6^;_qFCStShgFXDND-vmDzw3mq_V4tOyM4<3?pb5y`%NOPLs2244A+5V0@#- z&5l-vJ*O1=bZ<&bdQ`q8-(%XEgg6yfo{39_N2O-WZ@j^@;lZ#T`q=PD-dFUw$F`%j z-A>C0*cEek$vf>MAi;FQIYz+beSs@g+;+)p__hx9b1BBY=?I1b)bF8JL2w+_((WCm zA~vHU-ozB>H-aw_&B3JLwy#v`FNKjskZqf%G!M3I)}3L#0}ZBa8^B7W)Ho3zScd62 zW81XYVX4uYIDv874ttFf92jq(*3-Mt8zT4&WBwcjeG#<6(>R6OEh)T$CSc$z!vk?qJkcNlObF4gvVuF8U2v33oZp%aGbZQ+toaQ5#@;C3q>W&K@ldL=k zq9&?`@FY0U{BK)6$6~uwcNO@rbCJF~|3B%w39xVDc`qOxs>ZQu-d8d*w{OCD>l+5S zIBNaEk49P=V>Ihk%vqcu`1LZHfyA2&6L~XfnwP_7yzMk4#<_A>LP|<5iA042|K!~e zuyAi_4fkYOq9kb?y~pw~`ul6>?~AC=<5{;CRhx`M zckeDaE5g`$7E4ff3;w-~otjijNQ)4qQxW5p1oui5ka+*aL$UOaW_qnRPBo)fsi#9) zDGgHNZH!*}RgPy*n#UY(^Vap|XJ4VUlCA#z=ek9(MD*ZZYs;}$k8L-uM}IK+%tB*q z#>GG#HJ&+0o0dEHRJ_V%{-JU@Yh5^-*+u18{B%A^1h4+V(nFR*{Qll*?;#A^-M*q( zswpO*DK?wWJ1Q1mV(0c}2D<|+2oBbqB}@3Xf7t(*U(xhWzDdz_{Z><(^I?xRY{5Cdw8h|4#2y8yO^n-Hhh!iY zvlVg>q~@OR$!;3Rmv6BQX|Mw>LHQ>4k6YSdrKP5IINW?Y&5YG(8 zLb$Vw;*H7qszh4>lk>0o%x;R{FAF;+NhW7U%A|hdwyngD1J?uC>{Czh^Fc%N?qDWk zZJCTUnLNGOMEeqhb7gE{`&sb0!j4Ij$=@Pn@=jR8Z)|4gV<75vCh>w6iVkKd#+IQN zlc7f?;oo7FPRH#u9R*)6^AAjt3`Mv<)u!Gq&6lO&UQkuv#I6vrMUu^$E3B~2LbB6zBB1qqofXUk+clgVll zts>a9)BB$VKjJX#m?W9pZRTA0@N8(OpR9O%wMlpICludUJXpWbVBNtJF!5BQA?L7k zqx$UGO)ML4;HXgMCL$lN6c3Rq*CXU4v;e zm|&gta(ni>olE~r^K4YX59;q%x93lH{;_!WUAM@;;ygRluc)GQ&wBOIagEas zi7a>2ez!Lk$S%I+OsRSHPgTV1wJB~-&zQBIa^_0kE~R1j>$1MCO#jM0+C^{3M7|G-Y#w=mV^7Q8@q(lW{H+|QbnFiKHJVQ#+K2A1jPp*JdRFft8*CJM6G@`y%z zbB?Yzyz3*)Z}Ft`PQj~4njoV=KNE*LG^OKzIMoN0mcc?|`xCgzMLRTYwc3}rReXD_TX zc_9%DC$xKp4d{R9D$WQokH6k)i2)zv zOEk|g$<8}a>j`%<-c9fvF&03Ia{C(Gw>KVV?$WYLu5)JhR-fGK8@66ihtpFSez&I% zFB|^EJCa;i2(vm!B>xjmp+Nz^;9 z=1u1J@g{Q>DnaNR>t|2eoCNW=j->p0!ekgKc}RgF^5Y=Jy9!=I3=xoQXAWHTWGiy6Y73-0c%F>3q~&ImS_I zNdHMp4>*qeg*jd;_z>a9Bu{?mWvcf?>2m(*_TFqLW?J}WO)TBQQ*edkyC(7EtvPHG zLlqE@+dmrXrnbCKG6X(oq;eP zZbNVdfNJAJ*2P-0^3yJ?_$8Q0K3D& z`1l(mV0sJh!dp3&S4}E<3opYo8o5tm-=7&;7N}7SgJkxFm@zH>#jx_nIdBMe;DC#A z_)&9x34qzc>#;qCqJjf3GxBjn@a)%?W*>)p<9_?v-s}WNlrY8SC^qkI!RFlsUt6mB zIc&g~^|igK2@d4hpAc;XE_B_DKkrIq`s_Ye*8KrXvHybZ!)WofsrHvJ;Jx=gr&v?) zOd0S%;?e6N8hp3YoCZzx6agK&uR17eKq+(&T~j^n^YWGIFI!WtQhm2)ecHJI9}c)s z!JU7pHC@tUQIR29zEI_2?pJJlEPz2hL;XTd0O*{g`=WvP+a^`AiKL zorZ3T>lC#yjb_b^J!K4oA>q46#?oj}_bW?V7PaPdZ}`gImVha#(lxx(E;w2k_C;E$ z$A_kIm*Tf!wdO}p2hYZW{Bncor-K>hjSxk1J?80PugkmIG|La@C6BD;=wk$@qt9TW zNj-(6&-JW?E1Y6d)aQBto8y+gCUN&GIvtNV-(yVrzvxYKPM7L^xSl=Aoh~lTa=6Z+R zlU9I>=Gr)zR4`9p0_ro@sBvogjv@c}*G`vWX)N?f-)GWve=;XrRr38;nKISI8zr+J z;cVS2cqMtGM3Zh8QlK(NS&qGyHwyk;WfKJ?i%5JCpkyt8hjpX57m&M^d2`}kUiDBG z3B9aF7UNLjyQ9dnPnEc_BB+tQu^YpA3e3iP_>04Qt((5alH64`EiG?4^yIgN9h&Tp z(*GD~5Pk@WDsd#|@l2%Kn&zQRYkX!({S98@Xn~t9t`vNJB~u$r@|ov0eN+f`)TaIv zVX6NRZ_#k&uQYr%Jw7(e%^!QYVkdqEnO&@)}Bd(~*Z z27%4-^p)~2N6}ZlVf)nwV;yRkZR{yd-hQrFHFjg(DCx;epr{IVF5T~0UuQpG6XJC} zFX<#A{fBcn{c(a{Dd{uGw;HcJt?{3)eZEvVQ;q3Vv_i5kJDwb^Vz!c)8)KN`2`GzO z1z#9rI1=eAI^^g%aqh5ZM}ARxPvOvgS9wm=*-H+PPoK2QJ|FMQ9>ybY^-7*yxPZ&E zL8Um3rW`k~Fr3>U#bwxl@`>OzB}FDt7b%H%`t(6JuY6aG36{aQ_-2gYJ7t1}NuF=r zb-qi>KCdXt6(!BvJk2{QCe1rIHh9(QYQ6=LE??Y8Ve?bY?8#Sf32t=z%mGT3iR}K2 z4vTiAI#;%Hq~?|<7m_G>k6_d}`U%@>Cos?Qi~6N2kAQ+TRQK*W8`C^(;%KO+(IDNk zD?Ms`nrCplw&m&QG^R&-Y9Un}wK`w@(hUbgZM}6ik{a`gDgR_l>7-#jqmSSjGNnT# zQtZU|lL#X~&f9u@0rN9mc3Y>Ap2K29dExs6=7ZXGX1r**!8^-*kS1*tQUgSp%oCHY zRf1nFQJ5s9zi)S0rN0`}0Aq#4Svc)m9%TF>!FP+(4w4>2dE1|P(V;J!@cL43Guwjw z`m1+ij7Xs|0$*q1UT5ou40=`b&yTg*qq6|_qC5R$Fntz)V6EA$cS`eF0QLC?ADdj? zgwn*}cEaZczu+*X(WFcv?co7z@n={h>nr#d5`{?Vo-OHg1?t~QwY=&;h0xHaZ+fD< zKI8T(TfM8Y#D+%bDzkJ~`DsjN)lKfCON-Fe`KHvhn)#T9mW!gy9jL{6x+wz!uNQTB z&rI^ZqOJa!Of!qL<$W+UWbcnGwe|=$ceMY=UTXwLu(b8r zoT7KspI1e5nrJlFl!{{-7e3UOo@+|gM>NKpdI=n|%rz+)eG{UZh5cgsNZ1MlFC*xW zpe=$T%(#57?`A^a#R}5XCUvsAtK;U_!3NWIH^V;HcejMw-N_Cnb$;<5?QX~OW!c>o z?+&rMRq!fih9+WW=;tLmGc=d;CvMK$XfQpOLvX-joi=M&n?1eS9JKL71=?e3=T-z2 z5$wjf>{WCw`{HeS%;*9z8Nmr$>H8x+*s;fa(g$Em+!oxzyB_l5d<(}Rmmd*Stv7N;?%TFinsqnN?l5yT=mjweNa zKyVsQgX}`^34&P&e#iTn>s8>7KU-27@Sgam^M@VCZo++9-z_pjO+6TJ*OqW$mkVB5 z3^**#!;*!;M2>NE@(8JZ(st6UkLZo0wrwaN_pT*sazNOjcZAL^*(LQ5TehW)gO3+;8pu+QZgdYz??s-upsn^AThZJb_K9c^tM zQb(UIFaC0>5~@(N4!XF*9Rt3C$K8_6egR#68uM5mD8lRg|rk=HXdet zy5KV<3P}I1eEq}AryN|E(G5Rfjr|lH^ms}MS<;6pXoI6s_GidOcN9AcB<*%+_GBF_)fa`kL+x!k<}*<<;$uEuY=C~;VEUL3U}X-_ zZQz61*h)0T2sFn0wK?Wf_kFH|_bV}{>hGI6&_E^0cOERL#yEsi{GP#wiv`6bsikWA z2I%msMVF(hmI({mP^(zCUBLJpjb}~ zTS4?1oU7Y=7U^Amg!!htXO~`r!==~%)-Bvw9lU>DEBS}v?OuLYa~Q9<*20E>KMj@v zt_;&Xuqwl8bcDd00+)i%Nr={oxwUFlNxULuBDc)#pK^j@7imL;E1>D zeX9QEsbmLZ-SA!ni3qMlFdQp>_aUf{pbCNpu_L76iv&@oc4~t&fi@bvw7j zzQx=&-@Od;-5=2I+9^kMM||KNBVD<%EM32S%y}i0weIo>mGwO0&|8#=DnROhlEadQ?}P?1AMt+^WxhkpI>0UKJ6g0 zpD6h2GGDJr4-07mqP&TlqB;oPTcR+D_S8HO>DrekDxgA)hZn3I8lV2M-X)TAPlRtz z$hWn4Dr2?OAmUt&-76oxWioaaV}8a2#$OS9w~YBrQU?2cuEz4H&5-N)O)d-aZ{(kM z(4Blwj!+y^-{Mj37Yu4m-!h{d0l}-x+@2G`+sx8Dg|ItMx$Eqel(WyrIkQ_(u6)%i zQIFL(?w4*#_iUi##=W2t*frl2AO;2Nj@hZN1P_Q7U{b*bk`H&Ct?tsT$^62VnE;$F zQIO9>1k~V&IDQesZ1T86@>d)A-k-ue z{v&vdqA*OSl55apDoMItHya#2kVF;jQzb3%;JwB?HJFYa>LIAC0{_T3R#byI@LZwqL*jQ0NG~9WMR1bNBeagwo@q^JiSpQT zGJl?_xg}WRxE+U>a|QRw8iytg7t&Bf`5cE49~3-YqJU&s;49gR6)ZFA+Xt>8yyUq; zKbnZ@4x6f3iG`9s=9=W*z(U1v+!wl4@X4}J0a6^l_l1H?pJEC6?*P6N0*7u2AP${L^c5v z-QI@W=^L68S1PBT?~ub6$lca!k1Z8J* zPhwT0f$-Y{$NLE!9k^cbFU0YFLLVKFHOUjNnvZ56@-wqJa-rZOBr=hb&yu}6$ld(7 z({~RXun*x$`|0Z|Bmz zyh_>9%QD0pT}ZaNaU#LV?SbTGrrtf!Q9OkKURHJ+c7 zQO)V_-x-ZUB<0SIG9Ke?&MOvCir==YnbHu$z8fZ zBq;A|csoPo^R+OKW@5^_tKjbn8<2ygmJc*g&H#o)oq z@IZ>Z1=>Z(1t3s&RrS(Lb+TnUc9xn?@cyTcNTUr?Z*a zO=bPYCphaB4Av6a*6^`exOp+k6oCW5!HYbB{T^*pjdp4qs}cP=ceS>o_Q8itIiE~3hz=u!$!Iu&hn|JVQB7#0x2}v@AAxk)S z8#AkJFl`AFY*s*wCHx`QJZ2ymW?Kk(6YB(72>KytjbP?q9E?(d|L6TBrGY#DDr>(k z?1e^P6BP+k*!qG0z8|U6PD&Dro&;Ks(erwP z=}91hH_*NMwkvkjheuy9xtNAo>1?G}qH1PL;%y!gycZto4eH`DusN~wJu z9YSoram?*%oGnL_ck18O>EFuC)DP}8b4OjE>@>q$d%Y{MSJagQPepdaURQtFD%F)U zO;MXb_uagobMuDaH^{sPlftSXMXI1Ds$l4kk*D!H&a|{{ZQNpe=S+L+5*)F0ua^8w zhR$2Dm>HaX-ryOc^E7FnknTp5YB(veR`6RS3X^=6_g=KPF8wil7hTTcsF07{qADN{ z{y{r}2SMa;Y)45~AC9ex(d`bwgNI`^DNaZ=5#>oY;|{^gOB9gIWlT>-S{QiCVg2M$ z>zh`*!zc&Z+4a^8-70hsO#jh;)C$%DsdSQ@$SD#jj|VQ*xDsga{X zZ^<(EK-Mr3=x}U2X8EfaOdpOV*mg_SStzdE2<(SrxA`o&8i=ciR{QL^A~;<16py`7 zeqSPZ6~ROVhcIoh4#9RzCx3$A1q7oJ9ES4SpaTEkLN(;h`a9x&@}Jp$INF7-Au*P) zv48Z$pK5=fY5(^fEEk&}XWXABW1z#x1xV(sidl_{k+rJWQ_fiBBA#+yqfbhY&*eLu zf<{mx{m9inlKdSx58dbhL^|0<{Lu3(omKs)h@{G8hj)MR|=qH0FYc+^I&Gx}$pZ6rF+bXEEI zPX)d3?^&IY%b!ou(^A;aMyEvlKXp7;O7p|aN7*BZdfcCj6xc|hafN@(MNSMqem=53 z`$4Ejp7u&tdM&oXd7k#NMN_^ba$DqXUOX<53WRLU3hA>e&}WsyqsVLhwaROsLGL77 zqk^o}EQ5|rdTQjRTs=b5QzPqIakW-7n0{)6VV}#HVrv^^wK)P0WA~SNYUKNA7H-F| zb$Qh^J2!@Xt~Ra1xm{!7rZVfr_&@9tCT>?5`MO(ow4SAibv$T`KXEvEOMs_&K1q^nPjUDstHFq)I^*# zm#P)2ryACJN~C&9qIzoPU++XcrC=gL)l--Mxt^@=HmdwB%rW^(!NHy3k8r+U5WI#Q z+|i^bg;a`zJHKIixS!w$tq6BwN zgojjSt!e2{6*SqIlY`qM_GOza48wM}4s#e^D|jc_?nb2KHC#basHjBBLQX;w{qzOl z3=Xj-V45MuIztspEk@0o+ZRF&B~06kM}LeHd5Kg+UQjS&@&P?cG|M&Hq1msRi-|RO z7;|~njlSxlzT&L~zSVpTDS3^5)|rx0sv-J`vJIhGc^o-0ryr!^^K`}MpyE{~Q7r63 zogZb2$=VXl{Bw8*^?%!0?nh^7gw8T) ziYZ13CJ**t!eW5ndt~xJlhTCr8KSH?#CWpcb0i9pa`O_hsbrNC{IC2F!EPymiF7JU z`Wj56$8cP1ui*J&B7vlP8tucXj^}Ksi}|nV=wNA!B~fvJ`OCs&ESOgw!1&XGcNgYF zQW~73K#9Q-h(R~`P#+sU4EwpI;LAh|K>Dx6z&c3&Z^XfK)&E8uEXRgbafVMe#c3Ud z(I$(F`JmuDgkZD*sfCa(qh`9|utZJ4f0df)`qjU!8IqF8xw=+#O;n>VOuvq&9}A)^ z)v_$gQZ1`Ywa||>`bP>e+lVT5TkF1yrS5zB7^AqKX{(FDmjTROAJifq3aH z@CAZ*U}x!t{ALKMU82!vE;@%&2femLI7vmWx%H##wuYa&AEIh|#nak8>7`oW;$Cin z`37r)+6S!bM%lYuEws{V?L9kqEzHt;0$*Wg{g>+R9cxwwN63n*RaYI8?42qr1Z@o341K|l}&Q?sDaDS`jm;^ z7yqlft4JRD=u zuf&1IpJIva3+|Ay+a+E-5k|wEKkpmr=VT1P{s?q{Af|+!R#P=oFu@}D_hG90lL>ag zCpb{O#;2bIYx^3L(Pcy!U>@2@h$H3ric9Wq>iE)vBJ<(g+cpBRZpfHg;nY{ zwC4G7me#!7pHnzI&fb~?2gccN8~hz3)_UCj^NE#9;}YibW(XI81IO))Z|%XQHiBw6 z$MZK1@Dw8W9Km+mIi42~j7HEED{_qyI1!xqi*r`Zz+wRd2R9<6?mco6N*&e2=p%EywpTc zz6diN%XE+Q5BNHQAioIV$#_y{@)?!!c>%`K4fZ%PPOxRJ^qL&=TzM_?VRIFE0N;TZ z?PRRPky(QyFJRbbq9{)#`pn>XN8sl_Dd)W3kV^Q92Pat-)2(AQQ#!7ff~`GY7)&46 zW7y}~cjP)AvBpQCQ)H;Rd$8PTLQP#1W9u>on>kSHUkfs8Ek2NKw zfm42(6t~TX&%9{n!bk_7dun1l;b6fjyD_jf=Qr{C%dA zaIrUA9!xjtaGMSbb$FmW5B`4M(>ymJwt^P5IuYzU?e0JA%vp)4@S|gRpqYYwkiU#E z0}X&ONyaMs~LG||ZuYzy+l_@-NpS;gxmo~w0I7^o<52f?I z5pOM|_c=UDlfz{tD}?SqR^@nxOpxRV<(xVMx}nM#(|!*?*NFRI3nlIZ!3q<=Ciyu*)va+kVs&!ta>P~8F2{#FTTeGP-~!TgayfEz@0g`~M;>~|ly%g7 z!d;FH2tK$BOX3;UKi@}C=9$(n+J?6lI~0$O(!&Zl6e|{R{dP8(b|?TFp;&@KhdLC` z>L-$7O#=p6U=mt86gnTTN5}_x6Z=N$G|8KIV>;U3VA`7i9PELd%1&r)Zu8-hK z(2GW6M_RP!4XK>UBO~qFli^JvmLRfso_z!nI8nnSJAwF%todHk8czlK?gm%T z493iWYRfAl8LFGDUleHTYgPF$>uYRJRoux>=;C%zRnQ*_eyG82M-?#40FFR$zgqCs zM4fZ4QM|4bdoCG|RyT(P^*sL@ZD2B?K`a4imt9UE@&3Nj8d$*M?Z zhTF)_sdHg=ED;7dXxR#bNeNMzFrDSxnS37}$QYHtmu~jsFe| z>IK6r>1@W(H7g_?f&-_l2DQWb>Wm8B#J;yIx*gz|&y-G zl&m>e3MJb7U_a2K-BPbBW|(QCYq8o;VI|?wCx)8QqS#!FwSY)8T96BAMvJUSf>i~) zmkc$$^&@k+-=O@02OpUO$;>CBG3PrRLDjfG|KQbtj~&6)fK{3h&+1YCV2!v@|6q-{ zP5)qxXy)KqBOY)BHKJb=SR0Vc}!KNxsV~J`29>j_le3vXyfn@TiCsr(58?2QPW37x>Yh}b)D!6(Xz6Oc?==ID*1X0Yy7<2A1lbgP<1`gI{{8zzSi8TOHP*(hCs}=HTC9rs9BI9!f zKk6_nKr)NBOTdEs-1-)?eKS8`pK3j`^8e3(=1Elp*`=Eu|BHdF3I?*{upd?2bbo;)LM?d229crWgJi1CJk(=Bp{ z3ex{68RBPZ%ak3ju3!BIm@zQi*=rwjXBQ1*Lu0#MMbG%J3=MsYToeMmU3V2kE3v;t zv}WO`&UO9mqD63Exm~mlL73Jdco$o3ry}Tqpczh`Yz$>gY^`ega_;6k#X0Nvusv2vTB?)~<*OE~26owUt&$Ew#l`ueKpUBBIt(`_@uh6-8|oLDW`j zDQZ_Yf~qYc$bZf`GjpGN?=w&C6Z-r7-}iGp&6($!neRDg&YU^3?RqTYsX1WIf6T32 zju6Ug#>3ikwW=dkl1U`jPUvWre z)-G|mPBaYl;eU)#P%{W(i}j27WL4gxDmJAJ<`23HdJ$Pgp7f_oy5~i1kQM2Pl77NV zd_qa911}*%n$qpc%sOz8AfX^yt=o^o)$ZQuDlu?7Mc;8db&3DsYpcfHO1vSXJgZ8r z?ijV5O-r_dpkn0M<+d|{CHTl1zfMSM(os}t-2^>DI?6ohyiEF&eCr9M`gVGSi6guWrwhlO;FV^*h5rQkO#tO}_aNpqP|`hQUYL|HIxvKD)bDUQ&W?oOyn@uL zgIZ4h+L=!*=yFnA?`daa=3qxQ+AioscxHqKmbc&C$Z|wQ<#9EiX4&jezFWmg1VMt9WOlJV0n1hCh3j2Dtpqa<@u}S;8pRB zr{)MgjS~3UO7jz*{n$&q1p2%Tmb6~)2>5LtjwQVzN-E=8(mGjEbAHzt>p#y#jSdX7 zL`KGj29|}G*DXw9e_&BycRyhK*x8BqLsrJ4jB?1Mm4X&b{2{W|u0!FXsTLW=nx4Iz zI>de(sc6W*yEgw$w1umsQ~pF&<$rRxYyNLj<{sM2XN|$kZ+CReoXD!oZ;WuwoMo~? zWCF*`Hm8G|r}{ z>>*49H?^b$6E#0Q?$C5dc~KZ_RNJ`?D^OU__(nA#v;4~hr{tr6F&!2cDRX{@!my?6 zmnqsh%EUxkuCRa}U(phXbsaRtHla&1=5=r^7RapFa=|I{Gwj8(JnoW%ee8*rr77v; zBL7K`1$MugW!+e04Kq`>$769-1dY#35t;Wy&C!{bb z-d66-fFyg|$%Bq+F8@BdLj%YidJR6KZXh>tL*<(@Rjhl$X98SDf~&NEjQ)8Qmd)|@ zqV$HeouOcV%zmq+my+8VAc;viG}u0jd@3$!e{(roF=FM_mzjTJomQ~dHzZB2cEH5);dYw zDt9YTQkE=#E1x6F;Tp+M+=p$CP}pYkL$)cejShLa^Z-Bb^DkwcrqU%Kt;Qier=$;& zmw;eW++BXaJ5>z z{MDkunHDgQnzMC6zSpdA|Aes$4GKeX!-h1@P-3ju1$h+4ol*FoaMX&24aTLhnBRWf zPS@I+;D6{)KJJO)u{)748f_1w(J-->ZekG_jgE#8N2F#W9cC;x(#3MVVg)d#gvupp z7oFU38#kKu)Q1l-FF1aZ;|F*W4D6pf=raL^YIp+~9??F}aX+ot;3+np!!fM)!v%xa z(b#AW?SMTe=~Lw>ZwGN ziw_fN3HW?TZ)zVVp0zkNvlHlDXj{KM1|qB>zh&X28r0k;bqs0&9MeOJ`{5shFn zzC-#!Nk1(|Fqp*bLMICebh&(IHGP}oEu?=f=?U^%Op+Ice4@9pwlQLdw& zBE7DpTV$?~1RYQn+OtkKxWSTxeD7k{_zNv0ecoDhjYP=OPU8X~Jv%KCOy}nbi3Xr+ zoQqLM|5a;IbH0u$jV74-NVT*s0{<7zJ(SEOiMGkl?O zwU>=65*k;cH9FDL8h08GD2j7fM`dSZy_2-9lq8V_L(39FtA+{2@mZK~nuaPS>GoL| zN@At8*wUvr{f`;U7HKv(Ln`r^Ctl}BaRSM4x8BBM#o+iL?Z?fSn8M=rhrxA(B&l*- zQc^e$;%WxRCWj$Istnp^z~Hxh3>XaOvukHz7%TF&608_TEb^r@RPMJF^bQ_^MU;e~ z^PXNhsDbzCrFPIBe=*#zxNxbNf=kD&iH|v#{$!FnjJmZy8z=PFnC7zpG0{0d>@0Aa*4DJ-SI zTntI}n>_~o(g*oX_Dd;!X*l+nhEiu~uHy9;Xz@zW9B#fA!r}n|Ok^c-s7QZ$w5CTH zdgP!?PFcB$fXRu!|HP~k1&vQm06FEkW^#f7{5i=0;K+Pt0bZmr+D3ZJq(=k|&RW1i zp`uAJLbVmZ2P2-KQ>-@9bsj!i6y?_;ij3xtD1e-D>yZPBe|8(7SfAG{iuE+dFo7Ns zcK zR5u`}1pez#w-vN;A`Wgv@t(?t^fkq;D0<`h5Ssk4kLPi2(|KGU??1b#Fs-?1O!EUR z?u(Lio1AljB>Q-NHZ4Q%C|``CNt+zBilULE_mmk>l5k|^IXNxaMLkgk5DY$by05Nc$Ku#%YYW8zTjBJm+x+^m&jN zAhu)!#8o@(1H>M>1H?~X0d3#TM}+n>{0>v zftY-Bcq11n1C1&bqr-%*{34I|m$@>c$swI}IQVM3|G;;IG@%G4<<37My`!Wrwg@Rx zQWkoyJ36%T(V-P@9%eSkcZY!uI+07-psvyeoylr+*ol0ux->eR)mYTO4^7o9JC3-% zl60$_s-YxJ)ThuP7*Nni+Qsjs#oYe2WJbGaP9(kr(o0JEVmVJkNt0x-gX*pwj+Vm7 z$_q|`pX$5hTBW)+p9DJ8#eaKiFq8&gYDYE#*A=XdK`}> z*mCLYml)TA&)I~(d~N)M+nhSMbnp^kvNaNQ-%l>`VA_yyRMLNtE;1!?bHTW}i>o75 zL@cR8+tD8Y@XIIb9`=du=7GFr6{-Z0MdsxCen}r1PIC;DZTS}Nxr7t3I$`r_sPPUeOhs%D z8aR3fKu+oFxITyIo(7*v10huP|XL-Q=1=uwv@a=JIr)b#u%tZ7T9ngThc zrDIKhqJh9PI8@gYnPAJ<%z1H|yyh*mwf^bbvd6ce#tkHmyC&%~EJEW3x}$L;ia43v zl#D0Hua%n(_%*;{*2*qs7(OA9H>1ZVG!AH%hQ-x4D(-paBXh;2oT15{+4T6F4&42< zzD7Lx$fmEV?mJ%g$Vtq*Qsz1>3JmmvFsEeDQa}!NJd;uUCPyZQURz-Sxd(a z9F+87@@q&6gWJw!FOuOip(yV~q;ok{etDm|iX>W{`MIQ@lwAcRfy>n+3{FX6zD@*p znE*NXIG}$~h!>1~GV`Axc))s>Ao!<(hpiPlj$t6(P*`*V=dxg&pB%OJkdF-O;Vs1I zXkl#!*|$RT%cEi8NZek2$^hB)%7L~U$vVB&MCwGA))lCRkSU+p73uMk-cFiwN|Fm} z;~gt^!QxOkh~hPqnZT{UEc32`n0Zx6pKB4BQQ(&^QpuI+U-hM3e1lt|G#}Ax}tL%4>y%_tWEDTp*U<3OgM6j^H5~cL$v@T56jtIQ z(&pE2ER4uz_!<3`JN(>aL4J0sjuSm-zD5H68iI$DEy&wXOJTKM5!D(_)gm%Cg|>Bj z?FJGugh4z0g*H)K#3?OifR079*bYLCGzWpSVZ~GTO0#;=*J!)uBw8@J#-@T3oLPO30QF3uV@(YkVrT)6Hds4y47KI z3y>bVEe}*IGSm5d>4eb0Sc-p@q5YQN?pHqt{|D#83YyKHuttC=!JJZuKSQX49Q&q_ z%?VnWQ0+3(`%3yoxiW#0=JE3rnTT%h(OF*iueZ}%6L_=0W68%Irxga?GXJdG!J3zEiF+;7O-t(&zL^{>n)IRnj}lPcSKAbl`~UyKL2$rDv|hiP6Ru4C}#hknHUT z6xNH9pP#3&-v2HkJwnoV$gmzI%?tDcY-z|>KjLG(>KNarYwGwRg_F9YJs#0u)$$puXUHah?EJio}%tc+na1z1?ndQtvJ&ioBs75jyW zcw6F8YoaX&6gL8zMkj0Z8qtP4oP-Z>q_2yQTbvhWiV_f(w|io^fzP%nB-6^PhKnX_8wdFi4kU&23XXGxc3d@lwFSAcWcU}Dy*!1 z_8reUlcrrS(PJk)7SiJjdUU5L*>@_TT}hj?DCF=m%sxS7Qyp zT!)91W=8s1;Lti@3AvizEo^DwVG|d>^4G{qgQL!T@v1VS;`XrWw^MJ~dM?8NTIXe4 zM4yvpbf(z;whCO*pRy_^(NJi)ptYsyB3V;isA)BAO|gc>SPj4XM_a=b54h*!@=`4S z>{8ybtYW|EtdzzT1Y=^!j4r~1cl|3!`lr&2Vp7}@2ieG|itVdJ-l1Yp$wfdso^&io zQuT!9$D6&O4pRuHk4xzTjF3gj@W+R;J)*tG@b~DP3B{6LH9u; z2Qu=a%k&Q~Cls($NmRhn2}rLa>6Vg0;UTH|x!A6Op|Au9)+Nz8qSZ7*)9*HO@cdt0 z%)525>mF7O*_RU?!|ShnZNWDvAmc|p3$E{p3!}l`An*c4YUW#l{fTvhtb8FSbX%al zux=X5NYGsL@KEpg!&F>6?ceha0qaC@gd0^B=`AFEV{rkOl6c0^+YzM2XZ$4muo7B( z?ZvHDEIi^@ox)2~;nxDu=GUdgpnn7kn@uI(T=|_Bz^Ad0t+UI)y1}@dX>!d)Zz$F)C}{`DP=jAl{p_IFLfJU?dP9Y(pO6_ zm69UG?sF#Uk=!?2g#6s)DJR9bQ`m}W&z}qIP9X(4b)3Q(e}nF5ok7e}ID;$rAA@8j z(i8Omd`=-vBV?7e*#1~R&Y=A>TugY-X9At*eHIL=n4TdK9nq-6YV0S9?@G<-v*{dT zg0D~XH25x|%Hhz$%$xj+Z-Hw9ZdL?F^f8Wkg0E^nib{UpXF_o-?V^=WCN|*$q9z1cG>kkSkKqqi|nTTPMm_IU!V7fIknXv%R547E$i`o56k4E!&U(%Yq(W-RZMM!C(${k-t6<<%M$OTDy zomYj5^Q8PTsTh6oj8>XG3=s4*dCwIliADyq=3vQUp_zZU({%$!%*vwLHkogiHuN%? zF2VX*mNL93mOj1+(nm;o$D*Qip42q}>`=cV>_6KEa3j>O2pdxVhB_AWE1nhaUsL9= zyb$I*pVr^|OL}Y}kuxUAieA;TFFP#SR~Bip&=Qn*|D;lAAg|J}{^wG{Kmvg&j1|Yhrbe#fd*rj&p_z96#XFde__E$Mv<3YPGs ze@cp^ru2yqomX^P(#y$DAc?6kR1xOrY^i#DEJp)~S@Qb=le3h{T0F}j40J8VfQ{k)PHZeijkk`!D;p`v zEE`{$?FJhYFJ_yKwWhnUF~{s|uyG^U$O^O6Z1gu^W1bRDZ0t}T>HijYWg{h-W#g~k zxWUFz7qZR9%&9JH-2P2A*f;>98dqkj*|_iN{kjtylLjGuzt^1D_`zPJfBc#&8!5>w8>`Q7gN?V& zWt)vtzjk3`)fw4f<3$K|w4bhKqiu(pjWzt7*m%1G(o6WcvXPR^vhn6LH`w^y*=)11 z^JEt`-k6pRHqL&`*qDEsnvG)&*m%2`6B~b}9cibExw4Ux%(8LmR5#ez{m*Q(@vQ_G zHZGc)4K}ugK+nD@u54swBo`Ij@bN+}y+u>@KT7&txf&glq$_!SyAJP{(1>-g{F)y+ z(y%7dKah0$p(B)JmiOhSxWW4?r?bubmz&tleDjab)MTt}>U8AU>sRW;3wSalqH%OiB~mrgbq81_Exu7hton1DmWJqdik z*~%#20;dfIoHlT#MpJgf=y4>0>%HdC5xWvww&^JGG*aT#g@m$>A|+m52I(^-y^B<0 zNMed&eMX0x4VJG|r%$VNBmI~3Lh@5eG8?fepWsHs=E})zM{JhIy6S%d=>H7oh|LL~ z2@O&IFNE<0wP7-%*aA)*07)k&=R+`=7N1EwXvp8Xpx{M1s_Lp;wU9?OCEb4TBPPWi zw#GdMCG8Op;)~7<@QGf_UOACrjZ0x_ZvEI%&G)?Nq~-@;Nhd5_P714=G{PU3l9OtC z%7zsEPtKJ0X&v95c<1er&{DV>PC(YOx`fH4(P6kclP`^qgtHhz14pt_ksYbu+OACm zO-#%vmC}+-u;$=LTlsjdrZ-4U_tRqmJ-%{K+DgCZtQZ+jTut+F(!5Yw;&9Q&Rr4sx ztmdtm=!WJ+9M87q?HK2xc`GNrh~|}$n%9I5_c>9(N%Q`?i#*y^z*X}wNormv_cX6% z@QZ0)%Qyqg%YU3SuaoO`g{+b z*-A`GXdf6#312`0T~%#O-h~gjiWja~7b|(Oi{Z<8fzwzYxbEgu>eEb6wg6UvoIVrK zt4x4XbMWvrA5^@HF!2PRQvUn`H?=b(+JVOzXP*X^X0)5&hEG%AcUqdUh?ivEx3S;) z=|$@@T1{|vY~ok*dZuROTQ-Etn);4M6>4fpNr4Wy3;pSd2Y<0gSDH&~KpyA&c}b=? zZ8+r$%DJ(i@o7UKr__SWx9rn~zmZ<@MaWBT;v@Pd=IN0aBbeLh%&7a`rNwLr67(aN zJ`=u1JbYPy*La6WCp07e{$2YCEjqqX0~p_Xot=-k>kF}*S{vo$YtPAfGmZ@6 zSEk18Nw;ZTwc#U?9!u!a{W?AxT}SRE<YK9qhm-K_uxKffLu>2txjl;wvEun$eBe(*CoZ=#BHS0)fx$%WG zD`$@K_k-l@>zF<3EOg}Vm1qN2e|IQrR(B;i4{@Vf}o@qj8MB73@^U1+Vb>j9_)Fif73CPZYEdsg6iy zZdzrm`~|kLD7sF_1de$$gN%MbdMLjun&m_8I7?52G2!wg>Eq#~n;)Epclo-xW&R z$U8v?W3_su1D+nDuWQcwx;{~&uZx7)ah;Ctjs4{3Shc+zo_xgl+JiTF$Uw7uJVev8 z4US4jH1)bZ@HcSF>&rR!3 z_naF28S*M}yJb#C{Xw#h{yZs~mHv3xhX3V`{#e>%sXukx(Vr*&Vj5FIWM zG`e#6rRYliFSF8>$9rE~SDJqLBD&J&3yd}_YR&k&>bVhrThji=AdtT&a`AII_wj8{ z!9^s9i<Pfy8}E`hX*0?(DM zYx9{9mV=fa23sra)vils=`h9!#yeU1v-&Z`3v{WYCpq!GJe)j&dWVr7=HcoQKoVT? zobHNwSOfNrAO8l=WxbS$`Q#Kdel9DJS(^y42*Z!(va%P?S@?^c*~jN;T%0Uu@6gAb zyw0L=iO$nP*m)L5mk7uy??2Z%si|ApZ;6vf5bytyMIe1Z)^;ZC-DxT5r=+#zN!2W< z8bgVNr7c1=fB+2ItYA=DW`LbRrD!hvs-STO0a=$pTltGVF%7AnP3ba|C6ZoB){`eq zkV(%-xGfqXeW0XYkivx|rf7kn)Tedo-%ccsT5DgW5DBPCYf=3|DxTj76_8y~i7Y4l zXwP!k8bLj_PD6!z;I}*vu*==+C>FF#(8NhVjGWTVaRGF3lJ`^UDEQvZZS)AFM=t0+ zLO$nR%BQqqx+Sf@AN7xw#suyd_V?#9uD|yRa-EN^KFK@KPnBw?dV&6?Ayu^ zqYQ#~SpJ8f2??c>u$SRAJ-L2HI_yUHQwVznB*Br{0j$v%fi~~A4%>VYXAyP<-Q4z* zCJ{u~j1||N7Z+KR6*Zqu#cU~P{sa-oaR;MQgPAFUy=Rp@#J0MN?3WCAU;IhG;13~j z>;|WTTd+c|KjnqgVFfq3g#{lIv;Zm?$WU<4=p=8Kvd^>M9>{*_23MVJ%~Yufs8X|^ zH9A|Hl`(*o!Ai_er~Z5hC1P1XfRCb68@rUoUaTdm21aTU-A-Oc(72J}=Y(Tu6l?q`noEu;SYP!#pYYTp+Z1q#Fi4%%Ic3`c*^ zun4YU{W64xb*D8_&neEpj9KEYm-5q^q2;{K&=ivL@G7*T7prdpe~w1Ls_HKpicVI> zP>up_z!^YYY-YNs<6pFDZc25m;|)pQDOb($q(d@k9(|Iw8tEG){R{aCCdq}o^<0^S zdz43|W0T*@&wqw|@M})^IKx4`x@I`37o*jYWj~>1YmJ)Yy8)7ZPA*&HNx5XwFZ9VT zb&-BMP0;7aPbf*WG7q2eBQYt7iGgdLjeX+jGxh_ZlkieKQGhw|6iIZdnZ&|lS!W0c9a68e-(i{iEk*95 zwYlG+9X}CHxdRz;huN?ci(c-ZZPCxYq&D}a8!>lpr`&-Ixx>!rlqJt~a=)v{eb+-x z?jz{Lt%KKr`8>w_xG}+O!-ZOK42niQDc&dXS`-kvotvDLK)TTF)!;jmLB}PPOlm ze&@cRpOqVtAxV0G_S5Wf&pd2@S?{_SdKh$}OL$(`h1NZZ`A-%!-i31VSD=!18#j{w z>C%O=v@lu2>QwWagt>;K7m_vSNw3MIyENS0)CTDul737McOeN5dc*6CY(5FJh0_0z zd*aoFl*KD_Kiy7AkCItX67q>T-q7=Q3ah)zC%PlwM2!APsO-uni>-z4d8%CRm_nk$oh>67~9kRC1Ru)~->fg~6+RC8US zhT73aR1>sg?H8C&eL>^e!O4~H2WYk94gRN|c0B%v=g^1c8cVkXUl+7Clq)A65oEa8 zXYc}~Z51?rvk#C#8<--HhndnEXNBozANE@lM_c9i4&xLWP$bi11&k}&^yLHIdo*u% zf*zX1IB^bpL2Nre%;5whSoIYdYOt zBL?`lI~;IT#)NjgkqJKwS}|e*l4&A2WfI+i`8WF=k(tk9nM33?Sg(XW+7kRez!KUy zm4M{rMD#c+YD!?Q28ma3vNRk&FCu7SvXqfi?rCq*w4@B8>xJ4rCMIAH7wI}~@`)*_ zedEoab>4WIu6ZLwZ@pAY+P6LWwrB=#l0COjPv1+@3rl+rN!Y|`uwU8kTVF`jZ!jfq zYZ^>Hnxyo;?bu*AIpZIP2J_$_b%WV|OVn);^#(~5@tbv$-d6SoJZYv(sz#sGp{uOF zkaS=92_(T~f9ak+39nKA(?Pz*PZ+Fl&Y@ z=X_#b^R&m@-b%6$jeW*tQhoNNigIs|Q5#FgX{?p>{n8Hdr0Fv0d-}vW5b6Ju^a=74 zNMhwzW`;j7@oJ7dsVHq+uaZfOnRJ6Xlm_zacPQ5*?_;iSNP1bBD<#oLlZ{q#AQXeq z3e*5N@Y8O6UD^%FUK#B$xa4Bzi4Xe}vM zP7V=d@L|8EacE^h<322q5eT!!DSPhOeOUHe&wg`kS9)>V`3G6x&GZ;Tk9PE^PLD#w z_2d){@)5M_enW~Qa!y`$%K`cPTMFd1jE{LWG^dP0??ATu06kXFBaR+_lkHB<(Ab)d zIw6Ue8QM37xSDmJm?7FXg7uclg=^oqqxVKt?Hj9gMg}qYv~Tp)v5GM_pJ?6)(((Oc z_G{mGv`c?>S)i^NSZL`gTXrguc9?QKW_cU|xN1I4Tk+ce&}HNbPT`n^2I*p^cBcQl^NY z)uvoI`PttH<2#Br{PVYf@m+on1KZ7{e~>$S!FiF~si$W-uTTT|{%;MgEdiMMw7(s3 zadLEu1Fq32ss>W8C&sZ(^x*B}Lt01|LXVR4$fRX;qv_F&9`)%_f<0_A#OGUSE!150 zu$8Kwo|#hbrgj3-;e3KEbUr~G#COKrf^{|axb9u3XdIpSPn1iXVk1Ozt_KJcO`)cS zG*vNH(#y(F6D7rH4#$RhgGD;Mdq1#$JO_+=U#G!dWkKUnZzAXS2j!2?Rgyh)Dj7G4 z!-%1?o5$<{jKF$~db4a#T@#fZ=!+oArekqCBt6_$fZ$0>WKvc7q#*^{CrY}H{DhMD zx})grh~MHf{svxuh~exI7&F4r3HS<5K#O>mukAz5AU`JtmAa;3&<48fDDO2#1`#>` z)4!2H&>phIpp91rs!DWcW5pU++&oFoC+}?JNn>QvO}bFA2+k$>e=6w*<%Nor1b`tv z%uhUmA>m?pB|5{yXY4F|8B>Xk86toz4nL;^U{nY+;1+u3Es7kR>sLe_BFL{ur%N;r zOL`0GS5T7Tz6Drp(Zklg0F{duc7tTbUC~J9Pg+JZ_==-sh@AhU>nNFzuV+&-ugfZb zjp$bud=rcF6vd68;y5|=GADOsuh#qxX{QA(lwKvW{d^Lvkwi^3)437EUbijmw}}15 zF$>g}hJowI!w#9j!lz0C{4f;>6V%{4sI-)0X{_n0J z`tPq~6MeUfqRRZ_$){gpaZM%Ne)1$ws(2B*^mjb*uM+SgCKJH`X;<53Z#z<-ar@!$ z$prfcqz>$5TQ#mRctL#3B09}-{RL5_SUSxzWHiuo%|SZEdp{MYS+0O22=j)-h6Xl) zFz)~zM{WS%=b2(_+(4@&S_m3%jYNLY)(E9H0cGE<*Bpj>VbMqa5*WLCA;wr*(6LF< z8+i$FP?G8zn(aSnPs$0UHCf@%-8*!0wjzlx(PcX3GM=^o$oU;F+iQF5Qi%lS1^lI9 z-i!#WX}-T4nMdRoWgg3T!+F7inz@lR`)R6ZuA~=}dm?#KluUX+GX(c{Aw5FUPl*`< zOwvEk32RE{IW_O-)_G1n=0D1$3F0{W{i^}e>x}2?o~OVc8vVCflXNs=3e81qJcq5W z6ScbU*6 zIWEpHFhz8ALj^&r!A(&EUC)#m9TMqwXOTjXavjU)(pe#gWfYq_w*(8=FX`iCY>FqX zkx3uZCyVIhmzk0tDnG%bxb|>B;0(?m+(bZUUB*QQhQ-wgv?aL?oqS@-^HEk~Xs}}( zA~gAEL>4Fud_WPSb^il;u6#%bYjjFPj81QF6AXMRHo;*2@qF7!{0y#&e18eu zLA;2I4~wVWFe~6cHM?P&ws&KnnPndBhQWNY+HWSV0C3)NHji@zB!f#q>$TUOO(ojW zYF=BqcPbQ|M%ouMn}dns{H0RFej5K?X9BqV_^Ie6haf#n((R|BLz47WlJvaV@mO_D zQy!4y!Z9Na^Xt+at~ZW?0gbV{QzQDo#p zPdO?KkW*HqYZS(kGKEf_984!q7SiVO#dXZ(`ANrIfSmGCx`Wy|o;zx%)!tPgCR^RxB*m8QZ%FyN+f zfMF4DSDq~{a_vV4LRbZjFLDL)J~-V`Y+DdZlS_#gN3oAf(DIkOg7y)8Ok}7PZKn#7 zh$j`GRbqc0*HmE~-Q>OZxMLN73{|i=RDu2Gu;17?Iyr+q4$)&eJtD!BE%9e^Z1CLZ z{sW)!X(UhB6VmdyVDvc>Kt-BRepAx7O94<4giV+{>sWXT4hAWZOcMB}2QOQy&Y5=O zf+-qu`k2VtkBZDoR{K{;e{2y&Qc@^Q+t;yHu+fv*HgrVKki&i~9Zwq9u3d!x>Os~f zE|m76_*s26cMXi_jTW<>R!xF5YSM(&q$aOPBm7m{is6vvH5qAbx|sE56xLGl=MeZKPc%X=?5c4pmO*dDTm+h8s%6{S6bx!-BCG^ ztWl1~j>>WBh(AHO9=U03G*!|I$jNF<(q>%4_29Z;-5uUIzDwh}f_Up5)`<6^ zFP8PjVMp--d0!0Pdf>s_5nw@*M!b&>iK_J{1*<6tH*0Rm;q$HVCi9YGr3+byQ zJ)isple8En>x6syI=oSNw+3Y!mT$X5IKW=@3YO9oO2NF5p#5@)&VX?SK^MqD|9Led zKVg~r(azMn2RW@ZWzETd9@Ox6c44ILJ?O|^Aanj&ocYUsKeFE}aCk^_kI-W^J^0NF zspPXCBA>n2LBYoFDblo-u8#|o^a(Q3#FMJaq)+IRrF5s&Ym(kfeu7C_u9eW?+PKei zIK8z=JJgQpOhfHo4v75Up|u@RKOudwq?eUzJ0OXT3F#7xqBlNgZ^Y-fu}4^Z{uF%V znuf#%)A3Pr20YkMKs&YyW6yL8o$7m(Kgm_!&SNXvxwpQNd*)&=+#YOckwDrk3H}%! z_5uI+_Kxcx_-1dsL?Q~^Zrl(GdqH8)uV;nh`F?soTPe<#0BwvS6)-~o&2m-PahU`B zmz4%aS9ugK2%{P3$I_>iM-Q1tgv`TAdGN9z6LG&9Wzv%jUcujlJX%nTT~BM?AMY3R zin7J>qzf|1i#}OOSH0|$^c2~#QIh?hLG75y%c?m*!`EI@KUg{u3dSrVyDGTT;-71pgcTe{7ZzsHu9TUCh^8dhr~dmJj0(W zc%!_;pX+#I93&d!NFF1wAK~K5T4D`sjfJ!t5-wWfAlVK^O5KQ(x^cu+H<+r@s;(Nm zB^l;GUKpyy*!|kJv<&-r{F<^EDb*`Vt6uoA9~K9hJo`fL(7__rnaY2^!a1AR9Ok zKkpIc_aH;DXENL%_LX#t`~;HX3CWmLRs%~MhZQewy`|>9 zLfhO$eA1VHNd{->zZ!K45e8?G_QMr+LE3Ziv;FX!tHJ5uUJXDaLP)WsKtL@z9CX9v zkSi|s$8Mp=xAp~T>~Wubhhy|uPcB61B#l@H&~fVdlN`kgWCL?_l45E+&^Fy6(6)hM zR5R!?gdXkap@|aNcIRgv`hW+<HdiT_^)vGSryG^b(}uCy!1Z5*(6~!KP|$C4vT2x#k*JSJRAEi zAWuP0i|vQ*=~x_&(=q^N%%^uIyCl%1bp^gC$mAQR5%%pH*`D?BNn)tib|n9f>ux5W~8oTRN_~s~DBh z*k?M};pjafNw&Z9GK{4GV;1=AxBzKqNKNpcy+U2luq8@-Jr}FlQq(-Yn8FO-UtJ}> z&OYBre6Q%^8{VB^W4Zh9{FOJS7OaUqr_b*O>@bLzq#TTyTCN7J&G|_ zzxe^Nx(duURR;Vs@%A_1cZb}J-vxE_DUtAoL)X$n)1f5uJ%@1r)jV|9Yy*jUk2zh*k+P_EiS4O(*JEg3u3|0e8Yj?+H(`jd+E@E0d{n-oOqn zPcf@dk^Qi#R3dOyma3b|<#|f^J({a-Dl6ximS2<~12?3jY$}xi8*eIeb1`h?GIj4C zA3lVi{qyct-ZtROv)*CYUg`-NKl6;pF6A>ce%}@3?ij0#AMBa6y8hOrTO9dKWIcY*UgpB@>m`)@o|7Xx{Qivi-FlIl-yU<6{4Vybn%@V$HP7$Y8Na8s zm;C-r!|!dLYJMBwdzbJHSg6KV`dcNwTC>&oZq7E3uQyCFT;{8d@Tsyn)zycJ!dKL4gW@sui`B8`1~2Z zdu=7Y78-oT4e&{OaAc##9(=P9?ZMWKj`o1adiG$;L9IRT0uZPCl=fg^W}4a_*vE@_ zOkE{9IXDisTgUZx8ZyfJPZC^*jMrx>hm23AtNnqsGffW}^Ot12A0F;JWSk$0=W(#{ z;+*Gc>ha=Lu3zwRC&bGNq5Ey??)8bL`^rjGa`BXT_g{6cTK%rfP^w?rbhY}enqgl3 zN--7;ZR6Pe_aOCqS{Zlu%zVa}0F%it2|w?StIjdNKV6M~ngRal=J5vr{&yX_V}ZXC z;eV=+-;BODo~qXOhtrh$?mgAO|D9%9-@Stv*zv8M^?jby_mvqWeR(|8-}nDpippAw z5YsNQBwN-|DrL={B_nGHWyxU1gecjPo$UKMmJr5_EksCT%QAz>zKp?)8MC~8KHuLz z^LWnd+}F8}$36F+Ij{42o-;rg+Uk0c%Gc`DgZ6U0pp~48)Ptt-<)!DDb(ho(2HGkf z;b>9?C``z1!69$ii<5-gyFPax^8CY{Q({?rGIInz?ldP;H|{%Y&+}bjtOZl+Fgy-$&jY1Q)g}Ni5INziAF!P5)Q-Hp)gEWN10y^dQ_u zJmp4Ks;>E^q&|4%Bhc2?8-LYg-BCq2eAbxSt;(`syIm;8smv1}5NX3^`Y!VvQn~Qz z+2j}RpODsX-+vswcKiOAD0fBLxMb|_h^~{J2^aboGuHRsy1>@E^lCi$bEWVX$i#Pf zBPmx?PofkgkQZ^t0&)19X8n&1yT5rS=1S+6+czi7FvFpI|}Ab$Eve4`QVJ2dJM# zn8~pI>q1P{B7oht|3U!Vyw^7*{6yRV@j)nw)sA}}!GfRo$-eIIC!8Y3Cp)Lby%F#g z`=hh?fpSIKq(WNoLk>}duby`F*1$$WsYiWC+>}2 zh_AAZm+_4R1ux@WE7yUs%MZjr7XntmwGtXyPcPZe<-F~?IfGq$84&U*K^~t|aa-`4 zXOSrAF67t@wsuBtGG~XX9Tv?&EgYxziOeS`Ct#%Jeaikf;Oh=Pn8a$>ztD)z6{#FM z$TIPOLvBx?&{j?kAu3Nd=sjbAHogU8e#cUVNN`HtMV~27J(!g*S<+NaubU?{E3y74 zN)m06`KZ1*#Z9n??ASgC^oJ&OUPz4s`rk4To(v#vYyBgTe-g%bp%QwM3GtBfr9_p1 zZyE)a3PE4XN`;XlUv^j5KkPzZDkS$!(?o*oJY#m#74RnF4?^Dr?Kid;9koD`<37a5 zjWh8tBUnUzETw}kvkI(NFxN~}>_2Hfo`^|1PrYCLxDE5V67aK}p~@L-Kwk3H0s;O6 zmz9_=Okn0IP%%8diZ3UZA&?^hW8f>8@2oi#3;#DluCGFvzWlOSBNH%|>5T<4Qgsas zZzL4iw36CtuiQ-7nB-ono41YA5PwvtaU*o&Cg0J$8fp-Q&$@ShUbP$OmQP)@75|$< z_X|kEDeDRAtE!ob=|>B@sHNVa81__WEPHk0eohPx;p?`Rx_A0 z92BA-mLg{?Q;SftOHH2M!k=fSyK(reo#9~NA2$LjvmJn_yNC~KdLC$ZnFpSSN>c0t zQD(dP?10bvX+YF_9*Dc`1u0m62ON}aLswGyXoxgc63OVN9QO{N6#?Y>4)HyR5x|BB zm?I5WAA1ih#v}w*=vI)KhqsH-VBsU@*4S;Z(H7{G4)9shRs3WxthV{WPv!2sVuBmB zHKQa?*hrho{AN#FK4Fva;;ZG*n=Z2|#Nn->IkLjf*@psmtsio7TUdSbFFFgUHt}eh zz33qVc?pm5fm`Tu8df3Hh{{^kjPKn^J1wmRaUY~e0T&8fW153t@;(Z%zRJ658jeh? z>QQaP92GV?EjimncCp>l^&XfRSPCOJGG7 zL3@W8c&vnw!~u;Nu7!k2NxVsxa`jkG_Jk#2GOZV5krBO3Szmf6Q|+;aN- z2eBtsM!{3K?`&ZnDmmYju=tZ3GE0?+upams7u@d`F z{@SATRUlmDf%Fp?E&+@&-_t$y(7Z4B7>+X9TxgzqXo6P{^?5--Ha=2m*mqS}g_;dV zgsUL0Cay0lQ50PEGL^LFP&RPa)}XjkFJf=n-3w&B!QEOl9@AhhvU-+6JrIt|{}qGl z>T_+ZTlsDijZxhlsa&RX0U3bG$8ggEpf5h!;IN0cmfBIdHn``9S*d~M0=?n&O93k& ztCa^qDw(V^IRBA})f9wqS7&Sz6p6Dcw@aurs91Q^Pu`PlR z7nw`O?PG_mCqBjKg!STygNpW{jkc69__@4^gGmIyx1UYd^`w_CF-Ilzf)ZAXQv-{Q z4F*GAarK7Ni~Uzbb-_A8LYj^jMzrpv&NzQ`I}lBH8(f)3f+{CMG;%aaI|vob(|V+h zcpunufY7V!5%h~Wb>x?9?=vckwqb;7?&QAjI=y=sC&k^nKUWZacLxan1~UOo>X&6v zp@ZA2fR^b2Li5NoB^b=G6OX>@l`-9j5pqAouWbye$gbvF799k)jsvQdUZk87vfMYN zDPXa6FOCUHVuBsY5bBt*RXj?x3~>wN|NlKw+~F3cf%8OgrEnWvr&z-%&?-irrGwr5 z7$mfefJ|olXyiuiUTDHYSqEHk8WW+PcA-oz-5`G2kEJ&Xw8#}vw*U*3HOsjaQj+-d zaZ=KixuHH|8~LW(1G8b3;A@!KBlA7y-h`+$GB+F@fYyvAM9}m*W{8C*ezkq1gS8cy zjO+~k$df%jzKykzB#dT{-{IZ%u<12f;PwiZXQn%M;1mf={u=t3a68h(t~TlksEic9 zTF|4u#;%0>EL%c))a(Ln|MWLN#ABu5>HV5|iJ{lva8amAXMW%*mV{b4$!N8zM;)0Y z;sbTVLi^BtJBQ~R36az8)2}10IiZFRt0IKZj^{DcCUJoioO-BA^$HS&+M$SBrEvQ^ zJyWeU6Df*T*N1Dlzp1r)uc9?M?8_z?Ij*;r*JQ(`E?GU%%j@y>q5mDP#@%M8?-5)Z zv5QywJsORjr{MLmfo*a`I6KsgxS6(1Y@hU$Ck@O|UlpMja0S1R|z~tb*Z6FU*G}PV^BCu$thC>$xD$yXOeah^GwYbml`X97rQ{gY(Bd7R zzXP>*OoddJ0o4(p>+^rRVj*>=yx6*3&f_w%16S&A-dfJkx9--PO7e8w{Wn#EV!*4e z2*x(oIAQ)at*Kx5H)1DJn*=kqea~FyqugR6t8N*)cHPm7IEB?zzrCv2cuE~_d zs`NgCZ&dKL4ngU#q0mHEFX@qJ$e*Pk*m#^9amK ziZ%)d)ZUzz?Thu~t8zEyK6zGVTEcE9v#3dL;;Vb1>rhcsiFHz?f|DT~ruOMxRe7jv zv7mu2H*Vmr|3*uG=xqJnRoxdCPV0XA_`z~bl2*?}^L;*e?(fxW)Py^$JCjkjGXC`B zb%V}$XG*5Z#!ANRswuccIS+WDc={*ELcPg~>Sio6c*~T{Q0AIfa+USy5vcJpXt-fz z)tjkJlqMIGQme>IH%Piv&L7>2-N!<{eH`hozDshEm`wXqF5>;tj?*(l2|Y@bdj6sO zg~w$6THEsT58kmdw7t76y#C?hSi$tZ28+30&vu^;o|Opwn#SlyEOna-I(SPsb}2h| zdBIo8t<{w{A2nL~&Tm+H@G81{WwJZ9D)9az|M7Jwd7X2CQ{)(@l#k=Z{_JuOx$SBd zwK-EB6)l5PfhPJ&vy>Ml3yu^xw7HJUHZxmXb5UL6Gu2F6hbTXt_zK2+(?&=9ZJ?8yBz zt_OJ-)H&TYmLNrlR{Mb8Xx&5yLBjsbiw;+0gKmW9BN9#JRlh1^*ZxSv$Os7=CI@0}p-y19^=m%t_mBScVK9BMuqF{!sQQ=*>D) z(X%o0ATH3j%pFAtRzM})!Cu2<%_sSyL?^$8O`=%`SK~s-pbv-RyH|CYSL%PusZ0Vj zKks7{S@`V(Ln?xUx2x=i2Y{>#115XE{nxwC1`vZX^MU3=7b@cNQShej0m$`q03m&f zvt=iDfSlqrI-+v+w@M%h_tJSDP_m>W;ML6KIG}vMLd8b54aR<0R z#)9auAE{8prK9Homno9q*dYS^JDZhS#o2)Kn}l(z>a@U>tOf}oOVl&Ok|87K zxAqY6FfN(F>yx(}IQ*!DCN`HqqW^YM$FwUQk{wz^8L4~v7l4zP5k?_>6|{g!=>%8E z+Y&(V=Xl-@)dE~mK1ZNfwEBDa+Y+=$AUdk|`^L%H%Wr3y!rMt}?imN8U`JqCPNDK+ zWZQ?=-S1Ks09-Y#SekT@Tl@nu@*jd-i51L26;1C2zx{9C7`uq1^2{Gu5Xcs#x`f#N zw#MS@kqKK~j&6OFN6vn%1vh;Avyce63+#~UQg0v5jaxG_#jPIbkusmw_BduNsePkR z@i}nYHN$pGh6|O@50-{l#U0pbUdOcsj6u`J72*PCwWFE=9d(?p2=KbsRAonx=`r=B z5b`|qA+uuYrwQictKl4>XPJ?q?nHsLq6}9ySI%coTbd>;73dAEdak;YmI`fepJRW; zi}a*t2jPb||BLf84}FrksCDLGdSuOpg9Q<51gr)-fJ!HE$MK85fHvd~AlQ~~+owA34Ljle)AqRUd9W8v48b>|Y}1OucHAOI*MLQCNt%yCaMd`7K(Kglw>h>&4tjE_+( zh3Ap3;s}`zgxMmo=m#cuXJq&oW(>1kt#sHtue=T!oQOZvb+%&KuBEb03{Q+>jxU18 z7G7PD^SM^3a|>M6t#xnXUcjY#Pq6__zj7UC)pnuW=z-q1OG>kxsmCWHhnz4MW&l_D zl7PdR5y2tvD%X!oBCSGwp5Nsuq6v8pVUxTmK_6Rasq z_3^!q-Hodlpvm0Q@by%&cp62aS^AESDkD<&YtyAKEf>RJ#U zG!|nufxLH`sSY2x?$TFp*g7kB*N>*`+dGV{8lJ_MFobz~GuGtrj|pg)h>pFm{TvPz4o7}->f2#ng60#{ytTsxhF1{fn`M1*ZDpht{XQ#v0fW_ zA%m!XgD}Nk$knmq6(4*y6#80;`o_>|8Ky*~-qEuh8HXJ~Xx5z)>+DK-Cvqj?Oy!nU zgmK!oD-+sFbd-XtxxU#k-tAI2MtDYPKbP4^nj5Tqp6p(nBCAK+^$;r7cgM==)dXHx zu3yQ1p1kHO_i!(o+wZayLYjL=BwWnSh=A$^tKS_{9d|?Bo^xT{tjwrSdEZBeBn8^Ns5T}`W*`8 z5=j8@{|$JI9d-#qk!R?*CtCBco`J;;5y{P4L z%wOTP51|F&+iVVdgJtxUrt8VEtIzG`z!>{3#j6EXw^=luBZhz?Y_<7Jw}5J&{99+O z5k1!5Wlk`^bpE$YP+ZI{+UP=n5*QVewW7<_n?NYN2CjHX9d%*fCEWXF%Q#8mr!*lP z5=zDcBgf}NGq57yj$6`~Cl^CcNWYdEyxSk~O1{j&;56&6)H{;w$G_#nWL< z#G^z^wUXyu+OeRiJg|bfW=qn-Ew6geU*~$4<6ko4s&5=f!{$_a#ASrd-hO>Qam=Mp zr>MYtv3B}d4D|2Ap2+*5s7qj5pzh#vjDfjZ)o7rmW8@sJkHt>Nltfo0S`(x=qw0)> zA-h0o1SxW1uMs|Eoovl&2~XauCKM;ZyG0zjqR7#fi7X1C;T^!qrc9v{2wKIBi5BM2gyfi zkM{I0_){F3Zye>ZjNvoARIxyVEmRe4;4^;f2Sb-<7Kt4fP!$_yT@e@POzES?LSI#O zpEhJZnzY|)zB}bpxCcI6sj5_2_Qw<{TeaO4a!$#sypXe-2GS)@{`UcqkvdL0xlL$? zJdO(tI&&Sj6*&gwJTD&?xXFJPSPWz;`D&tX$63McO?cT+SzNbB;!&?FNbrx{3`oaH93&LD(JR>fl(O&(f6U|yDk`I;D za&7S8TZG#DPoaFvRdnI?BYXVi^de2yHPnsHDmv{e5KDzlL!LrZ8&QgBdKYG<8)q#Q_;y(K$TeF7j&s0tclVLXK2_p`GcdnSq5>lb8uP>ro+^ zAL?s)<3%;gNQjk+5`wlzM0i0;AK|ITzj8}t6K zcTo#`B&T@>asMLerPiR_^v9>u0iQ zN`||hwC4V@hx=tSRzq?JhY_M9ds10Fb}`eyC~SEVcxI3l`=)Llc!fPUm_Zz#rAK^o z^FUSJAxhFQM<8)0Llq^^rvo%w`~~gDLM54DfxM0FGc>zXlpZsssZ%3{5n>8qVP1PN zmfv?b&(3_*s$g|!GG&P6QPAy-vx{@wNBZ#GRU_z9`|l)Fb28FZ^Is4`3 z22+q!VvPLPGXy&zmOsibR=WQ>r&l9j``v$KW@_dvEx!0CJUJF_ z<2ExJ8BM_Xi80le@(>x(-enFeZ64>PUmKT)yAUfZcJ?tP7QgQ#Aj#1im?bj$GG}P^fkGuLWpshWNa&p+>9q1>PHHqTt>6ycj<7TGtDIIIHA^ zFTjLR52WBLMFdVMx@FYjJdfQ_${D2@z;mqKhhK#2iRlle7={JgX2^Tk)-t$U@ ztUU^;POI=n26{`*c*dJIp7ut&w6@1HQ}dY~Eog8(gPFFJ@C{wQ&8^`rsUG2|GOnTa z*`rmVU+F_wHl=+U^mhz51)@nOl)#60Z_so5>fmQo+gOj|D1Vy(Wp+Bk%nR`1pa3O7 z@JucWpbm$xPi?!bVH-p};D?eA%Z=&YWkHHkKTujjP7ZkMl8I6rQFz1b=d1{P9VbNo zsoq?ub)@jnzuN09*?k!AVc+g)wvO#XRFc;$vW}FFJcGT7Mr$p3)9d%$hXNY4$f*3W z(uK)!jS6TtN=wGUfhc3SVOICr39k0VtkC#PU74}1pW3=WVnd~|!u0C8ndOS%H+1p# zv?j~)?beT)$~Fr7q+#HelTbJlQl#qB6`F!?3dC|#8r1uA0wz3#E*F6y7L`4flPN(2b>s2e`$KyZmHaQ0$%d=dw>(1UzI(Ku z3X*m0K-lHkBmAyNZ;orlO&>pigTfi4c^ z@DBJQ0-QJ^!5t~(pst9_`z-LX{9|gHzq9JH9@;@Cuc+2t*7r17Xs-Q^|L)rOdV|uI z$^j>*38h2@9YQ?1XBh?V-5Sg4AA#XFnTX_DS4osMhg(i2>wZ`1jI-MbRe^@pa=Fi+ zuItBpdMHnz9c&=dc!f~sVawi?9%kb8%u*(P4%D*qHB)JeWm8eH)CS`sW~`#bx$;t}_1 zPJ?eT3q1bOHplD=YsXk=v1`TPYCJ9MvX+Wj%oLg?%c(uItMT#cG?Rr&thG#}lqzlC zI0an1r1i%3^W5!A2|Q}EQf?{L&dv8e&{vJI)jjoJ#OHT?(e zGl==r~&eZpk665%pFUpX|E_L5+Ny`SRP8UJvOkZ;s)PF$KN9 z$qKJI)N!swOL>LvtdojQcFTGkSq+I?q#+D~94BlbY14d({`x&k|AiacFl!MqgXb0y(QFL8Zw4?T+%FJ~|2H zfoh1CBGqUW^v)25FtaCuNTY9XMZ$CH>~N2j}tydg~|b$jG_BCL)Xs#S5QEe2w> z`@EgCMGens_c?2CDVm*YU;jQ15~it$$=rPA!;VrXFrensq|Cb(ufEz_xOyLp+IIlfyo_5CBT#Fw>9 zoHC5X00y;t&9#p*?5m42iNO!3Juso;TuDj%&mzr_x*=Z`{P*Te?kfCb699?*VJP$I zv17*@@_at?^3wd}rS!}&)&~PVaSas(qoW?L8qiwM%|mxNyUPUYB>APLy^lr+jb`PC z3OONLch>P=&-IZmCO+@;6PObjc{l+L+fyC{N|xta*!9k%+91{8gS_dMovSjjBxc{5 z+(ITP)t0gu81q|~`v-Y%(XC+3`#&BWa-!K2BT3$RQ=e(;8LCk2ql$P@`{BpkjhSQR zK6v!cJfVf(**iH+-@k!pzwv>r9-Dk?km305vt_j?-T;ZCuP{sAgm}Ar$9$ZKp4y8! zCursNea}UtS15bO304m7<~7)00wR6f&3elC-I*cnbdJDhHj2r7S+=DWXN z0+D{Uf8ze8IYIK_$?hfZ5Ws{Dn<_Z~5eY(>Dj`T|`Q0{^ADD$r%V1?evQxAwHqFK{)1JSIynaeDYi;D8}4`8XX{80TWEbS!z?=>a# z&yW;q>Wy+zz^tbTWS=(*naqK|9w+Z*ZxK1t&T{NwQ|hq@N#+mSveb#4brNwLGvXj^ zA@|`-dyCn1x!Gq4|Jr9d07FwcCYpog^ChSj6AsXewWiLbG)Nkw-xk3N?g1FvIe>U) z6$s3Vx~qKV5Rm)ksk>?D`{;V}zo4*B`xoX?yR;onVVlB>1^Nqcq5W@{W|Fb%3KFMfsn?%119A^aW)QF4-aKsGQ6tOF| z7wp|{{DblMJdybL1^8aIm`9OHpvcwgtDmDD7dcUG7j1xz2ao5$+}SWfELc!f1FXb@ zH5*4e@57GBUoa}ZJ>zAi^DFzr1F;wJe+MtIv`p18j(AMArECnfd)hCPszXa!%^gx* zxq!HI$MKCiYsaM}?GDB?G%JjWuW15oc{YK!Sm}5p4m$Y0JS(KTnzD$}IHGcDZUzF92qXvDj;Eh zB%V<)mZirrxA6g!KADBTpfI4jzB=@nv;CAz((*8zN97#DL1us__1oWa*C+de*Yz3P zt;AZHWozGebw&NZrL9fd6`g*X5y%DycC>{zNgpnDJqrz&dlCgJZ`T=03(ZP_)oniA zEADm0!blqZ)Ls8t{X8?j-3v}UvSca2j%RzwK^FLVsQK-Ygx#5O#%leOp9yUobC&Zr zu#EmUA4!CXOG28X3w^hW&oN#jF>|PU&q<-+TlASSo^@7J???%K=8dj4i@lLq4cEI~ zTV%`JLX2T{=0qVr76)>M%2M<+BhfLYK02<1o>tZ!Yb8<(uTfK4TB&&HB!7p|Q;D1ud|4C5S?T4xja2`w#*h^f4i9)!Ro0{#H}M zb&!wVJ&8q9@DOm1Y0-CE=$swCWldLU9u1acLy!wac5J~JoUmB7;nh;U@0%O$y&LKR z_u0KB4&#JZc^r=S&SvsVEv}r9y)XXmRQmAQu8y0GkwG^B1vcq7C$9C*s2r;1CL2}VYs+{4k2Z5m+b+apFhQ@&qGP)o?7JjE-bi2qUe zy;BLJj^c_Am&_d{-G&m6L!UFf{_4x92W8rfNw9ANh0gf#)|;Gzrd1pR<3!{;{| zB)f$AqUFOjF7?TWXkUAB6jkW2i@BDbO%HHPz-_+ZA~{{DajwNdh9NlBq72N}V35ZK zg7TTbxSsfYMUL+~j*L`5w2&-TXoCQVT)A+iF|-H^4pk<%^R8T*9m25#1_^z9$PDswe=(a@*r?r_V@ zz&}RvICFXr=}+=W-#<;L2rlJmL8C!O%%|8%P2-844XFqDS~!EZv6E+n>rzgB8+v`q zKCtMiAW2Py{D$h=sAb8xSDp};T1h6cPGb)*kU0sorUWwcL*=5wBW9rmAzWTNZQwVwZ;Xcry-q8)#AA9wHE@dugj zObues-Q$0dc*XFz?0ftBNwbJR*FfUj($--6DsgXRPgPlkIJXURb9HkaoDtf9>bs&J z#>zwbKYY6ES*-J80@8ni;vC1yUj!Wwas|<@^qxnA=b-yZ_{HqQmWw`9B9b`S+(D9{ z%yFFAaUzND9~2}qPHJst9fik_SU{u(0I5y{5cxA-C35m7lX~+fH#W&FOy30Zqf#U?>F5y6{x5m9|{`ERF}srOn;r99FPyRD+cYUhPT+swG4=!pM2)S zQqM(~=Oo}2L!29|jil81{u;H#d;YtU{@qk6d{<x; zsk)4X_IRjn*9{hZ*Y~`3!Yg&HcPk)zUY4BWf4-j*d?viD$n$-mIB18Nx)LZ!v7G?3 z6C!llz8=_Kq2YpzxH&2Z7-!`$8sRjaj~Y zkxr=E@xE-*{hWL5h}%EeWixFYZ-IaCr;5DTbz*P4*YNK={T0K;F9pU34z2TN1S1k* zj8@k=7HPxfN>)N!MLYzA=@b-xiTq|rx)I*`rPP%#dTWZ>__x_&jb2B9ciz$ISNZnj z+K&9j>1z4Pt?Pe`hEEI8JhvuKJqXINzSP|49#hmr`FpITI>5FFKf$`OTQ&XTg=g4l zThEPRG(=Yva$zw<4HEA|xPO$kDkfCidr3isXEyil zu=?*14}FSV5X@E$B7$%Fl`>clz~)Fpuj5V@Z>!gkyy7>?Wwv-8+-|vl`>=Q87xyFC z#0GR|&KUQd<^G{dp*f)nwP$(^ac||>Cr%vx^_vq$wlx4D@fSC7EvB^+u7jOMIhCTX zOqJPYB=z7mUe5M4MHu}N-OY&kb?H=2jJ{t{r(9r@2DLh?5KMh8F&`CpwiC(sqjy-> zj-g>ifIT?aY}}G=Ih{L{TJal^Y8MF}o~Z7MRz1En7Qeo+Hp6-|XkUED;7_F3+?-tD zYA8O01*F>Ly1A}RuJDBWTX5!&@SQ)@U>NA8j;HOUb!pN>qNR1hieFy#}p)i$G zXwa1t=!w%XRb#G5BzW;?CE|%&8Ky9%TR+J{`Z(J5I3BWf0?j%N`@!|W=fA}n1><<1 zDQ-#h6YLUIWaxJSQMq$vtwTjS3^|c>f59_`Iy{s@$Wnd&i5TPV3!5w5=nMQXA5xy( zF=-iwWD@Q#I8kV@_>1^ucT*VsNXH{%Y@AQm^Khig`!21O)36B8`O~1i+#5WwK5Q|y z#wdkgn_MFb`J)+*Ot2nD*!XcpCeTJo8kVTrMk$MX;~fWc=1l6g08C(};&6n__dju( zeS_j+?nQj1WgOLQJb}m-hww6I4lZy;cJ(m^r!quHBT@+nGsQ*xIVM&74|URJ9P@7$ zIG{~46ob%5L_kGI%#)-QPZut2;a(Fd(`~!(-I3SigdI;Z4`LXPegw)7Nt%Tuuz?cLgp)d_B?!v0QCdWN(qMVc z(`6rm(TJA}pBfR+BwqS|!VtrwTYO>28=gIYGn1NwrQ!{gw8YUSH(|dpv5hZ}t_Cr3 z%Z}z;?@QAqAj~X)FG*(q6G|H<5kf)=&Ov}vzOeILVIxL;7(;WWKB;TLiRCiltcrdi zP(;0P{U=E&GY^#8854`hDmzTGnfyPi_$4VWLcVCQ;wC>HRdJJo_+fHNmSnlDhX0eU zl#7sjP)AbiM+AXP*tJ4nhPjve zCKt^l(KUrj)KBM+LC%B|Csiz%YYl_{+f!>+PkdpZ*wjUR#)Ej|@=GR_aS|OuwqUwn zH-up>YyDu!HANV}xu$T5yy$K_syHk9SdDc@vHp)F-2vtsg7LS7Ox4+&Y?GBY!!|6y zc<=4xOVFOvl&{B`4;@6g_K|%jLJz++|A%bllU6X{)q0V9j*VWih`_a30KDQib>nT%=(! z1#1wtm-qf5wLRX~73ChEDQVzQyF4uFzZxETbM8{pN7#*Nt(M2%w|R+v_ z6z<95_oDweAi(zGo0Hepc_{)h0*x@cku#fsiNWwM%%v>Ep8%ExYL+E_0>Rr-&aI{mQ@pAsv$QS(zF=VQr*`{nI3u@YR~)gzvDqCImBmSct`$) z`%6Kp*{to=*Dd`Lz4{Ne5Z~?oZ4m-uW-G6q3CfsMWIkv5dDGOD815p}5AO4z%Y9%2 zcHktFs&B#wXe0q^f}tvuL4VM7x6tX=>ADY};SUp=S z*5WYf$<65(rbFAbXR=>kbnkmkNna*8Krtryy2Ps zOGY_^dmfI6K>OCCkCp9t2(nb2NPJX3!P*w~-XgNL&1+zY0}LF5JrkF{LaH+t+f#JJ z<>$AKFIZ&810IiaZxbYL!5?!7VZeKJD&OVMugKfBM%X)7WbTyl(om@r z3T4W)vFo#7^B&Tq-FLt@&mZTATyzU~9;yt>+YaJN*gfuFc-&zn+FY239r*(u5$A|P<4|RRCF7v7{uxmn=xPeP2G!RF{4eZFQZN51Df?y8c)BF&cuDQ9 zs>+GM@*7c9E8&Ec^FQ;pRNa*0D&F~i&wX#CGaL~t{Q6q|vE3*2TSpyF58|hxJ##GD zfR%ter~b6`!Wvs~6z7TXE&;*uR8u{T|wBY)m$z&>Bxtz;H`7Ulb* zgPyZeaURh-z8f!9^V#i)8;!W}d9Zv0#D!4w3hx44hjBFB4GwPr7yRowEUWaxYIZ)_Y2RVr&loqC3pK7sh@1 zk{fsd+VtaA$T_hjiz~5i&1ddk<9;sEccH>Co$*%ncl>J`Yv(Ut!ubAhOy$SH;+LAi zOLWTOSf8L-@L+X`b*%p@lD7|Ss^D?#cHNKT0`g4|DK*Vky(KIMC}}>=c4O50SFX(Z z^}ZPrToQ+F{|6n!AVqzA&xaq}KXKi@&)VrBui#O8*PWn~Ss?@M{U6$k?VbINTVU&y z3F5unu0Z2Qu;Cd`_dH!KSGFiY9X$C8;!uv}Z_csujXBrZwEepcsn5H`fOpBcOw zr9rxWtmUmLnK_h=V94zV>Yx$|mY|b?X^TT2Qwedz8W3?%k%d|9ur;8uuvNe@A8?QD z19oD~K@l_|Ac#!gb5yH z+WBJ?<{cxF?q7u2ow=?`zxEnEtCkp6W7gP1$VR~^(6;t=GzWQh6Ry9)^<;qDnj8yw zwAYky?5(uvk>QvIJG^J>`ea~0D+>q@M#}>s*64-UqlQ4X5pRWm^LM>$8}@|-JujjT zyqs76{ZIwH;}GuCiaDE0sAYKU2ByHd9=<5n zvE@49lG+NUQHg#`=#=Kplgy#KqG9k})gLErXj zL482qYV7;hyhNc+w6$)@H{LKwYAxcS;6EB9`4Q_N-Ww+1Im$p5 z1>YHaJBfh+#B0P?p7_+aO`6&Nx`ZiBtYOQn8X)a6pM5aAw4Fs%w)f#dsTUrZ#y^>m z&0j2vv=R$fDfkY8nOTJ+^%8008Lr0;37kH;*b+|wE=X{+q{QQ)X|u=KTUFce{u0ErS)=2 zFjVA~COn1TO+5$kcX@)^$Ahpk>&9pMNQ?kOA~b~hoI{f48tsFY9zq452>3ANmPHkm z?oV}}bU&F@a5=aAOsh_Mf)Jb9&l#onLvJ^Mxn0nZia7CR-^SIxw#QeUK}s8a8-_c> zdtV4l?*tU?gK+{KxV_t8S-tcO)HvEJGEf(#`qhjxoE*XjTOz)9 zOIA^P=itL^KU89~jSC-NL1^+XGG4c+%`_)gDBQ5)t$W4BKYrgp_ZZ1ILMMBG;L(nm zARx{kRvBuMB_~$icC^}e`oo1v@IEpYZYYk4`H9x?jIn5kcBhfz^(xH;;ib56mvw1O z-8~D@20EJ zfb?%$e<1fjE+IzCRO=-9AFO(M|rTV_6*$j_z%NLZ~Q(oPB=KuXsU0_qAh%b?t!^{R!DrCychEb-(5l@QLj4g87(lx57ti$Pl?7cR} zU0Ui|W}ngDKXFkt)k$sa@*ljj_Wa5q-MFPr(Bwj8wDurx>WD=D4(&3!aOfZPhH~0s z7TzEp3HM`C)dXNJ$F;yG&?TN+ACSiv+s4h~eJm6t(PD;6R1Otv0+OrqpjRLs`TiIL zsTA4W#}QtvxWoKy{)w1y!xuJDa!3lePQ}50k;s#1}*HIe+Uy39V7(}kWwZ)0>9UV!bXqdH|^q)WykP2ihmM_n&CbhI`PQw$M7v9-$?HN6v9r9PCwz=O?0t!IO4(ecBUF55;ya}oOl5})j}Nl)Eot0e1$*G;tBjnh5^T76dl@{}O`94p2fgLU4oF8#=~ zfLsN<@01})h*?kO@Qh$)}3Ov07Y z!P_5)(^nKPHkDkxR(-vo zm8kNMsy9foK#lu`{Is*Ob1kpV?uNW=TpW>8ezK}}EIbreO($~|TcUeWwr#~qAs9SfevQE-q zPBB;GRtyyGGX2cZ@;C8PWW_^-W)Q$Px(bl}2UW`Dwg8pyFsF0bSK*1ayIvDdF5|0b z?xB^`RR`0)kbh1hO!Al1#h2O+lv-dPK0IDhryT*&536ZD;42X1MOi%QG;P9qH5E1z z__V)yS^W}TN9^m8{?EgIZSG;RwEqX2KxDrXDD`Oq!sJZnIeXXD@PDt#{a;-T|5sPH ze8c-w|Ci0>8=_bkI5NL*{;#0{{a+mo|5sP;|LSP?zdE|{r3|3{&&KgJq?_lt|C{HQ z{VZ#*u%Efj(Eqh}wjWB?XFqZCblcAd1}FQeQd`6S)t39eS{nYZwr=@`$5Q`yjm!4~ zh5e+@Eu8(Z;{u!2(#U^m$@3o#e7kDt#+NdX=08_CzWxgP`D%_^_R~8;VLw0P{CK+v zXZxXKefASFN4Nd7FgV%I`5JQh&Z;Su@0uEN`Sz%(TfX6gh{X${@@QU()zt^Vft+9>Sjqgig*PnEU``>AjZ?59{;XZxXK zefD!_W`XwO?(@uZ6%onx;ogW~g`h)(phI2apXxYwV!8}o_|^000#AyA~Mx-VfcgUQk;peI)0Y#{LAXPaVC94aNfI=%g?{8u7FsH zLezi0=Szt1NNqX339m}=&3i?TuidNq@eL*TN;~kqq`=pBx*T6(1nV!iTEY8NXBUB< za*=$)K0*mb_Dr_zlIH7FPfR17W2H;|BU$~^TCu*@hqQ9_6KG{Lr?tbjC|R^M_j$gy z;wy=(Z`tiGYjyhxA09amNH^U=K8tLv2{+ks_I&%-`TPO>brkK3X|(?xaIAj*Q&ZkC zHw8&O;J%mS9`KVO-5xOYW1`R&7f_*flb$8f{Y1o47t&EeStHyGoM-AnXi=U^8*ChAy}?YkC&wSELTmg&qLL8>oaLM z0XpkXq0bK#{%6;eLitzr{?3o8%kfpKCdJnvP>%095N1wFs2r>snQguUH}Q#S?tLo)P$z=X*a(D-^z=i0`XcG~$0%dHk=U5&x^|$Cp6k z|7n45s51T+4&QLZcO*z7{#TL5f0IW1uc9AcB8~qJe8ZLTe{!Ml#Us9(FU#?*G)eJo zuPnzm$fO_NNP_S6QvzSS0$-0wg~FGJ_)2Qv%d9NLce0Wk-;~Pw@r@$*-uXk|OH||0>GkUj>c$S3y6%Pig%7P2lUIjDHggg^$^1 zdR2}1S3w^C0yN@ZA@Gf%@$ZDHeLkB|D16L5zpA1U{{rOkue?V53(${mERBD^s@i9z z!r^1~dBmg<|H{kbUpbBVS6)B9aWww@s%oE&leF;tg7~6oeK9be(0JhFVp#{*VJ=+H zDW?Ey7GUWECtsG84@P>G(*|qiV50=sV&e(eSB~STB1Gkx*og52aao4gU463t_`H%_ zpPOHl>T`ctxjsj~s9&E+1Y*l$s{L{BI4ylj_dnofq$&zN^UeR4y(gXjFC!lpE-tGL zFOWR1H|{dtVaARC69k4HR4|>{rJ*o{QF7ZYoLsOBMXJ^ zEyQQiz<0c)6yMbna(s(Q>c?lH^S=iLzPA+ktcm|-{+FEr(V)0I<+@(to^<}Vm^{vJ zEujrFjKg%y|4x}g=YJ14=6{uEKzx?q&iwCggHt|3pZDXNj{#_h;&R1!l#nJguQ8vYFlS1ZH&yOn33I2dF+OCdXH;xD;Q5qH=uKi|NLfJe7`r z_i=nh6xrIJBQ)@d_2_BAiuLF!aRylb3U*$Preuo7;`VxU%!mTlqraEQ*N*ZnSyV3H z%%W2Ho-87l@06nY<(p3DzkcMK*C}rb5q~nAh&V{+c!sTa)iKKb-6cP%zsoHm7t1<7 z{r+wmo&U;GtamBqzlIgcpR@J#4yEMyJmmPwY2Z6lL_faiwEzF0y1u?Eu2A^c`uayD z<@l-YFME5~=;S3kZPwEt(SuCJf{SPP%K`$19_0oHZdxuLHVXGg`)T=#=`>c{CZ zli)m*;kqBhu{e8cXs-5t5I4?eTI3~<%^iKDvAM68+~t(_(H)y7&LU7Re6Jpxi%^)V z&sXFzd{jWuY_90M*?y4L5@WWO!B*i_RgnZ;!-K|TI1(bgvZrx-t+2HCpgQ!w*TT}M zY{`FA`Dw-E%5UN=mB`!0c%%= zE*<~vQTQuI7p^t9Q21E9Iafqu{O2Jb{~0vKe;)er&7C`Pg+%3t{_{M=ACr{a!#q_A~ixv;8uVBxLCZ=Afo0g?DAbMhUJH0o;E%lEz` zpH;S|gd=#*fhs=*+w)ByxxQE0@5=POJ+GKl--GDS^yxckK3)I)PBs4ai2XPATv7vH zW}Xz^$>(x>Q}XoVTR`*QZ&mZBPY1ZSe&KjO@L)g5YfS?Gac~{x!u4;@@5SjYN>-$DZR!=0|{7jwk=g{8lI{i2}f{}c%G?SKF0u536{MDa7%++x>1 z+6YyKGZPjOgvmRcp8s<^LbmQhjrn~yo=@%mRIZLvN{r6g!pl$P82@;tjZr0An6Q{& zT)thow{5QD{KtOk`IF=Pn+l5aZ{FC5{;z`b`8P-gEbgCw(@*pK8?hfXFF>&$wP-l{ z{{ZLxsFX~br>!TdY)7rk#7i!hw>$Qu2AkP_)L`X))NlIcs_sWEXg+Zl4 zm(cZ(t&+osvOiGFM-ao=T#hFW^nF1KD9vXn&>kD&1HhQpQZhZf%a4U=VzY*vziHxN z(3Dp}@vDO((B>QeKbFR?a*yOMKv|93R>e^0;uS5y6erJ?^GGW}mhyk@MB{4$p6KN|F(f%;!> ztwl(2DyK|d%#~-?bM8um^Ow1DFWl>{?%?eC8A1Qb2B%XdXW@(QNpRj^0hPDzP9$K+ zpKocM=fjpnp5B(5>Bc)!lv%grC`aDWjWXqPg0lH~rzH``W03vd%T+(m=X+;-fGd#D z1kiL-MGZ!e-j?FKd`m8t`L}iB3;%-Pdw(5YQVUc(!)l3^ulIbfp}%pczeXC2-nu2l z=XFyqmL0cr<4ajX@QweH;~S??-k05E_(XotyM!V?7~~K6LAw&p`2mvkjgRVf(|0~7 z$aST&{hY~>3u@X;seC`XAy-Sco4Vy2zLvRR4ED31ygYSUHHKiuj6IU4={hP?k@ z*XaK@bmL3;lJ@^Kvi{#i6`!!5D#aA`b0P@rr&uv(`$4ik`?=LwpZz$=_bZg|qU&<` zcFd8=w{NywzU6at%Xh*$y8iPymoMc_F-POuS%-h6EGYWNcQ!erL$6EmC1=aU^44|T z_`=r{eD>9jEg6o^QR7{?f7Lk8j~#b+)+SE^re{mxt=5oAbhd7I6E_fefvfoxo6B)` zZQm(i{wdE_(Lc7uLjSn#>)bz(tgn9@eY=4E;ds9RdmmApl5C!d%9X$0;0fXlgB+bSaGF*WODl?k#M7L7IWMwd zmNEG!dSm*KUIub!FGGJKkDBy9=YhwC9QnYb%r)u2W37fq|MRN;fyYK7l+`P>1|F}D zhb;8_PDC`<^OSP}F7la-@(H2ie{W`g!--9vss=XMmD9STO#+#=8rt8fOEC5IqzIV) z0_b1S^shkM0A{?w&c;h;E<&jBt|Ff)wihV3JzZunWcswicxecmJTNC8_5d~h>ZC@h zZ#Ixr)u-{gT%WD3NcDM2!&R2JqFnV=0E<@ZMGhp>HNpi{AN4XG5;|d=Rev@=RXwodfi^d zVXtv{V6P`RjoB-bb=&Jmx9oLhyZ_K$>tB%DtL>uHUZ0xiZ{8zVv|tcj)%S!%GhHV`?~CLiUjP0cIvgzfwVX~K5@Z+XJD z=7R2o&2uY}#K(&yvo^US!BD50i71|G`PUSKu-8V8~3b=foN^K5wsRZzM;O5;Ff=(3Ilyj z(bAW#31w-dLr*%!s|JH79q?Q~D|g$={*=mp>lwNH2mGm9{;A&(`M);balW^wa!A*; zwPd{Nw!ic~Blnj(&r1E}k<)U2IpM5+f4QBYjF_kCF9(Hd_{+Nnd3*<1@c2&qqt#0p z;KONv4~GCh@`60TuRkLV@L?C^mJ)wPe}LaXgwbTKR)F6-9Qs|iRzxKC@>J&gCmDpl zEcTfB#$lxAz1{(OUhX4Cdk^~`lHKZm3XeIe0FU_@`B-gRS`sFExq3_&es3VZfyV8o z&h@Jqk_c-7|wKH=Gtw4cl0sXeyRM72-y@m@&(ib zk)mH|D*bumo`TZ+%@)(sCslAb_!NFC^V-ZKnSL$SC?>fNkvuxGEf&L~Am7 zpr}}LFoLzdO9ap=K+)b=AdevA_5pO;b}H<=z}m|OiOT&L5An1?#zcVaEvE*PnQoxw z_;^xdAgMW6@DSgNv`t9w65n<(p%oLlcM#h*-kCN+H;E?GuBk?8o zqf7K4nu*O~UkvbtbhhQ>ljcH%y$PhCi(;;qX6M1BL{iv_Hz#UrqrP6A7;c9Bt6+EB zbgDD=#ogWOUZmT+IK?S2!k$!SHOFjgo8{VbzEG>bpGy6074;{N3Gy?<*LJj1vLOm3 zfCwd_*nSer4A2<;%fqSJ!~Bm;wqV-+q{8BRf&9w$rbPqa!KVKOK4_;-Xd&>Ko67Jd zsiD!-#W;AiXn+lwtnFB_u$%2<7e|Ot^z!;SNI39W3nS=$%-p z2UO~)-d2wC_kjw3X~>C$fB*gW`VfY~DlqzP#kNO1IXyPa0=PvHle?HRo8F{=?+@{hr^ zQ)k-Z8WS#iID6PgD}`+(IR)izKk(M@&e(S&Er%kKpU{CjVGY{7ZniuzC)*A2tpq9C zY^`Xv)*!-8APBpYdItK@FO`hjyZalr5A-LIJfRe2so|Y5UlDl)cu=VY7_uxya=vY0 z@yJ=}hP=A{xAJQDkGt{;YgC}Ty8S=PD^*2a<(2Y!kICzYg5^b0(8?!VgjMpjyAolo zaT3;#wlWQguzKek&{9$P(Z>)#UOxbD4Udhj4U%a<2@)A$dBAX!{)Gcik{}JCDU?TcBu#fOze$9Vm*;99 z&hfS(8M_Rtj^miJ?+@XFn^A!cb3N682TT{rA>9O<2cTk@|y?UXuN*IHY!$AIYIx1{t(7^a4FqX=EGu+ zp$_F7fSZH82>Kj>sQC2~BF+?^QCMGN!`t&oYo`#ndC4vwq9~kjhs9NUa2Yvw=f` zOVBiZORKfUgngSod288(eIpO$q*?}gQv&|!XRTowSb}`NNpG+W^fw=95dh$=gp~s= zg5huE)MoI2_X}}yR-DD;|gwe9C)FGBe zOYH@&+-xYtLol z#m;CSW@;Zxf>r>UB|&Rhxe1V(3^p#pDrhY)ptabpak^cI7A~d3pr7b^nGxnw{Vb<4 za{|(O2DPl)9VEH zp{8Cti1`FM`XxRg04FbU);$2B2csvj5|5D`gBp5@az9Ju{-7R_`}BO>-9Udue2{6w zRW_6Ik;7CMa9S6onLakex3C5~nP{vxCE%Za)?iC)3Gy9HG?tiX7&FmWVxnPSqV(y3 zUBoA^A)o0k{FtioW@{5x>O2BkNlq(^tN@vIcyFl9E5}AY$ME-;t|)%LXaLZTTyg$A zkm>I|Tz>Dc$Mo=^Q|87kh*9<~Nxn|F0jeREK~;nHdCGuxc@Z0qy~6G9m6BkWJ<0<; zO3-~va=XM!bAmG9r^AT$S`dZ)ZuTI7aA1J>K!!imO$X~W?of3{@o{_@hP_rV;NzYC zib<=~wJ=v;y6`t|a0Ygej)#DLK+uN?cZ!!---2r$p^_2AiM1kZwI_aK8}j zTn|uE5+K-sNIY!xD)gNi2dS-$qqD37-e){hU3 zg2!6Is)s4PC9G4XU|UdGdhKS=H3)*8KTHj%JwIg>uGbZO0p?B4; zXx#phA@hoV(HwfCJuBaRyPfXyE1F}r4ifE|8|E34;hh@kL*6vdTZ-lkJWJiYb&$75 zj^$kDzLEpc%@6W6C-3)W+~?!jT*MuoE4j(@4c~%z&hk~|+0TV%KP{d|`MSe%dtdi> zu3R9`_kC1(F5$v+2`!%2`nbdMr#|lS9O+XK&o8UxC01_zTc7U(Yv`VMdIVCbbtlG#K>BwzQBYzKjRXfCuKB8n{wU>;AWG^`jF{&)IQe{Ea*DhQ)2_C=G}=iimbKAxb((>N9G6#fn`rQwgKX*8NTrB@ggS$c(W z8Y?5R^~E5_#_1SXZNxo4dEIMM*7K<<}8e;J}7PYVl!oq|_IV_A=_+jCJ#nX3L z>vNysDijtiv3Qvjwm;w&+c7MD!r})kc44s%i?6Ww0*mEXEWlzW7E`cD#$pT>30Mq8 zUOcn+J)(p2mI}$uhQ~WKl9ucw@*CS!UPJF(@@*W)RwftFJa`D*W&9~NnyOB^%I$K{ zRR(jK5xWT`XP13Sf0lETe10cCfBhlUQU;6r_n`QV6t*reli_L7y?oERwWUtlvA$yR zImJ8VtLX4sjfU25{=w-*gu};6?*&-S66>u@kD#%gCjpDZk;?G=e!kRqffv-ZQq+~? zg>6g%x<$}G@Dgp1OV()b<5|{Nzs!9_JaVkDB{KJwprwE2zS15!9w#hkpn0n)Lj1lW z*4yoCsJEV=Kl9}E!X>(i!T=hI4Ti@!X$%Y|G0+?4v?3dxFiw97M|?L=@;WwoLft>% zl*sRbK2y|` zye|;F?(5X+;*Hc}xr{Rp%0>^L%uAhR%x!2~9hXW39u#b4m0<7k~a7NNB5|Hxn)%E~WDg z23E06VLGubVu+RVjk{rH*lHRe>Y}Gwk~aF`>_sO=k59z7*K!_NnOVijpERBc@b)ago*hOfc>8pMzT4W6 zvyybbNu;L@wu2-xe`DN45)MoJ2poRJY4wpqO12!%%rVwGj6synn3b%Tg|fGt&dl+z zci7UC?cXBxA0(emq>WwZf|pPie6b@qrPEmaip60lEQai9&*9EkEF!ST`v-~(SS-Ne z6Id}b75xo{zPuzFOmlzkVFUOZ z$9}U|$$qmrTjl%B%-=}&oAuf%-*5K9H@f$md7kt#*iL^ef0FvSiC_*;EP1%#%|yIW zYUlNU>q$4Q+ahPV_cjI6FoBfLuaDRw-#=J=n>Nxgj?^rWCjUW@-X5xcc1wARQuVw; z*Yi07T+Zk4M~rR0m17*eRf=)?W;w=ITXkbhJw-4US77v~uT5ka->95h;Q1WN{gUu} zOD(O}fgIl?H{sMRQWIXZNiM67TlAaoX#%?3M{*NxR7tvD64s}Vm2j+2{a8Y*Pkk0i z{mg!!O(p31)GLc}?Y6)xcKd#xT*T3^(nUhk|fFR1)5XO#+Rf(;>-;jCwQ4H zFJqR9sWwZUdDcvrkE4q%ISH+ajJEqK_Tl-VjSXLKG{C9~EQ0zXvBOLx2EuZq7nNbV z5AG7iX&8-zW!PS3%QahHGYV)Fy*X6m-Dr_)UX*Iew&5!Em2|q8c(7p^b1R? zm1TP!nW@E@*+)KK*>(qL?!W#TbProHU{j*0-w~by&;?+^(Wv#nQ6%Rm0XYIP$-EMK z8@E@W!^q^v9*OPAHAiLyM9;+6=n9e;0VCBbu{0e%BQ>CC4vI6bEg%?(MIS7Bv}JfE zTW|r`mR+7es;?$re2f@gE^3AXD9UP4hHcPJrga ziIgq-P{v5}Osqk&G*3$O7euebl7#3*i2WbYDgf5%eOYS0(Q&!swwu2QwJh z8ugDw4=g%k(E*D#STx5X6pQ085?Suf)69=rcqr||%nan?Ltx1W{&r;w6RA@aMm>yzo+hxa6HU5QhSk94N>> zq>CkI`5-x1kbM*D5V9|lLj<`9&sJ!% zu+@TQwlpywP?kt~6-b(d6szgApIAovKs>i2Hg?{T)q60 zZutRyL46kvD(d^>JE-sQLFf8_oNn4s^aVwIW%AXhSPxAJqPaRQiM|qOpi80wUa(Ul zeRq(73;}Id8|B(DMn=&QGAW~RNZs)u^tv4e_!f4M_c|mj2?~STE5nM58UCijt&l17 zYPi@N?Hyz@%~4shDuFW)*$23_J$MnUa8X&H9~boBU*uK@m(oog7h^7Cdw2#nI`|>` zYdw+uO|0Arqhq#tHTx znj;`+*laYFA%|JS6oe16iO=7CYIkfjpudWt9)a8w4Ldg;8{*rO_ItDT;~Np47ES=3 z+Hu-T$PbXo57AWSps7swk(v}W!87FZ1Nm7Q0cBnpfLQc8RQGHjr;jYdA+k#s#icIz zlj)ch92E2h;wN}%Dq5g5g;^g-lmJ!iiByKjLB1E+-|6O^nD zE6RSt%yHp-y%&rVse2=z4dw$lj}M+RBWE)GzLS4Ho4tVg?C_xQroYWJRW+s_^Wb0u zm|qBFWiU*DnZ9qz`z?D2!rz?EZzh8x+bniEaq%@e1;*Fkt)`40crDpzE}hl@eXXElET*-?B}*1H|5#cl zT0C5p1F+E7hv2BEcPU;Zn9uIRX*V#odPd#;bZ*l|~2$L%2K;iBWN zU>(;_SOMRnw18Vd;#0H&?9rwoqLxQ!1(R`>|Mp%^KP9XHE}<2~nU7zNwEW(|a*$4l zPlheapz;ou)B3fJo;A#V!fnCP$3FwvvY>%kL>#pUKZQjM?vECc#w_9iO_Y~~f<-(E zWfoBlEy5FvZ?GHB%j5Qu+J^20Pp|XnR8dDhaNk}m18`PkhlUi+sBj@Voa?mf{2;fY7{G@(PqD^u4c1lVY5@dC@6>= zKx;X@n_I=#Xf0*_270ET&k)vvm!>j(vh>f2iEq7($c6`v>DM38r(|o83X*6Amg^uY zx`xnlIn+Cl)yvlqkc_NTZAXE&Ge(pm+V)B-W431!J?DI8`?dia)$=ukfvDbgwBJL* zlsfbgch94ku##ArhC=gsOHF8_gwVQtu5`~;AAt?*+y(BrgAcI3ZWnjYNZ5uyr%UHd z7-_6c8+>O8vx~4`K^w{x)`3W7L(7JlW4-7z4wh}u%W$LroS+Q&yEEUk_!WIbAt{#t zFLCUxiN?vNNu+4{YWe8FBvYj6;q42D-cLv%CLVvXD5i#<9(0@CK}S{?-<5zl_Z`zk zYnr>20f0YoS{;_Vm7(UH1s>o<>UQX$hL}-nLwK53_Opj}dkc#p=PFUkFXXcW*+{+o z5V~0X-?57&Qh*uGT`U7viQnVxbtF9aRtFwhb6NxBfszZ%NNM%dEMVCt&F9Esy7GtXgiEN#n0#tHei^j5=zpd~ z65O4FHi!)mqeub3u0fmU-p^^!&JF=xwyei=Sre659E-iE%jHy;YhOLR$T<0ZPnOip zo0gbnOg$xf?F`mi7qD^#_S%MlYO0+fdhNjF1@+nl?6o_;;euyd0`9j4`U*jJYze?i z$crRd`{|BTvesSHau?N|P#5Se1^ri{Zn#9%?buGQnzb+dpQ&7#(SRrk3rPlKVS#7< z#GR*U^cfS|qq?B+sMnartD~y@uuyCXK#iv^zYQ@Y#2<(MJ!o7!kO}dNJ_MC?8+v1f zZ7f#2MTEEi1_;lG)2gE2kn9w?4B26~AyAy7i#Q}M{FL)$(--&mUtvtOP^Q!C1RQ0t zvog4Ysrb;1BY=KL8d|cIHPo3j{$h7%JdM+uVB?gm9=u#T5N&{TmFzEW0cRQHv$kp7 z2eWP&Q)k}-S$LO1S&V_nH{eIa)3{r>|3S%8Gu)H(aEmiblY8c4?is^alRq#AKk)67;g-CwNIVZyjqWV!$;@E0sTVEBa`Lola?y zobMQz-JGDE%=}KVG6PDIH==v0AR3g)33BaPv=I=i>G9Vb%?w{aSp?T5FADlFUyc$k zk?PE_53uWati_xU<4?F?u~byC*$b*3+8^ktf##F=;>#6!fa15qgPKlFq7!t53mCd*N$mHUz~n^NAJhJvLx_25j%(Mqcl? zp3t7*63{mZ`XW!>9=!w)j~Y|I$6rqocdfx_`E?zj4;S<_5iRMZdOyK%Cxvk_6}cea z1DLr7vT_ELIMohSSQpS+X+RPSw+Fm~4B)&?&q9?8Rux&@Ynipca>XWQErGUM+ngSb zBsY#?jRrGjl2{ocgyzSTL>~<#?X7=U0<78gYX(~)0)wROlDHEBH^=(XziE|8O}k$Y zG#CD5BPf9Sf>86>a66`)Br}4*f zH=D%<-z^6z5u40OCa!Q8y6bn?{>KemO&blMzOm0heOm>cK8T6xW0w}NOY!mK_Vgz} zOX0Mhcq@=;et|&W6hKQ-pp=^Zn64V8nLZ|ga{-e~jNW&)1gg5F%%JiD|~Tr%NLk~Ra~ zBItR-(BV?LY0|6t7VNeTp{5s49aU%Q;)oH_ypiP3o+z=$tTcFG>BmZcTBfu6sEGkR znEr`*8?iP^oWI!;MU34XNIi{YNiPLA)Tc-Lt8T|?PwMF8Z>t&Vx}+Dy`UE_yz?bx_ z>zLx{l3v1KkjO|*V@rBKwiLLe7q-sD6z66_b;0ZMnZbS%ZSYSlzQbZM7HLnQ7zlHX{J9F^L-Ix%RO1fu z7gkdZj;9;J*aFwvUgWgqh!M$d#aPcEY%3u9IL=J&A)n7lotbM{opks9-f(E=D^6p( z_bEAhA^wi<-aqmPKyAb#1&a@{xPs3I?8jm?7OC_Rf=};1v}bR>kpDa`V&Z;cKS7h1 zsl;!L^5Xjm=%CFOTQS!zq5>UAvvPrO)|;5dc4FARx`tcO-!Fk>b>0Q^qk_KgC2m=G zi6}?WdDe;?Zreb5mF+!w9IpRdx>`d9_Hg&^pczok!MjN<^iEi1hv~n`#Y!0rY~82>F*sbro&2Sj zSY?MyD!op&fvvKqLhDDB3+yjK)uw5mbKak$$6E0b&=Upyyzp3f$uap1-7<-N0oRkp zrz)&bzSoWvm9U_vd*CAe7$Ux6TzpMEUBpKZ3N*dD8b%8}P>`+3Hw1tLHv!Z& zD+Co{Kau?_WdT>^59INwKy-@SAu?Z>ZmLm5ZNBK3@c#|dl~aMEFkM>m8P~)69-xO- zxU(ij&}mwaQ1B8PzF67NMfhS|FQBo1Dw~p_kFb;Ih|2)SVKodUke*X_$fhH#HQ4&C zsWffTl4-GFvp=9&lnVoP9`OC! zBIvDzDd43!Y?*T^@@Qo|TKIaJa)VWzW9yZ|6zFp+X1-tBVGF)1!4}Ni7_!h9s_X-X zY%4fJtA#P(B{gH9Gm0Ze{!3$kVV0v`=9e#rfY#tgt)U#XhM-E!8oHnvG{9mzTEl$W zy>X4-p?Ar8>GcZQ>!sZ-h1C1PNG#%XMT^#+^S<$R1{!s7h!y#NQrYx3~Gi#3ro@G8A)fdnvxeW_UNk2 z$P8flV@_kMGDt?2=^)pijvXA=$REJ`T?tJ7tg`liFY4wf811 z?pcWTzmU<|V2en0tAD#D-Pw~K0At(9XBpc$FyaBvDbtvqXRvYs+G7_lHG51G_IPEY zGN%lB0NOS$bjc|<9sw{R3-jlccxeus5M`63R@OdEfUc_bE4aB@izP`{<@wTX<&;}UPKir^lUMqZ;U6qCPhRBBoHuSM zI3t|5WJ`gEhxV3&yGaE(?~!oD6gJ<*4g$Xcdhq=Gc7T`WuqF7Z$di@vWWhxSw1Y5Z zViD?^SggE@c97wcSZtd|Eg{><4iaIF#k6oj- z`WIveP3xxDn`BIdCHDj2K~V;9J*Ez0)%;@=Dl~9>K?+UAX#DY9=8fp9r#^TJv>u$s zUOk0mw>*@1KvpITnv)#EMQ(WY6x%tm=Qj6RlKoEhyrL==?AY)0+Bl`x8j8#Cv*x&@ z!TY)Zz|nK^r@?q>4%_=P72CJ6_AR(G4z2Z|(rab7dae7n&{|i3e1)+Vnd6)VXQ928 z!|szkyGp*{4_^A;4u9lIf~hTq!8(RNuaqii_yeBFzPR~3W9m_6w9(9H7sRU>Z8Yj| z@EDyzeFPER##zi*`w(%?ZUf?6#A)qNlt^~lfPo!l5?%Es80;4ESp@q)68h8p{uYb< zaAd1f>~Bk$cyX2@LAvx981tCroFE}tBuKtALE3V|ksz_nAIon*MpkJ9YY>j=cFxMi z+yIMTF_Sg$0crI2L}+v>r$u0+NOn&e#vQ@^6*&j-WZ9*Wzpdo6m?m)9W9%$e(d}?e zo7&nPGfr;i$pVyTi?4PWQ|az7Vg=#M3Q7-Gvx0E6f)7U*)JMh;fkY+0rP;i zg43eeV!%ANu@c3HYd9{NZk2~kAvvqbXKK^x8NNRoQ|WRK$yl3HSdCR-HAh&}J}Ds0 zry1&{>52@sIzIY!WV&;PieyKI+MH&nW3MYRR8T?cAVLzSYNnf(C8{xJX7PWN(tC#B zMwHIe74qF-0%pRdJIfcz?#fpyFi`pK$acsVtmkOb?>CI8^zD%S36wAZ(&b|{AYlk3 zc$7{T5>G%4p2k4+B|y9W06@EOT6+YFWVe9AUZt@93Liqd%~=~@+e|(S+5Rbb&N{u$ zk2cn=@kKjIKQf%^KV8wKA2bH;zD;-T(nxlfySlDjy1C8KrJJrOb?>$@wKgG9nYRR) zUmBq%^Oh*{ZHY?bxql6er#$Cy1mSx7E5NlEr}aRtk?bzlq`m$c_Cs-uyaqVvp+Oe# zNINkowYv&MEi4XRf#S<6!06Da3gv%O0T}H*)miyKrdzw}(|`<%SoG|pYBbIRzXvcp z`+;BH0D!VL&}Ld2a?aT9`?6UCP(Eq;>%W168Gi!@H>^DP|A~8n8k_(weiQUPVlNQ8 z^sNGHid`flG(+UsA zFZnhWKjk(Sf7@GdS^>*9Vqh_{elJRj42qHMU^+X617|y!e)9)WHz0NzBZdo{8YX{Ro zahLNBrcHt_*};TdIQH#0?`WFJo`J^Y%4ldyYX{SNWtBUaDzUmoG1Uh+b|ujrOtojY z?qD*rM*Wzu_-+kEyEVW?sJp4J>Ph1A>Zi98rVUO3o3kMR!!r$$od%!cf z7Wxi4e)JJPhm@a-gkBq6D~pM1*%ye3o7k5C+u7RqyBKBsj8(?ZI1xXs@`ZG^2LiSg zTG`pEA`-|;TMR`7+fu0Mr@#hd z`nm#QF)?CON`NvlEkrlmLNqV|t+UH*pw|%eKEgWT5{yv=n!zhcJ>5AFzptdZ)Z=!M}(vK$=p>CE(87oE|WPe963a? zmS`Gw^fh4g1}lNr8o{d+e~hC0D|S*>K`O49tjM8mjDW_BJbE5AlU4Jbl?C%J4SpLvA2(da3Akiu5?2(j`S&lOhgw4aQgE`j^W zs?)9N6K=4L*1t^PmgQFjEUrH6jWg{K^lXtF;w9cmv7=+JUcAD9F`Y%w72s)z`8@8L z&wPxjbFt~pqKUC+?9XsMp^2dP7RLT8QPy-17prD_ELh3`bK@Y%TcAj|g*~D}`3voq z-@Jzr9(E=%<qdAsuC7XN#$*MM6U8=UqwHps}8IhjuU^uGc$KTcy4KR`Z!=^|LUqeYnbA)oc+Gn-h?Vl?zIc`h3= zpR1|vQ^-n93&%ruh{Al@I-Yk2AdsFl%3zSn<{*;|)QrzM!rd13v}Za$K9CK+;BPv- zh-A8Q+Re8LZOLyux0xwuOW)#z*qw2lK3Le&w`@{u0k2tNSkZ*bblP0{ZuSC|^R`uw z9@;5~koM9|!^F&B*Ki~q|NNscu_SI{sVXK$=kL0VQ>gJKY*#e380V};AZw_R{G^mX zIMD#eZ`^{aa>uf&1~LDL zFdsY;kbGtlQyPiUdKwzm$LK-(i$+Mp{gyz(?{FHMdO|WB<(RLdz|@nIftFAaEPX!h zpE0afx=>#hpL?-!8e6DGvZ{SPR@i5LHt=CEB^w{+XTzA1V0Yh);hwdtOopbHwMS7^*wZrwUOtrgay599^PnEj{yWaI?FO|DmyWVwM z?XIe>cYWDg<*q0A;(~{xnab&2?lKd>3@&jR+sjSK*hMymml zmaxF2rnj~Sl96iZNQ>E@3aETqPk7y9NLFNels}!CgXJ6Bg1L9?Ip=MgAKar)skVc{ zV&LPlPFRG{WtpQt5>Y(KQ_U|x9+yxaY&1^tpHC!RWk6d^v&P-sid%7q;ts_rTHK*f z+$Fd>#fnP{6nA&0xI=MwClCk(Zr<FyXZEZLT|w_;M$VLkj!FSal97$z zd{w@rC{R;&j~w7i&LDokBOuGrUHDAN&UfhgM$VE{tW9~dtZd6YnJY8oGSzY=9$mBq zV2s3#mLQ9Z)W$$=h$cCamKA?x#O|Y-njRHkh~E=>mwKfur45vlV7l2a2_c9sbKNt6 zH%@Vo+S`CtuLBx-7*89dO(XW>o&Y5zz|*L_{=c+DjR{Jy7yC}9E&x8VsMitZM0jB{ zt@F=Q9cV?qSl6<{)@nVcq$%I;hxmI?I{erU9)|^3S{tYZ4HS$G6xb*vF4zVV8)H!3 zn=spuY2!meQL1^yvGN03-z2SCCDb1v`ygKt( zlwI@H)&wZIt=fSRckQ<8^}3eh+QL~p#)zYxxwfn}tjmef1xzJv;)8l{=$PBKK*M<* z^v&7E#u@k#g?4xi&D<9|$!dU>w!s(O+*c%g$pxKo8C_fdcjy|P@{2zb?izGw<~nuL z#=44~kB_lHLRgDEsjQvE@wfaHdyo27z^#$m1x9Quaqw#op2sLDflthYvli@K>N@!c z{7N!Imq5#Vq7laQ?Nn8Rkrs1dlJy=#>elYot3#2nfsF3VvCCFb=xw)uhqsOrcienq z@6ZN`RT2n+jsIU`+uXKw8qQv5jWsuVZ!K5D2=VU8w^BY&CMiy;D^AYP)We%<#iYZ= zeEm1Uw)maHi7aLFQ_dmdnA4srV|8t()iBqicS{szH z+H&Z`_uZhfQJ^7OazSL!ek#{9I|qI5@H1*$>bUcrJbRo&8Ws`g3NzW@0F$xVEX_dE z-j&W9zZ{ZXhNtdO)Mdw_=}tn7df6naObOK2^!dfMq9xo6G1wGPCDVsk>@R6t-n3YDWiN@ z`h3b<`YO(!lsSL|qRO?lfTF9uK*LSWh_OT$ zX9IyWOqu}{;FBOMm_Q9(epRtltIH$#j$G_Mj*%$vr#}7riMqm%-jo@qb;Ws;>5W$~ z-sO@`i{K7ylipm37=7a-MR|UKqdA9)3(FcSt;6+)<*ltG{Y}-+{;V&O{^vrMgx|6M zQkeECc!_*qXYGebiEpnHUD7A8Ycwm&nJ8HMZ%TwelC?KQSuIm4v%h|CrV{Bh_vhzd zL$|!lqk_}Y3))#+;=aRNmxLR&3LZ^0M+^Sd0O<-_?3p&xsO{yg4BEgM@pqpeAIdCB zmx3M(v@XrFLX2%3*dn7&5k02CXPd;H-STOsS#O;X9T}S$0wAxFsWQM?2MuDTfC_FdvTP^ zDfq|+&bO8lXRsSXN^YSEQqSKcr~Zwo!lP(#BgU+gv5^u5-AUq9hUa?QI)~HAZxLq4 zPL`dTXvtxgR!>wBitrkRY4eGTy28H9ZaUXDT;keq{1W1$-~MXabixlUj(Gi4`)wnm zx0)+x_!g?=onv%tnD3#jIcSrMul8ZgoO4L7(cvby?UYW6ik)cc=7-2$ovOjd#l9`C zBuGT>-Bz_yq^I@?57}}cMpcE7P;?R{O-3NTEsOW4TV#-=ziLTvaE)DlwBzBVvs+w#rBVllj7u$=c(_ zj)hg!+_$g#iC0mk+egOZ@Mc1O)(4@iK3#_X-1!x#)hT8h8c|Jwhkg|s`AS5z@7m3F z)E@V>Rr{X9c&_vN#Z2=SM)htF>B&7pcSRji*FhrxYW9kjz7>XFCdmy4yo<98yym+a zkfTvN%BvCuEWK+C)y<`_F5@5DlefK~Ju|R$ofY9aua6s9m>fFWbRn8odq*1QqS3ft z8swbHt*TM;@t<;tiRSEn#Kr9wGzrNwO^HBd5$wa{-O$1nJPGT}K!VIzKV}7Vas)_6 za+_rnOe&n(uL#WV_=^-9jtG{K<#qdGLf>#t@FKCM^4vD-v)i3^#wCB8w;aht9bFU( z3j!TC{Lwn)(|3C!FZR?=JJr*D?_O`|)lHn&Jt*%EqVL(%ZBpUn*{%w&5-o0_W9|At zZ=Dmt584E=3mv7{;D*3_$)Oi-g+kArCKF}@dXcJGqW9qA8DX=a88ba9d9%!jkC5EM z1KxizE8qD|Qj=Gl!CXD!rS)tCcC65CjB%Dl99=aGU3WUBf~yx3ZMirKZ4|Ld^MPvO zr)ow$xxI1p@pKz$yBh(rLa(0KE_Uz1a~;%Cin=a753n}yR}Cm)uk)kfy}w-YRj0}B zvaW_qO`ADHab9*usi5br33yc$Ov7~N6!vm}X-x2p+j`oDXUZjXiGbhJ-+Z+7f{ad1 zlBROO`y^9uLY5ydlXkl#1l-rT64tXuDg%}1g&9|xMZgI(o33HiYhOxmv^ zypFDoFMN^f^v~B|Tfceq#a*)s?~n+&{RQ5?On<=nic3vCyc$OnlYvygaPyHH&=!&>D)pf{DB>@fY}H1yR4%jGtcxM z!DuetUO^1HUOBDiWalvgJOUNRUX$pzBPriANS`M_r@A0da+v6JN@SRW>-52S;8SAh zdbbcD=7i1XbN_yYg9QTB=fK9e*O66rcq<4^Im-^Uc5}84;Wlg~EYDvax@&Ss_lAu3 z_Nv%^{w*R}{gou#?ZON7W9?sCaqdGCJLohaN8igI*mwAlOgxxgg`LV9gqw~0+#YF| zQDw9p!iHh4f&zZ0wS|R{9;)(dl4THLC8s#vIh>pD+gbiPoY~I#Fy77n4#PH3|2-EG z;lUrJCx!KC*?vc)XtSGIvgZ(XhiX^+2a}l4hf>5~^RC}8>QvNb27;;E7w0rCFQAWATxDw_!uHrqIv6gCSUpio6ib8uKsN@1pR29MnD87*LK#}_ z@tZ{r->e~34+8#Fve@I0Au+=4|J=L#x`OxM;_OpFWP0^x~^1HdcQBY zcr?186$&>Lko~bw@_4~Q^Pj1LJK{k)@^F(8I`BC(ut-!7!^B`9Ur#@Dkl{`&1`vgt znqF{Vf5ukvGft=Rxrs3}pSj}b{@eGA+R!!zyrA);1yKa(F*W690c)j?ERR!13try) z>2=Rd#xEf~2D2aTzxl+-$geAYS(7Jg#Wak{OmpWF+Dp)#E{li*{|hj{5XaXy{4X0f zqxX6VEI-z-Gc(hrT_=iKncVBYk)3ll5t!bVJ8^E}?1@ula;(P-fBv;e6zFQJVt!9L z%rT}JY>OBu-%7V7QFKA>sNUoo-XNv#4Y;~Ud`a*6r(YzE8Iqdy9f(G_57xDS~fpVz9I=K2$tRO&`-cM#G%H6hK#gWUKXkhWkS){?_ zlXuHc)IJ**J}l{w{|^(iDM+`K;UNfr8>S00&gEcN;-`(+6*crzZ$`z^+o^II_TG5= zTDsXX8KyIb`_|RV-$Zz~6^{R2L07LZziO<$5RX z{$@($?b_udsdN6w=?|NnP}aZ>&t3qBnt+CYo0b7cB>kI_p5|)? z3JWu>F`_mB0ft=KEG|L{Ei(%>vo~tDqHXV|iN5K<9Yjzc4%q7d3(*?vl28JuY#Hqo98 z-to!qOAdp_>xXqhIx6+lP|mT_RdQ`zcjM&qd>^Fyuv206-lV~p>oSmHFw*9q~u=r+i@$_ z`NOzDiYeQ?s=nitwB6L;58OaHgFf{BI7KnS!#I%KLN_RVbr;U`Q(-1nkB@o%(xToT zp=zQ7ZgsPd+yMC#NfD1%r5$G{?)<`M)acFgpoydu`W#hM-5-F80KRP=Yq}>G`7F!qhjkPoUqOQQ3|KuFX5vGY-sixe|&y)(RGQh>Dm8nmg z^ZnRH#&*Q%mFtudPdb;yo}SQLfslur{hF&8EsXvwwHh_r)iIs)lo0e{ZH(6kI9eew zr3p#6WAuJUqSl(L2~*O*AbVruEavn|^vV9^f~@8mtiBfYf^Q=jR}xbE&rARMWj*Iy zWmxmJ?-oAK%x}2`p8I#V`ib=N^BWvjBTYL;oC@_c6;C@Sc8Srrylg~gR{FtzrhVrm3tlp zIhm6zouT~FhIeyW#gk_Wx|sAVg?A`-7Ht7m2QU57#letCUG^h857{TxeIM|+|CFE% z8F*_ku zo2n`*^0ABksL&@}j*DO$Lx*tots0NH7R6~QYJ=>1!PbBxrEFSj5lu*aUftkbiiE(8 zFki3^yyT>L$=pD^`7}E3*8JC>Da*6Z)t!ERLGeUSn-|PNnX038vJ$dSq^R$bl!MZ8 z&wD4;q+90@zamgzx982U+V7=B-91FtwA~j&#sLRqp_+ZUfO2Njr;$7<%)TPmQe>$= z$Y%Bz$ax3-7v_R%G7igYk66Xcn7^Yo7G8SdbiK{&?2HYl{Y%ya?+lJ-pvcaA% z&23m8fb1O7Wk>Q=HtVkrWO3v&ek%!-wx63@?zPRj6<)|CH?}uTW>@mt-Vxao!72j| zN>@SkjN2RUFHKk=cLY%DT#}vWXnpnf7;Gn(!7BFM#C}X3wT;Y5%PiiYqpoAjzw3hU zcE|RhsI}8|K&eP)?TCG=YEVtR|K-j|?NHE~vOU?H8e#dd(}=u(>w>&J%(}hAitHJU z$BuGTnVLY5i7g3jH9aPdSd2zHc8aY;|x^=X2M5`9DendeIWfveN4e)_YIb+zpFVQGRN%{<%M~3iXtWoqt z>H(`XdL67J&V%?-;3W<%)+vRz8PL>hE2*8A`$xF*m;N-?v1bOz`lEny<1hVe$V)u6 zQltMs>~mrFQB?|T9U=n95KylH$s)Vk3wgVQJ7Z`yPb|&!h&$GNc?7X7SDTw|8{7cczW399P5SX+jEc1g{(51=Ee%k2~kGr`FW$uF*>5A5R()U`DJ0 z3a-nwn;>^2m2FCK0opSmqeChEot5HO0Ba!gJ>!CEPf9e`6*I=^wKQZPtw`>~W zW2&z~H(_EWQye8B{Bfal4a!G_qO^Z%(jlpz-L%s9 z*KZ2sz9&ctfm&Q+08&JP1!8ITM2z*YGfQ|{Q{J8!YNdZ`Qn~E&+%Q9ljr-;IcfSR& zYI`ZA-E5#|W5cR6K zo3WaOuRhvq%Wi4$O{#Bcc}zxaYw;bby6c9iDew5mahE^Y}8NGs@1!X-D!Y6EZ-40<70UCW<2(0PsfikoAWXFtMgW6890-McPkDtPM0D4 zp|9bd1fe7@d)@VH3kTm_b-C5t`nK$LE7+l5BpLgCL*bMdDV5biw6(!UEpi8egmsy1 zN3=g%5pALUUYC}+kb~NbYvjjMg=+04-5~VJ3A>UK!v0*{Fsy3xW0%z&F$+lt5u}yl z%zssaC;3Y@yT}*TS!zL*3f;8j>eyaiO2K3%uS;Ks=Ybfmc5L z*XGaBzb1)|nEvv%HmKYh8l|M4_suMM#C zoGrrgn`}~_KJASwW-CHA&0FivP+tmli9B_PBVs%is3Nns zCT~sF1C6E4c@&>!^GB%?-hv zitIpFB%3#veTwU{uoJAZkQ38nNw}?Tv&^k7>J>DO9{--H!qQK&(Cat!r_l18Sd_?U zd!#*Yuplb>+~&jY;fY}HFZ}!~bd+=}GyFQP0B_HsXEQDK71YV~`vbUL3a{S-+L|&E zcgfq|l30j9SbFsYOoXhg*9D5E_b84QuGo4xV}0e?S_!2rIe!%ISxR#39pU;n7y~v} zWmnrbKKaBxEUw(bxDLI~ppm@>`Sjt0@wU}-9V4pl7MAVN-vJ#wNEgOgULz=6{(QW! zTu0r3$>mDm7v-!iFQWOwLa`uP!ophB6Kv;HVS{-wc3j3_t3fBiQc3>T8f#tPk;YE( ziW}ZwnaBy~kI);oV&%gfGA?J0U^IDIYFKDD0^(g^dym0V3_zM(zne%K`c4E%k9JmW*Kk z_GQ%w<>+Ue`GmxUpkDTjMfh^v`2`h7wm@ReySd6AtefVoynWPgbxN+e&@!cHv*Oquj^nJ z&#HNvIA9h$z`e!B0!Z&`EAS!FReigoVQWDzY)<t%kA9^A&c?KcpR@F8E^fn9!kCh7q)5%xQDcJvVB`w;}h6zC{%c7y&{ z67W;q&dnqN2nH>#%)~mKl3#@ZhX?gmY2rdmKi{zGUfDEd_f&9>@b93>{4y$e=?UML zlK$yG%VI2=IFiOZQRHBsrtE>NER_3Mdiztx$(e7vdPfJy4O_YW@NTu{s(a(=i;4TE zc7gqd!{m{PTbjc~z-`?@y7LR0Oj0Eui6;WmuPxOsb*%}choG% zyC&N$8Nh7(Q<`}EM(m0Q$M(fmPc1YHb?fM!51LmD#%p4La%c)D4POB=te69?u6yilc{I#?;PM98V zH~hBFf<=1jhsKG8I_sI#+ps9UJyH0GqBMY*HcB8pZ1|suUs?+ z*HB8u(1%97rZy_h=j8pV^ZK3OcJ}=iWRUNECi8Av8yMgqUQZ1kzfa}J+c-auExx*+ zP`i5Yl+~;~Rdzyw6o{R@4i(ix7zx6AEM&L;BvOJUUXy6qOKQI7$>QE^%eL*8V@tb+1f|0rXzG%C4#Io{`!2=PfBy8bScJJaKr>fUK!2HW2gCQ+fMu%hhS+ z<+&I@70PHq%G8_?K!`4Did$UkWC#LI-MK1nZ|ZF<5TEWtv(UVipRg7e*FOIVoz;sy zIlqgIda`w)dKaA)gpP&*rl{Wl$Az_N!fy%C7FiP0qv=3TOT#2GOBOo5IY2d|9D{ zEJHA3>m4+wuevFEbkI5l5b@9c_6@WNy>vzy`b7s_o%+|7L_L8P{lNy(uj>`t+hV*` z)WF-foh2g5y=|>lprg|+%^P8Gk1o!8!^2A$cI4S?Svx06%iZ6X&?lRqWsz{5;2Y;P zZ8S%Ydk@#~G4CSC^K1NHKJg?}2g<_)u|2B>K5pynGtRcpiJbnQ6gyV{f0(t6R`M81 z*ZGY)p7eS2s?25IVp(leTJt~knC^igXQTOTY|CpnbLhjzedlS*@hi@O=uK{JU#P$; zr!Z4YyU0ZP7`fK5FR2`V(SrqC6XMdp-Y{0 zUK-ElV*vlFfY!@nhqogaUhK#Bv2KXqz1cf*?Z2zvGa77CeF+8Gi0fh^5VV7 z|Hb*N{|z0w{@Lt(`{Wpey@w`EHFF*3U+8=T-wMq8zDM&8fZE%U<{e@n(Oaue4fY8% zZHwABA2JHPo!o$NmYGDj%ywqKl1S&u_{a6#Q=wI2?8bD(3e zfnn&^X9(-cq2cedGCe- z_5-wdrJ#WGFe${Mq$FnmdAZEA1o~Ox?U*J<7p!aB}2|DF~x>@*RS?XWw38+VSt{IPoRjvcd*p^e;8XC7Mm4( z%6NHN>63ZwJQM?@;Jk~kT$}2#;Q+dVj9WvXMJ@ndE3awZHi7x#yhFV+4=*cImgxT> zc%`HVN*)Bf-b-#rlW#2$Bi>%~Lf$-k1EKW>)haCA z6~9hxafPw2tmhF?9pD&edZqi=`sEZZTD9JNsH={6YnxJIy}LWW+TDSZ-=VWLvs~c% zvV=UikAGFwn%?)$NPRp zPdER@f?hog@WBF@XId_iuhAq4bbYD32;_k zbce5-VgP4TH|2r?WH8wHF26@SzQ>*wc*)7r@gJQW=YZx7aw-0X2t`$pzxsA1&U?oB z`gU{;)N1S7P4-ZyBL}*z&4!wO&L0exel;w04k9&%`ZUdA=hHYS84+}QEeG{&p&;Nx z*b^uvtf%^C?=64mbnhGc5>>6J9S2nWt~*c#^mSio=@n3q zmkE6xniReH9Hx&!!8*!HrFV<-{^myYUf~lRgjnbdGt|of-cOf9m!+brt@=;!ppK-V zbSR!Ay33rYhkCJrqpS|z(6Sj~dNTg^d}CAs8~E@t=nqDcdexfK`|{yk7}^T2Op&yq zUU(V`$8;!K-M1D%WJA3mXm=($5i0jf=C=@N&90%Xs1RDEPH5LA@~KsSyVuGCYPXGE zw(1k8(vHO6bbvVTf%o}6D^R)SL7eAnP@7$udUfs4ytS8cJ|IH1QUwAIOT9uB+e`5s z8XKPi#;ysWEE}O^|3{7o0lQ&uuZo|&L)CfQh?E9xfof2Zt)Uvz+FB6A*xQDKJXhg5{x3iYR>wn)G!J-X-G}lA=J)L4 zyl*WR%#7O^L%Wf$8AwngFl~(X!a!>s4gw|wKV_D1_Ig%BU25hw*02A!Gc*CkK_!-X z&8g+=4P)P&YmGfY=dsE0TfrU(n}hpzt@wH=Qo^NX&D=cNXYPrN23?j(b=Y_bx>Q=b zQ}7zzYEPCTU7Dm?t!q~yEsiqZH%0#QBz%i&fp6CG(|(g@*GkFEEytn?Z!pabgJdii z8SUMKb8N?<^cN;MK_rOnAuNT%+VXb&aYKSINU|4xs!(Y6J^Tin-|z)FYhi{V4K6Vv z$FM1T&$eYToM>>cCdcqV?Q}?kFUW8$gq8|We(lUBX~}my)JcHeQyTM!8YZ$YN6Fxh zeFV;(rE)Ww3m%Ig7AB8N246))rP`Tm$ovt7Bk-TvXk`QnN$(S4e>pa03}z&GBWo7B zf;lByJszvoJEa5H_1oyS5u0}#;$uVE75ZjneA4K`!v6lVRH( zWkPZGgWKMWjPnzI!*IF;L)_U-*|s%*5OtDXNQ}cj6Ab$Us!EA# z+!KM3GHw&pnE{AZgc8)medS3QG5uLRHWQy87nthVwi+9Qp03W{aI+qwKXuDfyLTk+ zO#YjC6UU#-!kYZFmCMbfC&F+tRG=$vax)s#2;G`ZxV%3jPYgK~n&_tzrd-#FqCCQ5 zivM;^asv#Z?}$2ui{kB}jl#k3xW;wVhP#)JOQd7INSDAVo2$&{NWpG`R%Jpiilwv%j=s z(M}51hkWv^<%EH!pXIE_fCs~JY1p4L$)w~=oZgCy5n&v5HS=t#Y1|6H`52ad+`mLB zBXwkg9{v{Dd!#D-HlrTZ%PQCg?me}C+XEvJLoi#jf`5_9CI9mL*BhOQ6727Dv?ZU9 zp2t5OLC)H~<#s*Fzam7e8t%Z!ik@s8IMNINl%~6N6zAJs3vcULz|joR!!irC}azQ3QDnUZV@^2}65duUpr8VqU?Yg0(1NzH`W!r7s)= z&U&b=sW@4M^(a>#vi!69fA8K{qRmF+@E=*`zA(hP)p8P+$BzlED9HtC6EMf2F(g{= zNF!kV*cq5aEWKh^*}*~O_(3w#Cx=48(l3WU!R?|67X{rfL==Vhl0+$ZS~R;)D;8Kb z`q}T5V07jdprTNg>wi_ZHzPG~JoxjsX|nDG{q;VQ`W=?YG5u{jxeE8_82=rjA9n?wsU)2#z1Ha^^4>C{rzK=L)@v?lIRvy>*jFX!>wU$+HRr|$` ztKzw1QL@%bPf2&en9MvjNfZ_>%xzmW zmM(IQo>myt9~6zh*d&gxS@+beaLX=8Rd7xi?m~I3L{5f~HJ(UwCk8nXrN zp|>;V2;6Pk+=z2yncqJ|{JU^Q^k+X7Ju>DbWP(U=-f>{*159SWWYhYrsG_tgKB<0V z)(GdL{XjQed4ggZYx*EwTN2hMJ3132aw2rs8kQIqbR3r$6;z&mzKW33`I_1C2~Nx1 zwc-e=JUcFZ3biuW%aVVJ+mKa_F;h82B$+ZPe-0v8{0|l*9Z%Lb2-ZRUkBf^xY-Aj3 zg}RKs4D3F!9`#Sb8P1xq&HlILI-;Bfe&G;cn~I+8McMuDcZik_XiB~Q3O~sH9I5Vd zv@BbhTe>`h=c0%L%Y5r#ooT~C8#u%3H)^fZ$b&8MKc2iQp zwsnl(Cg2#}TWR*km0c;oRWqY;N0uo$EV1YfUASgQU9g-cA*^a}x0e&hGP2Dq< zqP3h-eGXRnou~DYU9tz)Ecc>w@Q5o<-qpTvt1U+UsUKP&6wD4jzVuz~FptcP*&T<> z>HZmx7dR^K2pYTKPrcwT{R4ZE&QX=Eo~i#;RU{CfOskC9{)e+jcx}qfo?HZ@R0?-z z5CtVyAfX$Y@?W#Vr>LF=Y22CkQ-za?>5zu(DGwc6KDlu$ydFi9rN42~R&(^=-|r$Q z*vU6rclay@@~w$GCyzXV_bB?pFACJ}3c+_LA|!f8E0|7Xd`jrsXnE^mYSk9HU|KM{<;QbvoF%Lg1 zx;WyMN=gYM?=|o?{?9AMr&9Te`Z?&GxH%s7+C${cUi>2ZEEf(;^*U~8EwOe^19jOW ze=AG-1zWq^aw4|Iv1RX;H?WB@NLEVY3!{ zF&rZ!VBu~Pv`>`k#?7sWU@Z!2^aB8c=bHeF9ic&R&1XwEG();)RvS@S^ zXs3`w27C(H*ijk}<|z2mzRKUe`gW^jK#Xp-{@D?!DT4!js&JIc&!ZHbjVK?_ARx!$ zD!;dWiyl>i#*%|j?i&VbabQy$>1S)jPhXlyjtW60%DP#Jk|JdZG0G8_ zDQ#MMO1SCkh?;4#*s);|&M=V>=dcDlD`_GCwU&ya1IjXF_u`~@a++J(Zy0}ZkB5h| zcou6fYn&C=f77U5P9`ufFGWw2WZ|lo_hH(RyJl5Z$gCf2m`Oo64}UosEx9qf)D|nC ziJcS+=SYY-i4TpsK5B>y)JMNO%3RuYYV~x5@6}?CG-}o0;u@jpYE9rv|Mrh9{FAAV zYa%ls!9gpFDaZ3xLvSnTTVGo>iyM^s@h$&FP8(mnpN|%9*PlUD2}#SO$%JUBRQ;_c z;wA#`ic_M9HqaD5sTT=1DE+4k(Nl!;NIseEJ_=sY2`>F~7WZg;84MR=q0627P7x z-c%dj%f3%Vcq{Ka1{hJ2G0v?+y{Q&bb;9jPjmU*X zB#b!kDL|yiDn$+1n(WTW3qADpJD9cP6DvL~(x8Tt_?K~xddNJ)(CuZ5%>|O)b^z2{}CwJoc|1UPmVW|+}xq(a-Lrg$O`RX z5|tvP22YPLNfBqHHtaTj)9dd>>nmiJ@( zt$^%@u<+}eE`ZM#+jU1{>!oiR zbHwrdrEvQjxZdaL4fCPqsMsY04m3gP?WOJRsdMkYcGfN`#-{rD4xSprM|B7{!f7qN zF37o%AVl&@f<)l)@q-(n8A%QLK{vu-rMHL4w_yX42}8v{69${#`gLE>^}pKV_J4eV zu`PUKc@gP1@&8KO+K5IA*>`${_PaQ1X_JrS9%YK{gaJH__;Z}QVFyeaR+C4gEPv)B zMs6arTOO~4=WJSDGhWA%Nk43C{Pb$#5#Z7jxN)@p?sJD3o|Jk6VvUO|j~2Xv$ZHV$a5*x z64#H&K#7c-32RwQ?Sqr6Q4v2^AhwsO#-a**-N&y4lJb}TW z08VnmGn3YcS`EP85^Ugc&qx)syAIthhI`op+1SD>mxqIId8DIo$dFWUlmO#Hh#z)n z)qT`+yiGy8WmlLHU%Td3;szC&<46iMh5X2;EHG!cs)vjIT6bC{eEdEZfcckyLH0VV zC4k6>gPzbU_Wh;gIYX9h`$`(9{8aTLv{(CgzcxlkLdf#xQ)rA3ENzKOYN%L-e>Ky= z-LXY_-BBcrEZ}bb@_CGgH1R{izdVc&ypZ6^+p#4|KVJWznpWm@R=8Zso z^X{mp0Xb8g9gA**3-)mG*>>X&eP9R=(TCq65MnX)trM)R*~?R$y)Ec;=(}RShsWm9 z*I~avEPw@HpOY$1JuTPD0+AeZdpo3!MOWI}mRLM*QI7Ylvn|ArxWpB9#z!gE{^4w? z4}7r1(w5~nn3hV{oUp4KDzNF)at|=i!@R=-VR40~cokTHvV$^g9 zUD;^DB@}saSV!ysfFqtX$eN?^R%Q#9N;dzHOHtMQnQKwecu#yN6vo!I6;P9nEw4E9;N{-58VaiM1=M<2waug0tE(%d#p51PETLE3o~e<=#= zKGDIhtUK>)kir9a&+6tSqh*GYLF!-CcoN~=qq$$0J5DYIgk~GFSs>I+Q4d^_l?@!l zy3dL}6;gJDgfywSfB)u@otvmq*z8lIbCP<^5*C)SYCNCdVQHBW)nZ^BH|EDICY&M{ zO)gVpMmCS~98y5e3B<^7ZWwO!ye5ktL84(H{Vyz@$!l(KBgogV-(Sw#ZEoH;$$VFb zDaTKay3UFaE@TIBB`yh63`3^($paa{fLv1SM? zpf(GbK?=FwMV5Q5we`Ot*$d*$m)_0Cya~dqzo&;>P=B9QA8`K-ELWrzRiO?z5+NL@ z)ugNkiLehKJi_f#8`?^)&XDeEZkLDaS&$1XgG8!tV7{}0_365Zeha6cawi}WAkAB% zB(Qn}yGD5D6rbtmxIH`l?thBF*6dmF`eX3!OxP0W71iPiv;GG7^Q~KWX%AfnTvUAK ziH-B~8KyE&!PwKAEGFkvn?Kl*oYJl$P)(1&;MjfgGl@j;LkCh@Ro=t97s}ifO$ujW zqDOFe5SyHu+%xXFoo5GhbS);!?RLoNXc02(+V6MvM(=+1AZVuQ-oug>bFS7F4*qOO zFd^n=M;F9Kd!eUhW~m~ zGt8>4mf^$<$S&ZASeo5HV``r}*qDvnBQu;2HloQhKQX!D$toK-eP)CirE0o$<02Ih{$NH#<_d;^=q2#s(@8QQ}`8&xk zLyEjti`FV>n#=fqG)8we_g5RztG|Xt9@Eb_=_*-zC%^J1$byCaS1UI9w+T^z+wT0J zV&F-as)yGa%gJlP$;Le_G@gmjgX$FBu78_U2k<@F2prFA>+TbtG3Mget(3R0K3~$R z)UbaV71Bw|Quq@q6*yE_)JH8t;vF*a&$OfZ#L-ILaPM=n@l@)-y=Pso+-j6H`q~Vh zx?ioF4+H8phi|Cd4<>Y=eMxg^sr$AY82@Vm=o{@@VK8Rt8cHrze%J4#n50Oi-UB@4 zNLb|>!9BLGu)kni`~_2pafg1K9bl}Xvf1!X;{8&5gA)kll5xo>_m6@Jqku>#3eM^B znrXI|Bn~RnllWgC4`-|buH)G2>&S`ZZOuj4lpWIs^MqpKJ_sA{BAwoP23(YluAN6; zbsC0~VEyQq*p6pbPrZ5IaSw*}7`}^oVY!r23eUf}F9ISTPZYEv=}Osq+0(=9THiAC zc#$$6(|!j8HLjg=9e6?AO#xny=@}N`+}efy#i=T3;{8~CITk`GaG5W^gd^0m@mr3L z`06Sac~0He^Dt;ryvZI!ZuBl57ExXG9?swM-i6am@1f(0A4(P;Sp#b@5U+02Fs3ki zoqDbwC-rC+@g&Lzzdy^zp#?jZ)P5U~QXgkGDIEyA0`ril1DN*%jtQi zFwA1#{np^DBv;QZG=CB%fD2oNfme0GkAD#DU#dNzZCLX`IEFg8xDjX~*Iw|8^0=`U z5y`)NH0$OA)cyryluSe=SGN&ZM3r+*hCTO00Q7S4upq`=_=8qxPv=Tq>=JL$D>mSo zLsbTJ8h4X|7pSBrW0_)?qr(Tsnl1IqX7?_vNLzD?5C!|kjamaOo6@G1HqNa_s!tgY zKqR~aJ(J-zrb&spI3)qd86XsQJ+;H;h2g;I($ZC!#c>^9N^h3&y+rUi{K^%Diep#R z>b&buB^!%!L6?+xdwuwJdPc0A;-8X$I*S~dW*Svf*DqtF%;fEN>SjwT#kNmQNq^d{(Z0D(^Y)Fq7QylPW(+NDs|p8h$`zKgWL*EZ`Tg_%%+8 ztVwazt?7^g)3Vu9Tt7x@wW2ph3tF&bXCy3j+w=eVl}Bel_|nvsq~NP`9U#e(+Y{Z@ zCT8izi1)ZVf->&g$E)eu#Xs_v&F8&t(&-_N=*`Nm4w~$8e==k}*_j^A*ky9P|XZ~dLgb8oLxUgMD=^^QN6C{`mq&_<^WHg zumzeR$~rO(1?DmZf#r@UeJy{2C@>=+cAajd4qw%hz5+>PlLUZIH+ay^SW!HeyJDTy zrwowiolUbH9}{^Gm#T&0c_mY{34K|{npqxmD%1knO?U!skhHrj=kt#gnb)LWAxGxU z_aQa`MO@DXj^wg(D}U*?$%Ain@B&o~xCwWE+|CK55+JtRnz7Y z5peqi^Ej;-i?GYJcwk_a_;$-}RJdRhO~&YL2Wz3ryYU~wkfK$>j7b|>O_y)1?+_M; z$ryL_+utGe2GRW45n1tfRCuDqA{JRejaMDC$R=vn^1m~h1%~)E6TWm&sD_lH>8pZs z`*I2K=~;i=(BqbJ_ty7rDlKIC%rkh^G-ew_XUo^E6_^aKIiTueSLB5$qjOndgT7I| z-5yhnG$O;n`!oBaG^kR0_ccasaQaT`CA}(tzT?c1(EHjyxvu{(KGUoVW46wJ`BRJR zQ>ghxQGiQ9xe%Lz=iId~(xNkt1F_~Q!LkO!8N49W4gR5l+i$@6lJD|`lGRj&pzuPL z36@p)CmG_WExG1jMV*OF+8mNuE=YQO;lU)j4ZRqLBVv(uL7nyyA^1I7v9vuZiKQh4 zsE|{2Ei&g>xcpCeTVK?^X{1<&F0zT>-B^H~`Tl*&Fuf}M7j49IqJe5kXG`~ItRDPx z$?h)mTJ>mq0jtdL9I-2D|3&@OpW-Vta{ZbaPH;cppM&#{BX6wyspYO%#j4Nsg-v)$XA$Zd9CFbFRCvc_P_`TTsj~I{F&4)8k54w#epGs2II;psxV({ zwO-r4|FN8;#NR;etSfc4vL0ogoP0qc|H`sUZvC@}w%I=F3o|LJDb{Z#X*=TMO1wA4 zNIVw27u6AjQAq`IAcgHH*00Q3gPEVk*o;b5r40?S4+JF{`}ql9k|Yp?s_Yu0DpNEzRg{{7Ob5WwAkFwn-hWwNeYH-*On*=FA4`nCt35@a4hvplip2X_ zNm9_O7>ww{8w#JkF?fQ&6pSxA{nnDzNS0fU^v@Y$cFJ{X98Wer|J3Q#BZ_I!L^w@e zN5NG_d2>iG6I{-Z0jzJS;5xazk)vSlgwUFDDYzoPWQ|jC-p%pC!*YJvTRp;8ljfAy zg`g?wet>oOY=yhZO^yGHGMQW0W5^51V%BO)A=;1?iK4;gcaNL`LIPP1c#Sy@^icd5+c6m&kgK3VcCN95EX)0naJ^Ilj z{1G-ZUfs}aO0xz!H3VQ>AgO9-7fn8_g2{*8*I8&D=V3nqtJ_8WKu?HcKG4bsCuRavbOKhF?`XPhQOvu_zHt) zg^K#eg2u)|HaQ!Ia@gBZ{OyF1tcH$@u!g1r)|0+QFb>xVv?%F@+$W6h_P6j;@j_(U z87kAxaHZY@wD$gtX-uQ8h~x>>>8n|*1;+( zav`63?mnM-&q-dLRtb(xB6)2*fDJd0@ZM5hP$cD5$j3!q@3_kAFOt{!m7=x-B(Do& z5q?m@*GYL%5y>kKR|ce^YLLtp^Dpo;k$;9^Ehz%VPZL2fLyhF)kFt{T3zYH;lHv-H z;zGeqAi+(#?+_fGCZZTBbHVi@!8Inq`K(k4ZrDD=>G}$--~fz*Rtat`2`&Q!_m7PU zF6Oz*c}gd#KMLK?r7Hxpwo*v{b{;l0N5YrLynu?tKy=k$b>`|XeK;oYPhgp`wGS{R zIyi`UhP;>nb9BilFP=KRgfd^mYbqb?*s%@c*kv<7{JfM;@H;f&Drv&$;{<;kdv_gwH=zgn-fts*|DJ#~r*9GLRw&OFJw*-#U@zbHi298C zq4&w^id5JCSwHYkvL)}MSp`5fcB6b-2a#9d%!aneLqb8 zDIPR33F?HN->Q!U%RV6|755jSnknJw(n&#)%Na7p?ASL^3;!W4>>)oqO0wDd2f~|6 z_*YUkP!x9Ed~kO=BpOyk@k4N8>AF0|hd3Nfv77||qSXE1DH>FeI#)3Lv6QnFPLAxH zg3TQgFn)3*f%z02=yo_C4uym2pas6;43@ool7k8u4+=;pNBY^i61(e@0*(^3!*E8) zlh|Tk0pr6N0QQQwQj1)O<5HHx83`oqSHZ27{)dUVl72kO>KMF@HV+hmmB=aA4v}!a z`A`Vq3N6(Ap0;2tmGDDyp)M8iZP++^^(mAc+=Jdhkj3vFM9LQNT`|bl`SQlXfIG$j z+8TDpScdTzR_I?~|H{NT!8d$Ts1SRqShP@%l>m0|oibuLIzqjZ&@6Wn%1a4Z?|Jwf z*NM`!;U%2jic3>X#HB};KsLO$M6jU|t;a1($9zne@Bq0Uw=6&A18YpBUF8PjT&1|d zfGapno#jVIX;E&^IIOIpgnuO$uE~ROZE+i!7Bl(tLH8e1q1;&X7(1N`oSUha-Hbgm0CD zB2dIo8HV5Y_H`Dk5}&SzR9zZbC?_i{OKC{@5QINjEZ}#gGp3@R<^vsr`|;Ew$#JrU z>5%+nJNfksWa*nEe5tGoi!3L>aO2F@m(A8uERX3G07DY258vXnG2>Tc)M$U!5iJ58 z`hKiK@6zT-*1bP!wy+1w|7A0akkBt~Bx3Vn9G)ECL;Yii-M&!iT=NbrVgwJkSNYJ$ zd(O$sjlwDhmfSR**VYs=uw0o zS7=PZ_MYHxQ__^BeUQJuNcamfVTB^5k`Se*yym2iQE9H~h;#p$ydq4z>ysNy5HOy2 z1K4I%4VANZVk81@lirP@)F)iR$4kAVqMl|QH`)O|#zCmQv?-KwBr!r_Qr;EymC@+; zaS6X;(9!RBJ^h~gvRb$Ma@}@rQmVJDDh{)lo=x|lHxYe3>P>uJdSgE(_2x~xT5q;~ zsjD}y*rnbSrBnq@{#K$&@@~~UQlHWExJ2pVKAttwNJ>o_NqPGn!NHz15Zi&ef{7CT zvK)xzMFV9~0DUs#5yCr2_-(0;P$V5B8m>AlN9p?PcSz><7IOWY$(jhHS(OU{HjJt# zu#-L|wu8}a9BNRX<6?EUSzB3?4W6T9HI?VE7w4Yi1IDTulm@=JP|#PLtZ>6NM5?QV z=SpSgMWM3jN7CC~G?N@C;h)P-pokl;F};S56RW<`V^#VSgGRSQJB zJFxf*ADYU~l<<$F9r2>E3vkZz6ixKJ4liOc0sepT-Jz$__idJ zV{dbfh+|03>4`}05HK^LieNAF;oU9J`qQe8)|nz~VSme5yFJLJLg`VO9yiIf{OMt% z@zjI#SWk}#T6tWZ9*<}R@$dgZOYdr0vdy5f*Kl>Q>3WvRH6MP01pbz#bh|zGtU6j$GnrLgp4Rz< z3)n!an!q~B(!{N@2`ST3xFrB@V z*Ln0I;9a3xnLZ!&{0hxaO`R|FoCAgf;2_LyaznXA26Tvq7bE8j1Nuc85EL1+2jf2M zq3oTS{2lDLHhmwzGYS~*xDvQ?ENq`)hTSnZ9D7mzEbj{#hW%CODg;HaMwBPF9h1P= zab@-GvLY3V57z#*RZzhJtE{{^SaRb#7-91Tj4!!Cu;q~LEs8N>$xR5ET``yzN%{3& zp6Ai`cj9j?tKd*LcZGBqY$*w^!w>)Q$3*>8dL!`H#ViK6Akw6~&|J35d|F>uvS(e3>|Ga3D z#UuZFTk__ABa18lt61{S|KU#jFM89J|3@;_{Qo}FiT@iiUHQKx^MB<3?33Q|zgDIb z|5NA)rc#-%{O3h?GLZjvh;(}TpOH8JH)iPQe@6cKKf+o6uj}Z4hDQH0ob^9LNB=Ya zNB-M?@s|Ie&UNDd#%iShb6xq*izdzW$p7AR^X7k}xjOnkH~;*Pbk_fCI{Kfk(f@R3 z{ZH4?|MdTn|Fe&K=09A_fNP@~ik4zo>kn38>y-s8f?6jqU+?71fgyOfKQ!Rrf={l4 z3p?50C(6yA89uP&->p74$NR-;$h96uL@6UpaE${J(>(gVerb8jzHyqX?5m}@m;GJi z0C({|2&gV`)m8RCr>bSYJJm_{n^Ik6zbw^T*(>iH^FH1;O?9%j&eO4ZQ>v@I@gm<; zk37FLCvTqbn&ZmzFXrT*=bfB*{(<7k^MP~JJnuHgiRZ27xbi$?j<-B_vNz+=y!@TB zet(;SSk|UN&2=dPOAdHH#Urn$rsU1*-YKrUZkv*SUJrNTb-gRDyuO*N=Jmy7Cte>< zcIEZXWN&$`e0{`w{eCssNxzTLg4Q<4uKLZ3Y9yOH#S_2eym@|pwkyw%%+5d0M>z2u zR*^gNeEMuP&&SSo;`yN2t~@u-_Lk>P`rYVoUi$6K|I@Ra_^Xz`?VW?(Op7-70f@v;uZzhQE=?OVt?-|DF+#LW9%OMMdD*CX0SFEmB#)_)Qi7zJvJP0sJCVxloxt!T#+3(HyS`!V4GOC{8OR4>L)^zbGXPf{MDsL{x_m*NLdM z@{@^F6(6XtE#bXnRWwk4gjR)E%b2Yr{pr|78mK>N%y=87plPt)7Y6G)xK2bFv&X#& z^9JqNk74kmo!L4r21XH8cYd(=H%+u(izfBD(mI6&5?)(Q>Oqk;4bOOH#@Z3~d4`VH z*^V1Vku+LXQHiP!rM1~jB>b@)L8l@y369AwoyVeUA6Cb~yFp5+3pm>L*IT02GKn4vzZyD`4wcH6G3m%yySFQRaYA4_BoF5HzmBj9N*_fW?96C z#%onXc&LOshQ^@?gxM}4GkzHSXwQDUX|}|~n5|}poXPJclR>Nkh_)7fTFV4gJ*!1f z7!A~&BiffF+R`4dy+OiV57>@#d%*S~tb8XwK$M?XO$Ud9hw8Bsspx< zzu`DLbQ6B5b9QKnR&*YEckkg;R1Vi5 zs#Seby*yw$PJM_dRGZu;aZ5GT0o$t#{DAEX2F*F5)!)Mdwp-r0ZFhgbwsvUzC_TQS z3C+N%LMA^NP*wvKl$AlkKQ{c(AJQZ*lXcyYr zLj&3xKLkm;NZm9?G?9J|=g1sxB3_pKral-qcRu?$k)ml2dW6zrIt}^{qKBP6y1*W+ z$&O%+KaBR3F4)Bo`%$F7GewZxmNeQ>8{xl8c#za+UbG8})M-6Ge3hp-tK^qwC4bc^ z&S>_|4E_#Yc*IkjcmZqgn&RmAFy3?3_^)o~>~>o#VjEs~#HuYbMV;yRK_lu+=S~7| zRh8-dC16gO&LnN7qdI(*J$@rq-0|GO{}=PY|49i>{69cj(FY{B@}C#AP4LM7poF~n z|8%k||CPyJ@xPM}|BwF0`2XD_4gcSntmc2}WGDVln(WH|!IS@Q_&;luPDJfQ?LMA_ zXk9Cb|GG9wphW<2wTJ2CBqv_mHN4(3N$~oD6R+uL+{x^nh5Vg_Ar4;85U?(4UPr{{ z5x0ly@Vx(7#`8!zmgpPyx0F?Hnxy8ragr0ypHFn<`PGT~JRhayc_m`@V-=Slj?`Hl zw^a4Q)=_zz!RU!jW-xs(!h272H3ME0KGCG@X=%-%(!{*Y;QjE3OBa#EZ zGLdZgPh$r2Ca6U+V}g@NMo(}RNxupIH)c>VANfG?WljeRfttSz3xPz>s*hX<6zzE-P*+?`G$Fao zf1mS(K;>*j?}~*$tR3Ym%PmdCv>?d#H=fpn3xU?r!A+U;=uVGD?4g|4#=3>qZ#!*3 zavEQGADEqbZ9>>N%C1+Ts}py3n1+uPDl^TrGyosRWk{ z9_=bWD*8W^-|jwn$L52N!tGt<9MZzAxh;-Pt*#zPiIXEKyd^l(0q%e4 z?ZLSXKq2*!TQRs(i$$l_8CtTy<{+(8GbgvHzE(OlTuLXM+HYyM?0iUqeTe7J(O8zP z9(nAN?4gv~!q|7rnSI*vty?s{)dq%SQm#1!x1I|QJI$>B6EC<{lE!Mb(CPJ=5`JBd zo4GnCfVEivds>W5T)yLb#_<9HFs0Klut926W0gI+r0T~q6-B@`(a zrfO(N*$2ddsK)g4AgYb^q^KP6N34@1X<-P8agtVSa+}GYNNG*bNUL5dNh=nl6=Uno zrNt&nX7yg(E>icVR{2@s4yzaS%1h8lPbH zfy1V!j*Z5%i!Hxv)T1|S@1bgY`^yVrEu#bQ!kpwbJ=TDZn4&Fy9#qr7 zB7bGN@|jZf0=P-VaDjWvtK=r(Y7}!;gAcpAZW>Pzo5ueLf#EV#=^3EX2@n__n(YTs z3z+D{5_A%Narn&F+BOxC2AIMq!!o!mepY3!ct7|He)(v%e!&t z${+t<%xu|XPTdpB6Kd1hH=(7R0BVhoq48VqcfKjGaEzg0kp(uJr9Nf_aCS{{n|Z6M z(S`TzVbnF9f0oeQDDS$TC}7Q~8oKNLu_2*`Ict>uUH7=dE_Gk{UW;$;?@Z(eAUloD zYR@mc2X(kK>y~5ZTVQUg#n(38Weg41>!MC)6>i_M7^$@4Z@xu(vyx<-4B_?emrP{c zJ;Vo;Uk8$(h+U?|Lj;>@kPy!fMVeEjC39?Ak!DfW}M11*{hD5&Qw+eDJZ7OrP!4GGPXKI!ZT!S zq9VA>kla{9ow3DiC=Qf>UG2W>i0#iFVZrU-m6d%3L-pZnF z`7a4rBvr)0MggwRUR~W4VNYJ;u=4aOfDbUIWf1Ks7CP|eTMHggY@0-3tT${2|93qz z&+5;d<5%Jcx|_|kLR1dN(~P52y5os_Gd#jhz^?E^*xDj4%ta*3lzkv)Rag0HB6gMie#PX^U^_rzMRj@y1Gb@m zRi?)i(CM;knNENC%ya+w1&Z%x*EI=W3=lHRHK1%$&LjLi3IE9;WD7-#FYdgdbR`rw zyIWn)tfAor3qJ=1d(lDgYXbZVQM$AKy!l|EU;~#Ca}v)D2}8_Tg9FT2GoYdpW{Z)| zuI|Bm>OBIK58i}+8$SjooEzaF)shgU7G7PzM@5pjggC9K`^1c0FmNsr%xfZ+(1L36VDK4=!OK0>X4$R#u z&Ux@xiYE{-Ja++O{SDG!xMNd^`It$-`rOU^kI4VWn(-fp{#xYCsF(T)X7l69S6xT= z5eZ)}g+N8(>NBgnZ&#>lfD}xiviV*ig9n{MmZQEghEI*vnYMcb_{mpJ^;aKy{wLvH zTjB_(mP3#phj62WuQdqVsfbs{6`bR4ChlLnMi>W5jDsY`A%wBjw52bPYF$}#%_d@V zs|2huHAP^3W1{9b_xX{hKeE5CA=Hv}!Kvk})-Iw}m`O;YBNUqn7@tW1ux&UEndlr> zt~6ZDG{pAI-FZ`q!|azr0gxq31{Yk#lu*@Cym|mH&IHb- z?hDw<@{1s!+*?n(Kh)14d2yrsaR8QC!N1G~5_Zd1g;49z8l^|H8mNYZ z7nh@KROBLTW!3;X0xJT~XHaEo%~?gi^+6`or$Z->^bt%zfIx)Mvf%B&EK^}GuIVG% zPo=zm(}!5WJP98v^Lk!1UKX{dPd3sP(|!_OQ+`54T$y4W7Z2j`J}U<3+=sW(hrS3A z#D{WEBZ7?5kM|`4(U@lE`To||)bIDe_f4PoMs|Hq%e$8K7VILxAb#b<{Ac8QBZToL zbY*Xk>n(Caa5&VN7$9IZxU)Irp6yK4VHjW!`>bYf!86_){(Bu(S3<%ay+m^ts}2tz{@)8AEBG0t5u;DW!=@K39042Qy;G9@LH(Tinqrjs$E9qod@?x$}cpuZlG4Q3;rgk7yLoB$!*f-s~7w!2EO1A)Jc`O zhmOVte^G~d=B~5g&tPjv|0+R`YqZj@VGkjUKsrgeD$TgOAmNYX!dqVSq`N3OLz6Vc z>Bgi>6247-LPcu5!iy`JUNPg2Y^!_2{715$A%)aaYN-<5LDo-el=sqfr(Kf5bv5z0&h`DV(O|Z?}!Uomx;FdJLBo&fRaq!58pg;DLeB=z3Z@yT> zX%U@Yei1$E|8x`de($TE5}q#MD`adFQ^K)SFbh3E<7hd_NcICpqPCxCOOCi=5bOy1 z={^tj>}O>&9s7w^O=^Mt{B9)sAr0sC<}Qp*AGA-U{2_h&SugF!n2~{1 zoh1&q*ibtQvms+TMq9F@^=^2sRs!6fLW6NeaeCKJVCmJWO-5zg9B&m<-#x2cl}zNN6)QZ9F{tX#P~ zoQD6C@X~7ANXm(~Ln2IJwwxW^32aYsc%ZM?SGLsu31Yr*MdI zmZ?V*5A?iST9=+Uq{rRND5Ix;hMXBK{Zu_OT1HJ$jO{k9a)o*9Y+CvI0bSj}FRpAy zj~eta(BmQp+3C^fXxdx6REXT~3rNfh~V?Il9 zP-#Am5=wKK&W;;T8wau^e7`(94vWMZ>XF4@E(Q*$gP}gW2ks9Le|)H~_?$W~ZGMcgzB{E99sT(;V^d5`IWJYAmwsHmB|m zpgAb0%)*zwTjN8;K_b+>j)VU(J25SgRV7jrahce}R0;1Vn}8zrd6rlP0;Mk_rhaBC zC<>3cjQ1C0OA~m{(o{><_<%Y^hKtxzDG5I-J4H~0!xYAJKRSNoN~Cxzm-j;&ApB(g6lM2XkA-4r-Nc;E=9r*jJPY#jx+r09AZQ2kFl1#5*rNnJm{mMOdPM zwIDeXSc^s-sAKUJhiSuH_2^#eKO#PW%u( zKBGqidX%P2@^VL^U0}xy)0uP_(oYf&x8V@Byy$CQglAl5(L};>0pn*}Bbf5A!ae7R z;lbiy3bD2w6irsIEM?%sf!V<{iweVmHRg!nz?@oQIPjo_pK)!W+i=*UCq1fD7tfa; z4nvWHE5tP)@1B(ziRh`)8Y+op&JoV+mg+ z%@d25r@+-Ub8rfj($W}nR(}r&Y@7}V;9>+gGdfSFBC}D)(ySb=;5-{GEU~-iqjoCS z+Y9(N}iDsBkLI*=TfO zaw_CHczqhD60UYC5!|Ujed=s

    $v^eG2rW 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%0A#i%J6j_WJ%9Qq5b10rre|G=`nFW`* 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

    )EshGHP{9(Kb?KD9gP2UL2$Y{zUSe_vBux- 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 N^ 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

    6@v^oFxaECK`2UKG?dWi#G#Lkd2AD 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 z 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

    $1IzPCKcq?0p(I5+cg+ro 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

    |rwwbfQ*Y_DrjuQu_K9~a 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 QE5Avk65=_J5=bon3$==k6#xJL literal 0 HcmV?d00001 diff --git a/vendor/github.com/pierrec/lz4/fuzz/lz4.go b/vendor/github.com/pierrec/lz4/fuzz/lz4.go new file mode 100644 index 000000000..4b228a140 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/lz4.go @@ -0,0 +1,45 @@ +package lz4 + +import ( + "bytes" + "io/ioutil" + + "github.com/pierrec/lz4" +) + +// lz4.Reader fuzz function +func Fuzz(data []byte) int { + // uncompress some data + d, err := ioutil.ReadAll(lz4.NewReader(bytes.NewReader(data))) + if err != nil { + return 0 + } + + // got valid compressed data + // compress the uncompressed data + // and compare with the original input + buf := bytes.NewBuffer(nil) + zw := lz4.NewWriter(buf) + n, err := zw.Write(d) + if err != nil { + panic(err) + } + if n != len(d) { + panic("short write") + } + err = zw.Close() + if err != nil { + panic(err) + } + + // uncompress the newly compressed data + ud, err := ioutil.ReadAll(lz4.NewReader(buf)) + if err != nil { + panic(err) + } + if bytes.Compare(d, ud) != 0 { + panic("not equal") + } + + return 1 +} diff --git a/vendor/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 b/vendor/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 new file mode 100644 index 000000000..1f1915235 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/suppressions/a596442269a13f32d85889a173f2d36187a768c6 @@ -0,0 +1 @@ +SIGABRT: abort diff --git a/vendor/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 b/vendor/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 new file mode 100644 index 000000000..381c311ec --- /dev/null +++ b/vendor/github.com/pierrec/lz4/fuzz/suppressions/d159e91cdd6fcbee9e37460f96c597b70c590886 @@ -0,0 +1,10 @@ +panic: runtime error: slice bounds out of range [recovered] +io/ioutil.readAll.func1 +github.com/pierrec/lz4.(*Reader).readBlock +github.com/pierrec/lz4.(*Reader).Read +bytes.(*Buffer).ReadFrom +io/ioutil.readAll +io/ioutil.ReadAll +github.com/pierrec/lz4/fuzz.Fuzz +github.com/dvyukov/go-fuzz/go-fuzz-dep.Main +main.main diff --git a/vendor/github.com/pierrec/lz4/lz4.go b/vendor/github.com/pierrec/lz4/lz4.go new file mode 100644 index 000000000..bda675c78 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/lz4.go @@ -0,0 +1,104 @@ +// Package lz4 implements reading and writing lz4 compressed data (a frame), +// as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html, +// using an io.Reader (decompression) and io.Writer (compression). +// It is designed to minimize memory usage while maximizing throughput by being able to +// [de]compress data concurrently. +// +// The Reader and the Writer support concurrent processing provided the supplied buffers are +// large enough (in multiples of BlockMaxSize) and there is no block dependency. +// Reader.WriteTo and Writer.ReadFrom do leverage the concurrency transparently. +// The runtime.GOMAXPROCS() value is used to apply concurrency or not. +// +// Although the block level compression and decompression functions are exposed and are fully compatible +// with the lz4 block format definition, they are low level and should not be used directly. +// For a complete description of an lz4 compressed block, see: +// http://fastcompression.blogspot.fr/2011/05/lz4-explained.html +// +// See https://github.com/Cyan4973/lz4 for the reference C implementation. +package lz4 + +import ( + "hash" + "sync" + + "github.com/pierrec/xxHash/xxHash32" +) + +const ( + // Extension is the LZ4 frame file name extension + Extension = ".lz4" + // Version is the LZ4 frame format version + Version = 1 + + frameMagic = uint32(0x184D2204) + frameSkipMagic = uint32(0x184D2A50) + + // The following constants are used to setup the compression algorithm. + minMatch = 4 // the minimum size of the match sequence size (4 bytes) + winSizeLog = 16 // LZ4 64Kb window size limit + winSize = 1 << winSizeLog + winMask = winSize - 1 // 64Kb window of previous data for dependent blocks + + // hashLog determines the size of the hash table used to quickly find a previous match position. + // Its value influences the compression speed and memory usage, the lower the faster, + // but at the expense of the compression ratio. + // 16 seems to be the best compromise. + hashLog = 16 + hashShift = uint((minMatch * 8) - hashLog) + + mfLimit = 8 + minMatch // The last match cannot start within the last 12 bytes. + skipStrength = 6 // variable step for fast scan + + hasher = uint32(2654435761) // prime number used to hash minMatch +) + +// map the block max size id with its value in bytes: 64Kb, 256Kb, 1Mb and 4Mb. +var bsMapID = map[byte]int{4: 64 << 10, 5: 256 << 10, 6: 1 << 20, 7: 4 << 20} +var bsMapValue = map[int]byte{} + +// Reversed. +func init() { + for i, v := range bsMapID { + bsMapValue[v] = i + } +} + +// Header describes the various flags that can be set on a Writer or obtained from a Reader. +// The default values match those of the LZ4 frame format definition (http://fastcompression.blogspot.com/2013/04/lz4-streaming-format-final.html). +// +// NB. in a Reader, in case of concatenated frames, the Header values may change between Read() calls. +// It is the caller responsibility to check them if necessary (typically when using the Reader concurrency). +type Header struct { + BlockDependency bool // compressed blocks are dependent (one block depends on the last 64Kb of the previous one) + BlockChecksum bool // compressed blocks are checksumed + NoChecksum bool // frame checksum + BlockMaxSize int // the size of the decompressed data block (one of [64KB, 256KB, 1MB, 4MB]). Default=4MB. + Size uint64 // the frame total size. It is _not_ computed by the Writer. + HighCompression bool // use high compression (only for the Writer) + done bool // whether the descriptor was processed (Read or Write and checked) + // Removed as not supported + // Dict bool // a dictionary id is to be used + // DictID uint32 // the dictionary id read from the frame, if any. +} + +// xxhPool wraps the standard pool for xxHash items. +// Putting items back in the pool automatically resets them. +type xxhPool struct { + sync.Pool +} + +func (p *xxhPool) Get() hash.Hash32 { + return p.Pool.Get().(hash.Hash32) +} + +func (p *xxhPool) Put(h hash.Hash32) { + h.Reset() + p.Pool.Put(h) +} + +// hashPool is used by readers and writers and contains xxHash items. +var hashPool = xxhPool{ + Pool: sync.Pool{ + New: func() interface{} { return xxHash32.New(0) }, + }, +} diff --git a/vendor/github.com/pierrec/lz4/lz4c/main.go b/vendor/github.com/pierrec/lz4/lz4c/main.go new file mode 100644 index 000000000..dc0621248 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/lz4c/main.go @@ -0,0 +1,105 @@ +// Command line utility for the lz4 package. +package main + +import ( + // "bytes" + + "flag" + "fmt" + "io" + "log" + "os" + "path" + "runtime" + "strings" + + "github.com/pierrec/lz4" +) + +func main() { + // Process command line arguments + var ( + blockMaxSizeDefault = 4 << 20 + flagStdout = flag.Bool("c", false, "output to stdout") + flagDecompress = flag.Bool("d", false, "decompress flag") + flagBlockMaxSize = flag.Int("B", blockMaxSizeDefault, "block max size [64Kb,256Kb,1Mb,4Mb]") + flagBlockDependency = flag.Bool("BD", false, "enable block dependency") + flagBlockChecksum = flag.Bool("BX", false, "enable block checksum") + flagStreamChecksum = flag.Bool("Sx", false, "disable stream checksum") + flagHighCompression = flag.Bool("9", false, "enabled high compression") + ) + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage:\n\t%s [arg] [input]...\n\tNo input means [de]compress stdin to stdout\n\n", os.Args[0]) + flag.PrintDefaults() + } + flag.Parse() + + // Use all CPUs + runtime.GOMAXPROCS(runtime.NumCPU()) + + zr := lz4.NewReader(nil) + zw := lz4.NewWriter(nil) + zh := lz4.Header{ + BlockDependency: *flagBlockDependency, + BlockChecksum: *flagBlockChecksum, + BlockMaxSize: *flagBlockMaxSize, + NoChecksum: *flagStreamChecksum, + HighCompression: *flagHighCompression, + } + + worker := func(in io.Reader, out io.Writer) { + if *flagDecompress { + zr.Reset(in) + if _, err := io.Copy(out, zr); err != nil { + log.Fatalf("Error while decompressing input: %v", err) + } + } else { + zw.Reset(out) + zw.Header = zh + if _, err := io.Copy(zw, in); err != nil { + log.Fatalf("Error while compressing input: %v", err) + } + } + } + + // No input means [de]compress stdin to stdout + if len(flag.Args()) == 0 { + worker(os.Stdin, os.Stdout) + os.Exit(0) + } + + // Compress or decompress all input files + for _, inputFileName := range flag.Args() { + outputFileName := path.Clean(inputFileName) + + if !*flagStdout { + if *flagDecompress { + outputFileName = strings.TrimSuffix(outputFileName, lz4.Extension) + if outputFileName == inputFileName { + log.Fatalf("Invalid output file name: same as input: %s", inputFileName) + } + } else { + outputFileName += lz4.Extension + } + } + + inputFile, err := os.Open(inputFileName) + if err != nil { + log.Fatalf("Error while opening input: %v", err) + } + + outputFile := os.Stdout + if !*flagStdout { + outputFile, err = os.Create(outputFileName) + if err != nil { + log.Fatalf("Error while opening output: %v", err) + } + } + worker(inputFile, outputFile) + + inputFile.Close() + if !*flagStdout { + outputFile.Close() + } + } +} diff --git a/vendor/github.com/pierrec/lz4/reader.go b/vendor/github.com/pierrec/lz4/reader.go new file mode 100644 index 000000000..9f7fd6042 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/reader.go @@ -0,0 +1,364 @@ +package lz4 + +import ( + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" + "runtime" + "sync" + "sync/atomic" +) + +// ErrInvalid is returned when the data being read is not an LZ4 archive +// (LZ4 magic number detection failed). +var ErrInvalid = errors.New("invalid lz4 data") + +// errEndOfBlock is returned by readBlock when it has reached the last block of the frame. +// It is not an error. +var errEndOfBlock = errors.New("end of block") + +// Reader implements the LZ4 frame decoder. +// The Header is set after the first call to Read(). +// The Header may change between Read() calls in case of concatenated frames. +type Reader struct { + Pos int64 // position within the source + Header + src io.Reader + checksum hash.Hash32 // frame hash + wg sync.WaitGroup // decompressing go routine wait group + data []byte // buffered decompressed data + window []byte // 64Kb decompressed data window +} + +// NewReader returns a new LZ4 frame decoder. +// No access to the underlying io.Reader is performed. +func NewReader(src io.Reader) *Reader { + return &Reader{ + src: src, + checksum: hashPool.Get(), + } +} + +// readHeader checks the frame magic number and parses the frame descriptoz. +// Skippable frames are supported even as a first frame although the LZ4 +// specifications recommends skippable frames not to be used as first frames. +func (z *Reader) readHeader(first bool) error { + defer z.checksum.Reset() + + for { + var magic uint32 + if err := binary.Read(z.src, binary.LittleEndian, &magic); err != nil { + if !first && err == io.ErrUnexpectedEOF { + return io.EOF + } + return err + } + z.Pos += 4 + if magic>>8 == frameSkipMagic>>8 { + var skipSize uint32 + if err := binary.Read(z.src, binary.LittleEndian, &skipSize); err != nil { + return err + } + z.Pos += 4 + m, err := io.CopyN(ioutil.Discard, z.src, int64(skipSize)) + z.Pos += m + if err != nil { + return err + } + continue + } + if magic != frameMagic { + return ErrInvalid + } + break + } + + // header + var buf [8]byte + if _, err := io.ReadFull(z.src, buf[:2]); err != nil { + return err + } + z.Pos += 2 + + b := buf[0] + if b>>6 != Version { + return fmt.Errorf("lz4.Read: invalid version: got %d expected %d", b>>6, Version) + } + z.BlockDependency = b>>5&1 == 0 + z.BlockChecksum = b>>4&1 > 0 + frameSize := b>>3&1 > 0 + z.NoChecksum = b>>2&1 == 0 + // z.Dict = b&1 > 0 + + bmsID := buf[1] >> 4 & 0x7 + bSize, ok := bsMapID[bmsID] + if !ok { + return fmt.Errorf("lz4.Read: invalid block max size: %d", bmsID) + } + z.BlockMaxSize = bSize + + z.checksum.Write(buf[0:2]) + + if frameSize { + if err := binary.Read(z.src, binary.LittleEndian, &z.Size); err != nil { + return err + } + z.Pos += 8 + binary.LittleEndian.PutUint64(buf[:], z.Size) + z.checksum.Write(buf[0:8]) + } + + // if z.Dict { + // if err := binary.Read(z.src, binary.LittleEndian, &z.DictID); err != nil { + // return err + // } + // z.Pos += 4 + // binary.LittleEndian.PutUint32(buf[:], z.DictID) + // z.checksum.Write(buf[0:4]) + // } + + // header checksum + if _, err := io.ReadFull(z.src, buf[:1]); err != nil { + return err + } + z.Pos++ + if h := byte(z.checksum.Sum32() >> 8 & 0xFF); h != buf[0] { + return fmt.Errorf("lz4.Read: invalid header checksum: got %v expected %v", buf[0], h) + } + + z.Header.done = true + + return nil +} + +// Read decompresses data from the underlying source into the supplied buffer. +// +// Since there can be multiple streams concatenated, Header values may +// change between calls to Read(). If that is the case, no data is actually read from +// the underlying io.Reader, to allow for potential input buffer resizing. +// +// Data is buffered if the input buffer is too small, and exhausted upon successive calls. +// +// If the buffer is large enough (typically in multiples of BlockMaxSize) and there is +// no block dependency, then the data will be decompressed concurrently based on the GOMAXPROCS value. +func (z *Reader) Read(buf []byte) (n int, err error) { + if !z.Header.done { + if err = z.readHeader(true); err != nil { + return + } + } + + if len(buf) == 0 { + return + } + + // exhaust remaining data from previous Read() + if len(z.data) > 0 { + n = copy(buf, z.data) + z.data = z.data[n:] + if len(z.data) == 0 { + z.data = nil + } + return + } + + // Break up the input buffer into BlockMaxSize blocks with at least one block. + // Then decompress into each of them concurrently if possible (no dependency). + // In case of dependency, the first block will be missing the window (except on the + // very first call), the rest will have it already since it comes from the previous block. + wbuf := buf + zn := (len(wbuf) + z.BlockMaxSize - 1) / z.BlockMaxSize + zblocks := make([]block, zn) + for zi, abort := 0, uint32(0); zi < zn && atomic.LoadUint32(&abort) == 0; zi++ { + zb := &zblocks[zi] + // last block may be too small + if len(wbuf) < z.BlockMaxSize+len(z.window) { + wbuf = make([]byte, z.BlockMaxSize+len(z.window)) + } + copy(wbuf, z.window) + if zb.err = z.readBlock(wbuf, zb); zb.err != nil { + break + } + wbuf = wbuf[z.BlockMaxSize:] + if !z.BlockDependency { + z.wg.Add(1) + go z.decompressBlock(zb, &abort) + continue + } + // cannot decompress concurrently when dealing with block dependency + z.decompressBlock(zb, nil) + // the last block may not contain enough data + if len(z.window) == 0 { + z.window = make([]byte, winSize) + } + if len(zb.data) >= winSize { + copy(z.window, zb.data[len(zb.data)-winSize:]) + } else { + copy(z.window, z.window[len(zb.data):]) + copy(z.window[len(zb.data)+1:], zb.data) + } + } + z.wg.Wait() + + // since a block size may be less then BlockMaxSize, trim the decompressed buffers + for _, zb := range zblocks { + if zb.err != nil { + if zb.err == errEndOfBlock { + return n, z.close() + } + return n, zb.err + } + bLen := len(zb.data) + if !z.NoChecksum { + z.checksum.Write(zb.data) + } + m := copy(buf[n:], zb.data) + // buffer the remaining data (this is necessarily the last block) + if m < bLen { + z.data = zb.data[m:] + } + n += m + } + + return +} + +// readBlock reads an entire frame block from the frame. +// The input buffer is the one that will receive the decompressed data. +// If the end of the frame is detected, it returns the errEndOfBlock error. +func (z *Reader) readBlock(buf []byte, b *block) error { + var bLen uint32 + if err := binary.Read(z.src, binary.LittleEndian, &bLen); err != nil { + return err + } + atomic.AddInt64(&z.Pos, 4) + + switch { + case bLen == 0: + return errEndOfBlock + case bLen&(1<<31) == 0: + b.compressed = true + b.data = buf + b.zdata = make([]byte, bLen) + default: + bLen = bLen & (1<<31 - 1) + if int(bLen) > len(buf) { + return fmt.Errorf("lz4.Read: invalid block size: %d", bLen) + } + b.data = buf[:bLen] + b.zdata = buf[:bLen] + } + if _, err := io.ReadFull(z.src, b.zdata); err != nil { + return err + } + + if z.BlockChecksum { + if err := binary.Read(z.src, binary.LittleEndian, &b.checksum); err != nil { + return err + } + xxh := hashPool.Get() + defer hashPool.Put(xxh) + xxh.Write(b.zdata) + if h := xxh.Sum32(); h != b.checksum { + return fmt.Errorf("lz4.Read: invalid block checksum: got %x expected %x", h, b.checksum) + } + } + + return nil +} + +// decompressBlock decompresses a frame block. +// In case of an error, the block err is set with it and abort is set to 1. +func (z *Reader) decompressBlock(b *block, abort *uint32) { + if abort != nil { + defer z.wg.Done() + } + if b.compressed { + n := len(z.window) + m, err := UncompressBlock(b.zdata, b.data, n) + if err != nil { + if abort != nil { + atomic.StoreUint32(abort, 1) + } + b.err = err + return + } + b.data = b.data[n : n+m] + } + atomic.AddInt64(&z.Pos, int64(len(b.data))) +} + +// close validates the frame checksum (if any) and checks the next frame (if any). +func (z *Reader) close() error { + if !z.NoChecksum { + var checksum uint32 + if err := binary.Read(z.src, binary.LittleEndian, &checksum); err != nil { + return err + } + if checksum != z.checksum.Sum32() { + return fmt.Errorf("lz4.Read: invalid frame checksum: got %x expected %x", z.checksum.Sum32(), checksum) + } + } + + // get ready for the next concatenated frame, but do not change the position + pos := z.Pos + z.Reset(z.src) + z.Pos = pos + + // since multiple frames can be concatenated, check for another one + return z.readHeader(false) +} + +// Reset discards the Reader's state and makes it equivalent to the +// result of its original state from NewReader, but reading from r instead. +// This permits reusing a Reader rather than allocating a new one. +func (z *Reader) Reset(r io.Reader) { + z.Header = Header{} + z.Pos = 0 + z.src = r + z.checksum.Reset() + z.data = nil + z.window = nil +} + +// WriteTo decompresses the data from the underlying io.Reader and writes it to the io.Writer. +// Returns the number of bytes written. +func (z *Reader) WriteTo(w io.Writer) (n int64, err error) { + cpus := runtime.GOMAXPROCS(0) + var buf []byte + + // The initial buffer being nil, the first Read will be only read the compressed frame options. + // The buffer can then be sized appropriately to support maximum concurrency decompression. + // If multiple frames are concatenated, Read() will return with no data decompressed but with + // potentially changed options. The buffer will be resized accordingly, always trying to + // maximize concurrency. + for { + nsize := 0 + // the block max size can change if multiple streams are concatenated. + // Check it after every Read(). + if z.BlockDependency { + // in case of dependency, we cannot decompress concurrently, + // so allocate the minimum buffer + window size + nsize = len(z.window) + z.BlockMaxSize + } else { + // if no dependency, allocate a buffer large enough for concurrent decompression + nsize = cpus * z.BlockMaxSize + } + if nsize != len(buf) { + buf = make([]byte, nsize) + } + + m, er := z.Read(buf) + if er != nil && er != io.EOF { + return n, er + } + m, err = w.Write(buf[:m]) + n += int64(m) + if err != nil || er == io.EOF { + return + } + } +} diff --git a/vendor/github.com/pierrec/lz4/writer.go b/vendor/github.com/pierrec/lz4/writer.go new file mode 100644 index 000000000..d400c6a73 --- /dev/null +++ b/vendor/github.com/pierrec/lz4/writer.go @@ -0,0 +1,370 @@ +package lz4 + +import ( + "encoding/binary" + "fmt" + "hash" + "io" + "runtime" + "sync" +) + +// Writer implements the LZ4 frame encoder. +type Writer struct { + Header + dst io.Writer + checksum hash.Hash32 // frame checksum + wg sync.WaitGroup // decompressing go routine wait group + data []byte // data to be compressed, only used when dealing with block dependency as we need 64Kb to work with + window []byte // last 64KB of decompressed data (block dependency) + blockMaxSize buffer +} + +// NewWriter returns a new LZ4 frame encoder. +// No access to the underlying io.Writer is performed. +// The supplied Header is checked at the first Write. +// It is ok to change it before the first Write but then not until a Reset() is performed. +func NewWriter(dst io.Writer) *Writer { + return &Writer{ + dst: dst, + checksum: hashPool.Get(), + Header: Header{ + BlockMaxSize: 4 << 20, + }, + } +} + +// writeHeader builds and writes the header (magic+header) to the underlying io.Writer. +func (z *Writer) writeHeader() error { + // Default to 4Mb if BlockMaxSize is not set + if z.Header.BlockMaxSize == 0 { + z.Header.BlockMaxSize = 4 << 20 + } + // the only option that need to be validated + bSize, ok := bsMapValue[z.Header.BlockMaxSize] + if !ok { + return fmt.Errorf("lz4: invalid block max size: %d", z.Header.BlockMaxSize) + } + + // magic number(4) + header(flags(2)+[Size(8)+DictID(4)]+checksum(1)) does not exceed 19 bytes + // Size and DictID are optional + var buf [19]byte + + // set the fixed size data: magic number, block max size and flags + binary.LittleEndian.PutUint32(buf[0:], frameMagic) + flg := byte(Version << 6) + if !z.Header.BlockDependency { + flg |= 1 << 5 + } + if z.Header.BlockChecksum { + flg |= 1 << 4 + } + if z.Header.Size > 0 { + flg |= 1 << 3 + } + if !z.Header.NoChecksum { + flg |= 1 << 2 + } + // if z.Header.Dict { + // flg |= 1 + // } + buf[4] = flg + buf[5] = bSize << 4 + + // current buffer size: magic(4) + flags(1) + block max size (1) + n := 6 + // optional items + if z.Header.Size > 0 { + binary.LittleEndian.PutUint64(buf[n:], z.Header.Size) + n += 8 + } + // if z.Header.Dict { + // binary.LittleEndian.PutUint32(buf[n:], z.Header.DictID) + // n += 4 + // } + + // header checksum includes the flags, block max size and optional Size and DictID + z.checksum.Write(buf[4:n]) + buf[n] = byte(z.checksum.Sum32() >> 8 & 0xFF) + z.checksum.Reset() + + // header ready, write it out + if _, err := z.dst.Write(buf[0 : n+1]); err != nil { + return err + } + z.Header.done = true + + return nil +} + +// Write compresses data from the supplied buffer into the underlying io.Writer. +// Write does not return until the data has been written. +// +// If the input buffer is large enough (typically in multiples of BlockMaxSize) +// the data will be compressed concurrently. +// +// Write never buffers any data unless in BlockDependency mode where it may +// do so until it has 64Kb of data, after which it never buffers any. +func (z *Writer) Write(buf []byte) (n int, err error) { + if !z.Header.done { + if err = z.writeHeader(); err != nil { + return + } + } + + if len(buf) == 0 { + return + } + + if !z.NoChecksum { + z.wg.Add(1) + go func(b []byte) { + z.checksum.Write(b) + z.wg.Done() + }(buf) + } + + // with block dependency, require at least 64Kb of data to work with + // not having 64Kb only matters initially to setup the first window + bl := 0 + if z.BlockDependency && len(z.window) == 0 { + bl = len(z.data) + z.data = append(z.data, buf...) + if len(z.data) < winSize { + z.wg.Wait() + return len(buf), nil + } + buf = z.data + z.data = nil + } + + // Break up the input buffer into BlockMaxSize blocks, provisioning the left over block. + // Then compress into each of them concurrently if possible (no dependency). + wbuf := buf + zn := len(wbuf) / z.BlockMaxSize + zblocks := make([]block, zn, zn+1) + for zi := 0; zi < zn; zi++ { + zb := &zblocks[zi] + if z.BlockDependency { + if zi == 0 { + // first block does not have the window + zb.data = append(z.window, wbuf[:z.BlockMaxSize]...) + zb.offset = len(z.window) + wbuf = wbuf[z.BlockMaxSize-winSize:] + } else { + // set the uncompressed data including the window from previous block + zb.data = wbuf[:z.BlockMaxSize+winSize] + zb.offset = winSize + wbuf = wbuf[z.BlockMaxSize:] + } + } else { + zb.data = wbuf[:z.BlockMaxSize] + wbuf = wbuf[z.BlockMaxSize:] + } + + z.wg.Add(1) + go z.compressBlock(zb) + } + + // left over + if len(buf)%z.BlockMaxSize > 0 { + zblocks = append(zblocks, block{data: wbuf}) + zb := &zblocks[zn] + if z.BlockDependency { + if zn == 0 { + zb.data = append(z.window, zb.data...) + zb.offset = len(z.window) + } else { + zb.offset = winSize + } + } + z.wg.Add(1) + go z.compressBlock(zb) + } + z.wg.Wait() + + // outputs the compressed data + for zi, zb := range zblocks { + _, err = z.writeBlock(&zb) + + written := len(zb.data) + if bl > 0 { + if written >= bl { + written -= bl + bl = 0 + } else { + bl -= written + written = 0 + } + } + + n += written + // remove the window in zb.data + if z.BlockDependency { + if zi == 0 { + n -= len(z.window) + } else { + n -= winSize + } + } + if err != nil { + return + } + } + + if z.BlockDependency { + if len(z.window) == 0 { + z.window = make([]byte, winSize) + } + // last buffer may be shorter than the window + if len(buf) >= winSize { + copy(z.window, buf[len(buf)-winSize:]) + } else { + copy(z.window, z.window[len(buf):]) + copy(z.window[len(buf)+1:], buf) + } + } + + return +} + +// compressBlock compresses a block. +func (z *Writer) compressBlock(zb *block) { + // compressed block size cannot exceed the input's + zbuf := make([]byte, len(zb.data)-zb.offset) + var ( + n int + err error + ) + if z.HighCompression { + n, err = CompressBlockHC(zb.data, zbuf, zb.offset) + } else { + n, err = CompressBlock(zb.data, zbuf, zb.offset) + } + + // compressible and compressed size smaller than decompressed: ok! + if err == nil && n > 0 && len(zb.zdata) < len(zb.data) { + zb.compressed = true + zb.zdata = zbuf[:n] + } else { + zb.zdata = zb.data[zb.offset:] + } + + if z.BlockChecksum { + xxh := hashPool.Get() + xxh.Write(zb.zdata) + zb.checksum = xxh.Sum32() + hashPool.Put(xxh) + } + + z.wg.Done() +} + +// writeBlock writes a frame block to the underlying io.Writer (size, data). +func (z *Writer) writeBlock(zb *block) (int, error) { + bLen := uint32(len(zb.zdata)) + if !zb.compressed { + bLen |= 1 << 31 + } + + n := 0 + if err := binary.Write(z.dst, binary.LittleEndian, bLen); err != nil { + return n, err + } + n += 4 + + m, err := z.dst.Write(zb.zdata) + n += m + if err != nil { + return n, err + } + + if z.BlockChecksum { + if err := binary.Write(z.dst, binary.LittleEndian, zb.checksum); err != nil { + return n, err + } + n += 4 + } + + return n, nil +} + +// Flush flushes any pending compressed data to the underlying writer. +// Flush does not return until the data has been written. +// If the underlying writer returns an error, Flush returns that error. +// +// Flush is only required when in BlockDependency mode and the total of +// data written is less than 64Kb. +func (z *Writer) Flush() error { + if len(z.data) == 0 { + return nil + } + zb := block{data: z.data} + z.wg.Add(1) + z.compressBlock(&zb) + if _, err := z.writeBlock(&zb); err != nil { + return err + } + return nil +} + +// Close closes the Writer, flushing any unwritten data to the underlying io.Writer, but does not close the underlying io.Writer. +func (z *Writer) Close() error { + if !z.Header.done { + if err := z.writeHeader(); err != nil { + return err + } + } + + // buffered data for the block dependency window + if z.BlockDependency && len(z.data) > 0 { + zb := block{data: z.data} + z.wg.Add(1) + z.compressBlock(&zb) + if _, err := z.writeBlock(&zb); err != nil { + return err + } + } + + if err := binary.Write(z.dst, binary.LittleEndian, uint32(0)); err != nil { + return err + } + if !z.NoChecksum { + if err := binary.Write(z.dst, binary.LittleEndian, z.checksum.Sum32()); err != nil { + return err + } + } + return nil +} + +// Reset clears the state of the Writer z such that it is equivalent to its +// initial state from NewWriter, but instead writing to w. +// No access to the underlying io.Writer is performed. +func (z *Writer) Reset(w io.Writer) { + z.Header = Header{} + z.dst = w + z.checksum.Reset() + z.data = nil + z.window = nil +} + +// ReadFrom compresses the data read from the io.Reader and writes it to the underlying io.Writer. +// Returns the number of bytes read. +// It does not close the Writer. +func (z *Writer) ReadFrom(r io.Reader) (n int64, err error) { + cpus := runtime.GOMAXPROCS(0) + buf := make([]byte, cpus*z.BlockMaxSize) + for { + m, er := io.ReadFull(r, buf) + n += int64(m) + if er == nil || er == io.ErrUnexpectedEOF || er == io.EOF { + if _, err = z.Write(buf[:m]); err != nil { + return + } + if er == nil { + continue + } + return + } + return n, er + } +} diff --git a/vendor/github.com/pierrec/xxHash/LICENSE b/vendor/github.com/pierrec/xxHash/LICENSE new file mode 100644 index 000000000..c1418f3f6 --- /dev/null +++ b/vendor/github.com/pierrec/xxHash/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2014, Pierre Curto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of xxHash nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/pierrec/xxHash/xxHash32/xxHash32.go b/vendor/github.com/pierrec/xxHash/xxHash32/xxHash32.go new file mode 100644 index 000000000..411504e4b --- /dev/null +++ b/vendor/github.com/pierrec/xxHash/xxHash32/xxHash32.go @@ -0,0 +1,205 @@ +// Package xxHash32 implements the very fast xxHash hashing algorithm (32 bits version). +// (https://github.com/Cyan4973/xxHash/) +package xxHash32 + +import "hash" + +const ( + prime32_1 = 2654435761 + prime32_2 = 2246822519 + prime32_3 = 3266489917 + prime32_4 = 668265263 + prime32_5 = 374761393 +) + +type xxHash struct { + seed uint32 + v1 uint32 + v2 uint32 + v3 uint32 + v4 uint32 + totalLen uint64 + buf [16]byte + bufused int +} + +// New returns a new Hash32 instance. +func New(seed uint32) hash.Hash32 { + xxh := &xxHash{seed: seed} + xxh.Reset() + return xxh +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (xxh xxHash) Sum(b []byte) []byte { + h32 := xxh.Sum32() + return append(b, byte(h32), byte(h32>>8), byte(h32>>16), byte(h32>>24)) +} + +// Reset resets the Hash to its initial state. +func (xxh *xxHash) Reset() { + xxh.v1 = xxh.seed + prime32_1 + prime32_2 + xxh.v2 = xxh.seed + prime32_2 + xxh.v3 = xxh.seed + xxh.v4 = xxh.seed - prime32_1 + xxh.totalLen = 0 + xxh.bufused = 0 +} + +// Size returns the number of bytes returned by Sum(). +func (xxh *xxHash) Size() int { + return 4 +} + +// BlockSize gives the minimum number of bytes accepted by Write(). +func (xxh *xxHash) BlockSize() int { + return 1 +} + +// Write adds input bytes to the Hash. +// It never returns an error. +func (xxh *xxHash) Write(input []byte) (int, error) { + n := len(input) + m := xxh.bufused + + xxh.totalLen += uint64(n) + + r := len(xxh.buf) - m + if n < r { + copy(xxh.buf[m:], input) + xxh.bufused += len(input) + return n, nil + } + + p := 0 + if m > 0 { + // some data left from previous update + copy(xxh.buf[xxh.bufused:], input[:r]) + xxh.bufused += len(input) - r + + // fast rotl(13) + p32 := xxh.v1 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v1 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v2 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v2 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v3 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v3 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v4 + (uint32(xxh.buf[p+3])<<24|uint32(xxh.buf[p+2])<<16|uint32(xxh.buf[p+1])<<8|uint32(xxh.buf[p]))*prime32_2 + xxh.v4 = (p32<<13 | p32>>19) * prime32_1 + + p = r + xxh.bufused = 0 + } + + for n := n - 16; p <= n; { + p32 := xxh.v1 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v1 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v2 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v2 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v3 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v3 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + p32 = xxh.v4 + (uint32(input[p+3])<<24|uint32(input[p+2])<<16|uint32(input[p+1])<<8|uint32(input[p]))*prime32_2 + xxh.v4 = (p32<<13 | p32>>19) * prime32_1 + p += 4 + } + + copy(xxh.buf[xxh.bufused:], input[p:]) + xxh.bufused += len(input) - p + + return n, nil +} + +// Sum32 returns the 32 bits Hash value. +func (xxh *xxHash) Sum32() uint32 { + h32 := uint32(xxh.totalLen) + if xxh.totalLen >= 16 { + h32 += ((xxh.v1 << 1) | (xxh.v1 >> 31)) + + ((xxh.v2 << 7) | (xxh.v2 >> 25)) + + ((xxh.v3 << 12) | (xxh.v3 >> 20)) + + ((xxh.v4 << 18) | (xxh.v4 >> 14)) + } else { + h32 += xxh.seed + prime32_5 + } + + p := 0 + n := xxh.bufused + for n := n - 4; p <= n; p += 4 { + h32 += (uint32(xxh.buf[p+3])<<24 | uint32(xxh.buf[p+2])<<16 | uint32(xxh.buf[p+1])<<8 | uint32(xxh.buf[p])) * prime32_3 + h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4 + } + for ; p < n; p++ { + h32 += uint32(xxh.buf[p]) * prime32_5 + h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1 + } + + h32 ^= h32 >> 15 + h32 *= prime32_2 + h32 ^= h32 >> 13 + h32 *= prime32_3 + h32 ^= h32 >> 16 + + return h32 +} + +// Checksum returns the 32bits Hash value. +func Checksum(input []byte, seed uint32) uint32 { + n := len(input) + h32 := uint32(n) + + if n < 16 { + h32 += seed + prime32_5 + } else { + v1 := seed + prime32_1 + prime32_2 + v2 := seed + prime32_2 + v3 := seed + v4 := seed - prime32_1 + p := 0 + for p <= n-16 { + v1 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v1 = (v1<<13 | v1>>19) * prime32_1 + p += 4 + v2 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v2 = (v2<<13 | v2>>19) * prime32_1 + p += 4 + v3 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v3 = (v3<<13 | v3>>19) * prime32_1 + p += 4 + v4 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_2 + v4 = (v4<<13 | v4>>19) * prime32_1 + p += 4 + } + input = input[p:] + n -= p + h32 += ((v1 << 1) | (v1 >> 31)) + + ((v2 << 7) | (v2 >> 25)) + + ((v3 << 12) | (v3 >> 20)) + + ((v4 << 18) | (v4 >> 14)) + } + + p := 0 + for p <= n-4 { + h32 += (uint32(input[p+3])<<24 | uint32(input[p+2])<<16 | uint32(input[p+1])<<8 | uint32(input[p])) * prime32_3 + h32 = ((h32 << 17) | (h32 >> 15)) * prime32_4 + p += 4 + } + for p < n { + h32 += uint32(input[p]) * prime32_5 + h32 = ((h32 << 11) | (h32 >> 21)) * prime32_1 + p++ + } + + h32 ^= h32 >> 15 + h32 *= prime32_2 + h32 ^= h32 >> 13 + h32 *= prime32_3 + h32 ^= h32 >> 16 + + return h32 +} diff --git a/vendor/github.com/pkg/sftp/.gitignore b/vendor/github.com/pkg/sftp/.gitignore new file mode 100644 index 000000000..9fc1e3d24 --- /dev/null +++ b/vendor/github.com/pkg/sftp/.gitignore @@ -0,0 +1,8 @@ +.*.swo +.*.swp + +server_standalone/server_standalone + +examples/sftp-server/id_rsa +examples/sftp-server/id_rsa.pub +examples/sftp-server/sftp-server diff --git a/vendor/github.com/pkg/sftp/.travis.yml b/vendor/github.com/pkg/sftp/.travis.yml new file mode 100644 index 000000000..9ef70d869 --- /dev/null +++ b/vendor/github.com/pkg/sftp/.travis.yml @@ -0,0 +1,21 @@ +language: go +go_import_path: github.com/pkg/sftp +go: + - 1.5.2 + - 1.4.3 + - tip + +sudo: false + +addons: + ssh_known_hosts: + - bitbucket.org + +install: + - go get -t -v ./... + - ssh-keygen -t rsa -q -P "" -f /home/travis/.ssh/id_rsa + +script: + - go test -integration -v ./... + - go test -testserver -v ./... + - go test -integration -testserver -v ./... diff --git a/vendor/github.com/pkg/sftp/CONTRIBUTORS b/vendor/github.com/pkg/sftp/CONTRIBUTORS new file mode 100644 index 000000000..7eff82364 --- /dev/null +++ b/vendor/github.com/pkg/sftp/CONTRIBUTORS @@ -0,0 +1,2 @@ +Dave Cheney +Saulius Gurklys diff --git a/vendor/github.com/pkg/sftp/LICENSE b/vendor/github.com/pkg/sftp/LICENSE new file mode 100644 index 000000000..b7b53921e --- /dev/null +++ b/vendor/github.com/pkg/sftp/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) 2013, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/sftp/README.md b/vendor/github.com/pkg/sftp/README.md new file mode 100644 index 000000000..875bf2747 --- /dev/null +++ b/vendor/github.com/pkg/sftp/README.md @@ -0,0 +1,29 @@ +sftp +---- + +The `sftp` package provides support for file system operations on remote ssh servers using the SFTP subsystem. + +[![UNIX Build Status](https://travis-ci.org/pkg/sftp.svg?branch=master)](https://travis-ci.org/pkg/sftp) [![GoDoc](http://godoc.org/github.com/pkg/sftp?status.svg)](http://godoc.org/github.com/pkg/sftp) + +usage and examples +------------------ + +See [godoc.org/github.com/pkg/sftp](http://godoc.org/github.com/pkg/sftp) for examples and usage. + +The basic operation of the package mirrors the facilities of the [os](http://golang.org/pkg/os) package. + +The Walker interface for directory traversal is heavily inspired by Keith Rarick's [fs](http://godoc.org/github.com/kr/fs) package. + +roadmap +------- + + * Currently all traffic with the server is serialized, this can be improved by allowing overlapping requests/responses. + * There is way too much duplication in the Client methods. If there was an unmarshal(interface{}) method this would reduce a heap of the duplication. + * Implement integration tests by talking directly to a real opensftp-server process. This shouldn't be too difficult to implement with a small refactoring to the sftp.NewClient method. These tests should be gated on an -sftp.integration test flag. _in progress_ + +contributing +------------ + +We welcome pull requests, bug fixes and issue reports. + +Before proposing a large change, first please discuss your change by raising an issue. diff --git a/vendor/github.com/pkg/sftp/attrs.go b/vendor/github.com/pkg/sftp/attrs.go new file mode 100644 index 000000000..3e4c2912d --- /dev/null +++ b/vendor/github.com/pkg/sftp/attrs.go @@ -0,0 +1,237 @@ +package sftp + +// ssh_FXP_ATTRS support +// see http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5 + +import ( + "os" + "syscall" + "time" +) + +const ( + ssh_FILEXFER_ATTR_SIZE = 0x00000001 + ssh_FILEXFER_ATTR_UIDGID = 0x00000002 + ssh_FILEXFER_ATTR_PERMISSIONS = 0x00000004 + ssh_FILEXFER_ATTR_ACMODTIME = 0x00000008 + ssh_FILEXFER_ATTR_EXTENDED = 0x80000000 +) + +// fileInfo is an artificial type designed to satisfy os.FileInfo. +type fileInfo struct { + name string + size int64 + mode os.FileMode + mtime time.Time + sys interface{} +} + +// Name returns the base name of the file. +func (fi *fileInfo) Name() string { return fi.name } + +// Size returns the length in bytes for regular files; system-dependent for others. +func (fi *fileInfo) Size() int64 { return fi.size } + +// Mode returns file mode bits. +func (fi *fileInfo) Mode() os.FileMode { return fi.mode } + +// ModTime returns the last modification time of the file. +func (fi *fileInfo) ModTime() time.Time { return fi.mtime } + +// IsDir returns true if the file is a directory. +func (fi *fileInfo) IsDir() bool { return fi.Mode().IsDir() } + +func (fi *fileInfo) Sys() interface{} { return fi.sys } + +// FileStat holds the original unmarshalled values from a call to READDIR or *STAT. +// It is exported for the purposes of accessing the raw values via os.FileInfo.Sys() +type FileStat struct { + Size uint64 + Mode uint32 + Mtime uint32 + Atime uint32 + UID uint32 + GID uint32 + Extended []StatExtended +} + +// StatExtended contains additional, extended information for a FileStat. +type StatExtended struct { + ExtType string + ExtData string +} + +func fileInfoFromStat(st *FileStat, name string) os.FileInfo { + fs := &fileInfo{ + name: name, + size: int64(st.Size), + mode: toFileMode(st.Mode), + mtime: time.Unix(int64(st.Mtime), 0), + sys: st, + } + return fs +} + +func fileStatFromInfo(fi os.FileInfo) (uint32, FileStat) { + mtime := fi.ModTime().Unix() + atime := mtime + var flags uint32 = ssh_FILEXFER_ATTR_SIZE | + ssh_FILEXFER_ATTR_PERMISSIONS | + ssh_FILEXFER_ATTR_ACMODTIME + + fileStat := FileStat{ + Size: uint64(fi.Size()), + Mode: fromFileMode(fi.Mode()), + Mtime: uint32(mtime), + Atime: uint32(atime), + } + + // os specific file stat decoding + fileStatFromInfoOs(fi, &flags, &fileStat) + + return flags, fileStat +} + +func unmarshalAttrs(b []byte) (*FileStat, []byte) { + flags, b := unmarshalUint32(b) + var fs FileStat + if flags&ssh_FILEXFER_ATTR_SIZE == ssh_FILEXFER_ATTR_SIZE { + fs.Size, b = unmarshalUint64(b) + } + if flags&ssh_FILEXFER_ATTR_UIDGID == ssh_FILEXFER_ATTR_UIDGID { + fs.UID, b = unmarshalUint32(b) + } + if flags&ssh_FILEXFER_ATTR_UIDGID == ssh_FILEXFER_ATTR_UIDGID { + fs.GID, b = unmarshalUint32(b) + } + if flags&ssh_FILEXFER_ATTR_PERMISSIONS == ssh_FILEXFER_ATTR_PERMISSIONS { + fs.Mode, b = unmarshalUint32(b) + } + if flags&ssh_FILEXFER_ATTR_ACMODTIME == ssh_FILEXFER_ATTR_ACMODTIME { + fs.Atime, b = unmarshalUint32(b) + fs.Mtime, b = unmarshalUint32(b) + } + if flags&ssh_FILEXFER_ATTR_EXTENDED == ssh_FILEXFER_ATTR_EXTENDED { + var count uint32 + count, b = unmarshalUint32(b) + ext := make([]StatExtended, count, count) + for i := uint32(0); i < count; i++ { + var typ string + var data string + typ, b = unmarshalString(b) + data, b = unmarshalString(b) + ext[i] = StatExtended{typ, data} + } + fs.Extended = ext + } + return &fs, b +} + +func marshalFileInfo(b []byte, fi os.FileInfo) []byte { + // attributes variable struct, and also variable per protocol version + // spec version 3 attributes: + // uint32 flags + // uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE + // uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID + // uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID + // uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS + // uint32 atime present only if flag SSH_FILEXFER_ACMODTIME + // uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME + // uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED + // string extended_type + // string extended_data + // ... more extended data (extended_type - extended_data pairs), + // so that number of pairs equals extended_count + + flags, fileStat := fileStatFromInfo(fi) + + b = marshalUint32(b, flags) + if flags&ssh_FILEXFER_ATTR_SIZE != 0 { + b = marshalUint64(b, fileStat.Size) + } + if flags&ssh_FILEXFER_ATTR_UIDGID != 0 { + b = marshalUint32(b, fileStat.UID) + b = marshalUint32(b, fileStat.GID) + } + if flags&ssh_FILEXFER_ATTR_PERMISSIONS != 0 { + b = marshalUint32(b, fileStat.Mode) + } + if flags&ssh_FILEXFER_ATTR_ACMODTIME != 0 { + b = marshalUint32(b, fileStat.Atime) + b = marshalUint32(b, fileStat.Mtime) + } + + return b +} + +// toFileMode converts sftp filemode bits to the os.FileMode specification +func toFileMode(mode uint32) os.FileMode { + var fm = os.FileMode(mode & 0777) + switch mode & syscall.S_IFMT { + case syscall.S_IFBLK: + fm |= os.ModeDevice + case syscall.S_IFCHR: + fm |= os.ModeDevice | os.ModeCharDevice + case syscall.S_IFDIR: + fm |= os.ModeDir + case syscall.S_IFIFO: + fm |= os.ModeNamedPipe + case syscall.S_IFLNK: + fm |= os.ModeSymlink + case syscall.S_IFREG: + // nothing to do + case syscall.S_IFSOCK: + fm |= os.ModeSocket + } + if mode&syscall.S_ISGID != 0 { + fm |= os.ModeSetgid + } + if mode&syscall.S_ISUID != 0 { + fm |= os.ModeSetuid + } + if mode&syscall.S_ISVTX != 0 { + fm |= os.ModeSticky + } + return fm +} + +// fromFileMode converts from the os.FileMode specification to sftp filemode bits +func fromFileMode(mode os.FileMode) uint32 { + ret := uint32(0) + + if mode&os.ModeDevice != 0 { + if mode&os.ModeCharDevice != 0 { + ret |= syscall.S_IFCHR + } else { + ret |= syscall.S_IFBLK + } + } + if mode&os.ModeDir != 0 { + ret |= syscall.S_IFDIR + } + if mode&os.ModeSymlink != 0 { + ret |= syscall.S_IFLNK + } + if mode&os.ModeNamedPipe != 0 { + ret |= syscall.S_IFIFO + } + if mode&os.ModeSetgid != 0 { + ret |= syscall.S_ISGID + } + if mode&os.ModeSetuid != 0 { + ret |= syscall.S_ISUID + } + if mode&os.ModeSticky != 0 { + ret |= syscall.S_ISVTX + } + if mode&os.ModeSocket != 0 { + ret |= syscall.S_IFSOCK + } + + if mode&os.ModeType == 0 { + ret |= syscall.S_IFREG + } + ret |= uint32(mode & os.ModePerm) + + return ret +} diff --git a/vendor/github.com/pkg/sftp/attrs_stubs.go b/vendor/github.com/pkg/sftp/attrs_stubs.go new file mode 100644 index 000000000..81cf3eac2 --- /dev/null +++ b/vendor/github.com/pkg/sftp/attrs_stubs.go @@ -0,0 +1,11 @@ +// +build !cgo,!plan9 windows android + +package sftp + +import ( + "os" +) + +func fileStatFromInfoOs(fi os.FileInfo, flags *uint32, fileStat *FileStat) { + // todo +} diff --git a/vendor/github.com/pkg/sftp/attrs_unix.go b/vendor/github.com/pkg/sftp/attrs_unix.go new file mode 100644 index 000000000..ab6ecdea9 --- /dev/null +++ b/vendor/github.com/pkg/sftp/attrs_unix.go @@ -0,0 +1,17 @@ +// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris +// +build cgo + +package sftp + +import ( + "os" + "syscall" +) + +func fileStatFromInfoOs(fi os.FileInfo, flags *uint32, fileStat *FileStat) { + if statt, ok := fi.Sys().(*syscall.Stat_t); ok { + *flags |= ssh_FILEXFER_ATTR_UIDGID + fileStat.UID = statt.Uid + fileStat.GID = statt.Gid + } +} diff --git a/vendor/github.com/pkg/sftp/client.go b/vendor/github.com/pkg/sftp/client.go new file mode 100644 index 000000000..f0d67e801 --- /dev/null +++ b/vendor/github.com/pkg/sftp/client.go @@ -0,0 +1,1211 @@ +package sftp + +import ( + "bytes" + "encoding" + "encoding/binary" + "errors" + "fmt" + "io" + "os" + "path" + "sync" + "sync/atomic" + "time" + + "github.com/kr/fs" + + "golang.org/x/crypto/ssh" +) + +// MaxPacket sets the maximum size of the payload. +func MaxPacket(size int) func(*Client) error { + return func(c *Client) error { + if size < 1<<15 { + return fmt.Errorf("size must be greater or equal to 32k") + } + c.maxPacket = size + return nil + } +} + +// NewClient creates a new SFTP client on conn, using zero or more option +// functions. +func NewClient(conn *ssh.Client, opts ...func(*Client) error) (*Client, error) { + s, err := conn.NewSession() + if err != nil { + return nil, err + } + if err := s.RequestSubsystem("sftp"); err != nil { + return nil, err + } + pw, err := s.StdinPipe() + if err != nil { + return nil, err + } + pr, err := s.StdoutPipe() + if err != nil { + return nil, err + } + + return NewClientPipe(pr, pw, opts...) +} + +// NewClientPipe creates a new SFTP client given a Reader and a WriteCloser. +// This can be used for connecting to an SFTP server over TCP/TLS or by using +// the system's ssh client program (e.g. via exec.Command). +func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...func(*Client) error) (*Client, error) { + sftp := &Client{ + w: wr, + r: rd, + maxPacket: 1 << 15, + inflight: make(map[uint32]chan<- result), + recvClosed: make(chan struct{}), + } + if err := sftp.applyOptions(opts...); err != nil { + wr.Close() + return nil, err + } + if err := sftp.sendInit(); err != nil { + wr.Close() + return nil, err + } + if err := sftp.recvVersion(); err != nil { + wr.Close() + return nil, err + } + go sftp.recv() + return sftp, nil +} + +// Client represents an SFTP session on a *ssh.ClientConn SSH connection. +// Multiple Clients can be active on a single SSH connection, and a Client +// may be called concurrently from multiple Goroutines. +// +// Client implements the github.com/kr/fs.FileSystem interface. +type Client struct { + w io.WriteCloser + r io.Reader + + maxPacket int // max packet size read or written. + nextid uint32 + + mu sync.Mutex // ensures only on request is in flight to the server at once + inflight map[uint32]chan<- result // outstanding requests + recvClosed chan struct{} // remote end has closed the connection +} + +// Close closes the SFTP session. +func (c *Client) Close() error { + err := c.w.Close() + <-c.recvClosed + return err +} + +// Create creates the named file mode 0666 (before umask), truncating it if +// it already exists. If successful, methods on the returned File can be +// used for I/O; the associated file descriptor has mode O_RDWR. +func (c *Client) Create(path string) (*File, error) { + return c.open(path, flags(os.O_RDWR|os.O_CREATE|os.O_TRUNC)) +} + +const sftpProtocolVersion = 3 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 + +func (c *Client) sendInit() error { + return sendPacket(c.w, sshFxInitPacket{ + Version: sftpProtocolVersion, // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 + }) +} + +// returns the next value of c.nextid +func (c *Client) nextID() uint32 { + return atomic.AddUint32(&c.nextid, 1) +} + +func (c *Client) recvVersion() error { + typ, data, err := recvPacket(c.r) + if err != nil { + return err + } + if typ != ssh_FXP_VERSION { + return &unexpectedPacketErr{ssh_FXP_VERSION, typ} + } + + version, _ := unmarshalUint32(data) + if version != sftpProtocolVersion { + return &unexpectedVersionErr{sftpProtocolVersion, version} + } + + return nil +} + +// broadcastErr sends an error to all goroutines waiting for a response. +func (c *Client) broadcastErr(err error) { + c.mu.Lock() + listeners := make([]chan<- result, 0, len(c.inflight)) + for _, ch := range c.inflight { + listeners = append(listeners, ch) + } + c.mu.Unlock() + for _, ch := range listeners { + ch <- result{err: err} + } +} + +// recv continuously reads from the server and forwards responses to the +// appropriate channel. +func (c *Client) recv() { + defer close(c.recvClosed) + for { + typ, data, err := recvPacket(c.r) + if err != nil { + // Return the error to all listeners. + c.broadcastErr(err) + return + } + sid, _ := unmarshalUint32(data) + c.mu.Lock() + ch, ok := c.inflight[sid] + delete(c.inflight, sid) + c.mu.Unlock() + if !ok { + // This is an unexpected occurrence. Send the error + // back to all listeners so that they terminate + // gracefully. + c.broadcastErr(fmt.Errorf("sid: %v not fond", sid)) + return + } + ch <- result{typ: typ, data: data} + } +} + +// Walk returns a new Walker rooted at root. +func (c *Client) Walk(root string) *fs.Walker { + return fs.WalkFS(root, c) +} + +// ReadDir reads the directory named by dirname and returns a list of +// directory entries. +func (c *Client) ReadDir(p string) ([]os.FileInfo, error) { + handle, err := c.opendir(p) + if err != nil { + return nil, err + } + defer c.close(handle) // this has to defer earlier than the lock below + var attrs []os.FileInfo + var done = false + for !done { + id := c.nextID() + typ, data, err1 := c.sendRequest(sshFxpReaddirPacket{ + ID: id, + Handle: handle, + }) + if err1 != nil { + err = err1 + done = true + break + } + switch typ { + case ssh_FXP_NAME: + sid, data := unmarshalUint32(data) + if sid != id { + return nil, &unexpectedIDErr{id, sid} + } + count, data := unmarshalUint32(data) + for i := uint32(0); i < count; i++ { + var filename string + filename, data = unmarshalString(data) + _, data = unmarshalString(data) // discard longname + var attr *FileStat + attr, data = unmarshalAttrs(data) + if filename == "." || filename == ".." { + continue + } + attrs = append(attrs, fileInfoFromStat(attr, path.Base(filename))) + } + case ssh_FXP_STATUS: + // TODO(dfc) scope warning! + err = normaliseError(unmarshalStatus(id, data)) + done = true + default: + return nil, unimplementedPacketErr(typ) + } + } + if err == io.EOF { + err = nil + } + return attrs, err +} + +func (c *Client) opendir(path string) (string, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpOpendirPacket{ + ID: id, + Path: path, + }) + if err != nil { + return "", err + } + switch typ { + case ssh_FXP_HANDLE: + sid, data := unmarshalUint32(data) + if sid != id { + return "", &unexpectedIDErr{id, sid} + } + handle, _ := unmarshalString(data) + return handle, nil + case ssh_FXP_STATUS: + return "", unmarshalStatus(id, data) + default: + return "", unimplementedPacketErr(typ) + } +} + +// Stat returns a FileInfo structure describing the file specified by path 'p'. +// If 'p' is a symbolic link, the returned FileInfo structure describes the referent file. +func (c *Client) Stat(p string) (os.FileInfo, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpStatPacket{ + ID: id, + Path: p, + }) + if err != nil { + return nil, err + } + switch typ { + case ssh_FXP_ATTRS: + sid, data := unmarshalUint32(data) + if sid != id { + return nil, &unexpectedIDErr{id, sid} + } + attr, _ := unmarshalAttrs(data) + return fileInfoFromStat(attr, path.Base(p)), nil + case ssh_FXP_STATUS: + return nil, normaliseError(unmarshalStatus(id, data)) + default: + return nil, unimplementedPacketErr(typ) + } +} + +// Lstat returns a FileInfo structure describing the file specified by path 'p'. +// If 'p' is a symbolic link, the returned FileInfo structure describes the symbolic link. +func (c *Client) Lstat(p string) (os.FileInfo, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpLstatPacket{ + ID: id, + Path: p, + }) + if err != nil { + return nil, err + } + switch typ { + case ssh_FXP_ATTRS: + sid, data := unmarshalUint32(data) + if sid != id { + return nil, &unexpectedIDErr{id, sid} + } + attr, _ := unmarshalAttrs(data) + return fileInfoFromStat(attr, path.Base(p)), nil + case ssh_FXP_STATUS: + return nil, normaliseError(unmarshalStatus(id, data)) + default: + return nil, unimplementedPacketErr(typ) + } +} + +// ReadLink reads the target of a symbolic link. +func (c *Client) ReadLink(p string) (string, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpReadlinkPacket{ + ID: id, + Path: p, + }) + if err != nil { + return "", err + } + switch typ { + case ssh_FXP_NAME: + sid, data := unmarshalUint32(data) + if sid != id { + return "", &unexpectedIDErr{id, sid} + } + count, data := unmarshalUint32(data) + if count != 1 { + return "", unexpectedCount(1, count) + } + filename, _ := unmarshalString(data) // ignore dummy attributes + return filename, nil + case ssh_FXP_STATUS: + return "", unmarshalStatus(id, data) + default: + return "", unimplementedPacketErr(typ) + } +} + +// Symlink creates a symbolic link at 'newname', pointing at target 'oldname' +func (c *Client) Symlink(oldname, newname string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpSymlinkPacket{ + ID: id, + Linkpath: newname, + Targetpath: oldname, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +// setstat is a convience wrapper to allow for changing of various parts of the file descriptor. +func (c *Client) setstat(path string, flags uint32, attrs interface{}) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpSetstatPacket{ + ID: id, + Path: path, + Flags: flags, + Attrs: attrs, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +// Chtimes changes the access and modification times of the named file. +func (c *Client) Chtimes(path string, atime time.Time, mtime time.Time) error { + type times struct { + Atime uint32 + Mtime uint32 + } + attrs := times{uint32(atime.Unix()), uint32(mtime.Unix())} + return c.setstat(path, ssh_FILEXFER_ATTR_ACMODTIME, attrs) +} + +// Chown changes the user and group owners of the named file. +func (c *Client) Chown(path string, uid, gid int) error { + type owner struct { + UID uint32 + GID uint32 + } + attrs := owner{uint32(uid), uint32(gid)} + return c.setstat(path, ssh_FILEXFER_ATTR_UIDGID, attrs) +} + +// Chmod changes the permissions of the named file. +func (c *Client) Chmod(path string, mode os.FileMode) error { + return c.setstat(path, ssh_FILEXFER_ATTR_PERMISSIONS, uint32(mode)) +} + +// Truncate sets the size of the named file. Although it may be safely assumed +// that if the size is less than its current size it will be truncated to fit, +// the SFTP protocol does not specify what behavior the server should do when setting +// size greater than the current size. +func (c *Client) Truncate(path string, size int64) error { + return c.setstat(path, ssh_FILEXFER_ATTR_SIZE, uint64(size)) +} + +// Open opens the named file for reading. If successful, methods on the +// returned file can be used for reading; the associated file descriptor +// has mode O_RDONLY. +func (c *Client) Open(path string) (*File, error) { + return c.open(path, flags(os.O_RDONLY)) +} + +// OpenFile is the generalized open call; most users will use Open or +// Create instead. It opens the named file with specified flag (O_RDONLY +// etc.). If successful, methods on the returned File can be used for I/O. +func (c *Client) OpenFile(path string, f int) (*File, error) { + return c.open(path, flags(f)) +} + +func (c *Client) open(path string, pflags uint32) (*File, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpOpenPacket{ + ID: id, + Path: path, + Pflags: pflags, + }) + if err != nil { + return nil, err + } + switch typ { + case ssh_FXP_HANDLE: + sid, data := unmarshalUint32(data) + if sid != id { + return nil, &unexpectedIDErr{id, sid} + } + handle, _ := unmarshalString(data) + return &File{c: c, path: path, handle: handle}, nil + case ssh_FXP_STATUS: + return nil, normaliseError(unmarshalStatus(id, data)) + default: + return nil, unimplementedPacketErr(typ) + } +} + +// close closes a handle handle previously returned in the response +// to SSH_FXP_OPEN or SSH_FXP_OPENDIR. The handle becomes invalid +// immediately after this request has been sent. +func (c *Client) close(handle string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpClosePacket{ + ID: id, + Handle: handle, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +func (c *Client) fstat(handle string) (*FileStat, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpFstatPacket{ + ID: id, + Handle: handle, + }) + if err != nil { + return nil, err + } + switch typ { + case ssh_FXP_ATTRS: + sid, data := unmarshalUint32(data) + if sid != id { + return nil, &unexpectedIDErr{id, sid} + } + attr, _ := unmarshalAttrs(data) + return attr, nil + case ssh_FXP_STATUS: + return nil, unmarshalStatus(id, data) + default: + return nil, unimplementedPacketErr(typ) + } +} + +// StatVFS retrieves VFS statistics from a remote host. +// +// It implements the statvfs@openssh.com SSH_FXP_EXTENDED feature +// from http://www.opensource.apple.com/source/OpenSSH/OpenSSH-175/openssh/PROTOCOL?txt. +func (c *Client) StatVFS(path string) (*StatVFS, error) { + // send the StatVFS packet to the server + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpStatvfsPacket{ + ID: id, + Path: path, + }) + if err != nil { + return nil, err + } + + switch typ { + // server responded with valid data + case ssh_FXP_EXTENDED_REPLY: + var response StatVFS + err = binary.Read(bytes.NewReader(data), binary.BigEndian, &response) + if err != nil { + return nil, errors.New("can not parse reply") + } + + return &response, nil + + // the resquest failed + case ssh_FXP_STATUS: + return nil, errors.New(fxp(ssh_FXP_STATUS).String()) + + default: + return nil, unimplementedPacketErr(typ) + } +} + +// Join joins any number of path elements into a single path, adding a +// separating slash if necessary. The result is Cleaned; in particular, all +// empty strings are ignored. +func (c *Client) Join(elem ...string) string { return path.Join(elem...) } + +// Remove removes the specified file or directory. An error will be returned if no +// file or directory with the specified path exists, or if the specified directory +// is not empty. +func (c *Client) Remove(path string) error { + err := c.removeFile(path) + switch err := err.(type) { + case *StatusError: + switch err.Code { + // some servers, *cough* osx *cough*, return EPERM, not ENODIR. + // serv-u returns ssh_FX_FILE_IS_A_DIRECTORY + case ssh_FX_PERMISSION_DENIED, ssh_FX_FAILURE, ssh_FX_FILE_IS_A_DIRECTORY: + return c.removeDirectory(path) + default: + return err + } + default: + return err + } + return err +} + +func (c *Client) removeFile(path string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpRemovePacket{ + ID: id, + Filename: path, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +func (c *Client) removeDirectory(path string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpRmdirPacket{ + ID: id, + Path: path, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +// Rename renames a file. +func (c *Client) Rename(oldname, newname string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpRenamePacket{ + ID: id, + Oldpath: oldname, + Newpath: newname, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +func (c *Client) realpath(path string) (string, error) { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpRealpathPacket{ + ID: id, + Path: path, + }) + if err != nil { + return "", err + } + switch typ { + case ssh_FXP_NAME: + sid, data := unmarshalUint32(data) + if sid != id { + return "", &unexpectedIDErr{id, sid} + } + count, data := unmarshalUint32(data) + if count != 1 { + return "", unexpectedCount(1, count) + } + filename, _ := unmarshalString(data) // ignore attributes + return filename, nil + case ssh_FXP_STATUS: + return "", normaliseError(unmarshalStatus(id, data)) + default: + return "", unimplementedPacketErr(typ) + } +} + +// Getwd returns the current working directory of the server. Operations +// involving relative paths will be based at this location. +func (c *Client) Getwd() (string, error) { + return c.realpath(".") +} + +// result captures the result of receiving the a packet from the server +type result struct { + typ byte + data []byte + err error +} + +type idmarshaler interface { + id() uint32 + encoding.BinaryMarshaler +} + +func (c *Client) sendRequest(p idmarshaler) (byte, []byte, error) { + ch := make(chan result, 1) + c.dispatchRequest(ch, p) + s := <-ch + return s.typ, s.data, s.err +} + +func (c *Client) dispatchRequest(ch chan<- result, p idmarshaler) { + c.mu.Lock() + c.inflight[p.id()] = ch + if err := sendPacket(c.w, p); err != nil { + delete(c.inflight, p.id()) + ch <- result{err: err} + } + c.mu.Unlock() +} + +// Mkdir creates the specified directory. An error will be returned if a file or +// directory with the specified path already exists, or if the directory's +// parent folder does not exist (the method cannot create complete paths). +func (c *Client) Mkdir(path string) error { + id := c.nextID() + typ, data, err := c.sendRequest(sshFxpMkdirPacket{ + ID: id, + Path: path, + }) + if err != nil { + return err + } + switch typ { + case ssh_FXP_STATUS: + return normaliseError(unmarshalStatus(id, data)) + default: + return unimplementedPacketErr(typ) + } +} + +// applyOptions applies options functions to the Client. +// If an error is encountered, option processing ceases. +func (c *Client) applyOptions(opts ...func(*Client) error) error { + for _, f := range opts { + if err := f(c); err != nil { + return err + } + } + return nil +} + +// File represents a remote file. +type File struct { + c *Client + path string + handle string + offset uint64 // current offset within remote file +} + +// Close closes the File, rendering it unusable for I/O. It returns an +// error, if any. +func (f *File) Close() error { + return f.c.close(f.handle) +} + +// Name returns the name of the file as presented to Open or Create. +func (f *File) Name() string { + return f.path +} + +const maxConcurrentRequests = 64 + +// Read reads up to len(b) bytes from the File. It returns the number of +// bytes read and an error, if any. EOF is signaled by a zero count with +// err set to io.EOF. +func (f *File) Read(b []byte) (int, error) { + // Split the read into multiple maxPacket sized concurrent reads + // bounded by maxConcurrentRequests. This allows reads with a suitably + // large buffer to transfer data at a much faster rate due to + // overlapping round trip times. + inFlight := 0 + desiredInFlight := 1 + offset := f.offset + ch := make(chan result, 1) + type inflightRead struct { + b []byte + offset uint64 + } + reqs := map[uint32]inflightRead{} + type offsetErr struct { + offset uint64 + err error + } + var firstErr offsetErr + + sendReq := func(b []byte, offset uint64) { + reqID := f.c.nextID() + f.c.dispatchRequest(ch, sshFxpReadPacket{ + ID: reqID, + Handle: f.handle, + Offset: offset, + Len: uint32(len(b)), + }) + inFlight++ + reqs[reqID] = inflightRead{b: b, offset: offset} + } + + var read int + for len(b) > 0 || inFlight > 0 { + for inFlight < desiredInFlight && len(b) > 0 && firstErr.err == nil { + l := min(len(b), f.c.maxPacket) + rb := b[:l] + sendReq(rb, offset) + offset += uint64(l) + b = b[l:] + } + + if inFlight == 0 { + break + } + select { + case res := <-ch: + inFlight-- + if res.err != nil { + firstErr = offsetErr{offset: 0, err: res.err} + break + } + reqID, data := unmarshalUint32(res.data) + req, ok := reqs[reqID] + if !ok { + firstErr = offsetErr{offset: 0, err: fmt.Errorf("sid: %v not found", reqID)} + break + } + delete(reqs, reqID) + switch res.typ { + case ssh_FXP_STATUS: + if firstErr.err == nil || req.offset < firstErr.offset { + firstErr = offsetErr{ + offset: req.offset, + err: normaliseError(unmarshalStatus(reqID, res.data)), + } + break + } + case ssh_FXP_DATA: + l, data := unmarshalUint32(data) + n := copy(req.b, data[:l]) + read += n + if n < len(req.b) { + sendReq(req.b[l:], req.offset+uint64(l)) + } + if desiredInFlight < maxConcurrentRequests { + desiredInFlight++ + } + default: + firstErr = offsetErr{offset: 0, err: unimplementedPacketErr(res.typ)} + break + } + } + } + // If the error is anything other than EOF, then there + // may be gaps in the data copied to the buffer so it's + // best to return 0 so the caller can't make any + // incorrect assumptions about the state of the buffer. + if firstErr.err != nil && firstErr.err != io.EOF { + read = 0 + } + f.offset += uint64(read) + return read, firstErr.err +} + +// WriteTo writes the file to w. The return value is the number of bytes +// written. Any error encountered during the write is also returned. +func (f *File) WriteTo(w io.Writer) (int64, error) { + fi, err := f.Stat() + if err != nil { + return 0, err + } + inFlight := 0 + desiredInFlight := 1 + offset := f.offset + writeOffset := offset + fileSize := uint64(fi.Size()) + ch := make(chan result, 1) + type inflightRead struct { + b []byte + offset uint64 + } + reqs := map[uint32]inflightRead{} + pendingWrites := map[uint64][]byte{} + type offsetErr struct { + offset uint64 + err error + } + var firstErr offsetErr + + sendReq := func(b []byte, offset uint64) { + reqID := f.c.nextID() + f.c.dispatchRequest(ch, sshFxpReadPacket{ + ID: reqID, + Handle: f.handle, + Offset: offset, + Len: uint32(len(b)), + }) + inFlight++ + reqs[reqID] = inflightRead{b: b, offset: offset} + } + + var copied int64 + for firstErr.err == nil || inFlight > 0 { + for inFlight < desiredInFlight && firstErr.err == nil { + b := make([]byte, f.c.maxPacket) + sendReq(b, offset) + offset += uint64(f.c.maxPacket) + if offset > fileSize { + desiredInFlight = 1 + } + } + + if inFlight == 0 { + break + } + select { + case res := <-ch: + inFlight-- + if res.err != nil { + firstErr = offsetErr{offset: 0, err: res.err} + break + } + reqID, data := unmarshalUint32(res.data) + req, ok := reqs[reqID] + if !ok { + firstErr = offsetErr{offset: 0, err: fmt.Errorf("sid: %v not found", reqID)} + break + } + delete(reqs, reqID) + switch res.typ { + case ssh_FXP_STATUS: + if firstErr.err == nil || req.offset < firstErr.offset { + firstErr = offsetErr{offset: req.offset, err: normaliseError(unmarshalStatus(reqID, res.data))} + break + } + case ssh_FXP_DATA: + l, data := unmarshalUint32(data) + if req.offset == writeOffset { + nbytes, err := w.Write(data) + copied += int64(nbytes) + if err != nil { + firstErr = offsetErr{offset: req.offset + uint64(nbytes), err: err} + break + } + if nbytes < int(l) { + firstErr = offsetErr{offset: req.offset + uint64(nbytes), err: io.ErrShortWrite} + break + } + switch { + case offset > fileSize: + desiredInFlight = 1 + case desiredInFlight < maxConcurrentRequests: + desiredInFlight++ + } + writeOffset += uint64(nbytes) + for pendingData, ok := pendingWrites[writeOffset]; ok; pendingData, ok = pendingWrites[writeOffset] { + nbytes, err := w.Write(pendingData) + if err != nil { + firstErr = offsetErr{offset: writeOffset + uint64(nbytes), err: err} + break + } + if nbytes < len(pendingData) { + firstErr = offsetErr{offset: writeOffset + uint64(nbytes), err: io.ErrShortWrite} + break + } + writeOffset += uint64(nbytes) + inFlight-- + } + } else { + // Don't write the data yet because + // this response came in out of order + // and we need to wait for responses + // for earlier segments of the file. + inFlight++ // Pending writes should still be considered inFlight. + pendingWrites[req.offset] = data + } + default: + firstErr = offsetErr{offset: 0, err: unimplementedPacketErr(res.typ)} + break + } + } + } + if firstErr.err != io.EOF { + return copied, firstErr.err + } + return copied, nil +} + +// Stat returns the FileInfo structure describing file. If there is an +// error. +func (f *File) Stat() (os.FileInfo, error) { + fs, err := f.c.fstat(f.handle) + if err != nil { + return nil, err + } + return fileInfoFromStat(fs, path.Base(f.path)), nil +} + +// Write writes len(b) bytes to the File. It returns the number of bytes +// written and an error, if any. Write returns a non-nil error when n != +// len(b). +func (f *File) Write(b []byte) (int, error) { + // Split the write into multiple maxPacket sized concurrent writes + // bounded by maxConcurrentRequests. This allows writes with a suitably + // large buffer to transfer data at a much faster rate due to + // overlapping round trip times. + inFlight := 0 + desiredInFlight := 1 + offset := f.offset + ch := make(chan result, 1) + var firstErr error + written := len(b) + for len(b) > 0 || inFlight > 0 { + for inFlight < desiredInFlight && len(b) > 0 && firstErr == nil { + l := min(len(b), f.c.maxPacket) + rb := b[:l] + f.c.dispatchRequest(ch, sshFxpWritePacket{ + ID: f.c.nextID(), + Handle: f.handle, + Offset: offset, + Length: uint32(len(rb)), + Data: rb, + }) + inFlight++ + offset += uint64(l) + b = b[l:] + } + + if inFlight == 0 { + break + } + select { + case res := <-ch: + inFlight-- + if res.err != nil { + firstErr = res.err + break + } + switch res.typ { + case ssh_FXP_STATUS: + id, _ := unmarshalUint32(res.data) + err := normaliseError(unmarshalStatus(id, res.data)) + if err != nil && firstErr == nil { + firstErr = err + break + } + if desiredInFlight < maxConcurrentRequests { + desiredInFlight++ + } + default: + firstErr = unimplementedPacketErr(res.typ) + break + } + } + } + // If error is non-nil, then there may be gaps in the data written to + // the file so it's best to return 0 so the caller can't make any + // incorrect assumptions about the state of the file. + if firstErr != nil { + written = 0 + } + f.offset += uint64(written) + return written, firstErr +} + +// ReadFrom reads data from r until EOF and writes it to the file. The return +// value is the number of bytes read. Any error except io.EOF encountered +// during the read is also returned. +func (f *File) ReadFrom(r io.Reader) (int64, error) { + inFlight := 0 + desiredInFlight := 1 + offset := f.offset + ch := make(chan result, 1) + var firstErr error + read := int64(0) + b := make([]byte, f.c.maxPacket) + for inFlight > 0 || firstErr == nil { + for inFlight < desiredInFlight && firstErr == nil { + n, err := r.Read(b) + if err != nil { + firstErr = err + } + f.c.dispatchRequest(ch, sshFxpWritePacket{ + ID: f.c.nextID(), + Handle: f.handle, + Offset: offset, + Length: uint32(n), + Data: b[:n], + }) + inFlight++ + offset += uint64(n) + read += int64(n) + } + + if inFlight == 0 { + break + } + select { + case res := <-ch: + inFlight-- + if res.err != nil { + firstErr = res.err + break + } + switch res.typ { + case ssh_FXP_STATUS: + id, _ := unmarshalUint32(res.data) + err := normaliseError(unmarshalStatus(id, res.data)) + if err != nil && firstErr == nil { + firstErr = err + break + } + if desiredInFlight < maxConcurrentRequests { + desiredInFlight++ + } + default: + firstErr = unimplementedPacketErr(res.typ) + break + } + } + } + if firstErr == io.EOF { + firstErr = nil + } + // If error is non-nil, then there may be gaps in the data written to + // the file so it's best to return 0 so the caller can't make any + // incorrect assumptions about the state of the file. + if firstErr != nil { + read = 0 + } + f.offset += uint64(read) + return read, firstErr +} + +// Seek implements io.Seeker by setting the client offset for the next Read or +// Write. It returns the next offset read. Seeking before or after the end of +// the file is undefined. Seeking relative to the end calls Stat. +func (f *File) Seek(offset int64, whence int) (int64, error) { + switch whence { + case os.SEEK_SET: + f.offset = uint64(offset) + case os.SEEK_CUR: + f.offset = uint64(int64(f.offset) + offset) + case os.SEEK_END: + fi, err := f.Stat() + if err != nil { + return int64(f.offset), err + } + f.offset = uint64(fi.Size() + offset) + default: + return int64(f.offset), unimplementedSeekWhence(whence) + } + return int64(f.offset), nil +} + +// Chown changes the uid/gid of the current file. +func (f *File) Chown(uid, gid int) error { + return f.c.Chown(f.path, uid, gid) +} + +// Chmod changes the permissions of the current file. +func (f *File) Chmod(mode os.FileMode) error { + return f.c.Chmod(f.path, mode) +} + +// Truncate sets the size of the current file. Although it may be safely assumed +// that if the size is less than its current size it will be truncated to fit, +// the SFTP protocol does not specify what behavior the server should do when setting +// size greater than the current size. +func (f *File) Truncate(size int64) error { + return f.c.Truncate(f.path, size) +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +// normaliseError normalises an error into a more standard form that can be +// checked against stdlib errors like io.EOF or os.ErrNotExist. +func normaliseError(err error) error { + switch err := err.(type) { + case *StatusError: + switch err.Code { + case ssh_FX_EOF: + return io.EOF + case ssh_FX_NO_SUCH_FILE: + return os.ErrNotExist + case ssh_FX_OK: + return nil + default: + return err + } + default: + return err + } +} + +func unmarshalStatus(id uint32, data []byte) error { + sid, data := unmarshalUint32(data) + if sid != id { + return &unexpectedIDErr{id, sid} + } + code, data := unmarshalUint32(data) + msg, data := unmarshalString(data) + lang, _, _ := unmarshalStringSafe(data) + return &StatusError{ + Code: code, + msg: msg, + lang: lang, + } +} + +func marshalStatus(b []byte, err StatusError) []byte { + b = marshalUint32(b, err.Code) + b = marshalString(b, err.msg) + b = marshalString(b, err.lang) + return b +} + +// flags converts the flags passed to OpenFile into ssh flags. +// Unsupported flags are ignored. +func flags(f int) uint32 { + var out uint32 + switch f & os.O_WRONLY { + case os.O_WRONLY: + out |= ssh_FXF_WRITE + case os.O_RDONLY: + out |= ssh_FXF_READ + } + if f&os.O_RDWR == os.O_RDWR { + out |= ssh_FXF_READ | ssh_FXF_WRITE + } + if f&os.O_APPEND == os.O_APPEND { + out |= ssh_FXF_APPEND + } + if f&os.O_CREATE == os.O_CREATE { + out |= ssh_FXF_CREAT + } + if f&os.O_TRUNC == os.O_TRUNC { + out |= ssh_FXF_TRUNC + } + if f&os.O_EXCL == os.O_EXCL { + out |= ssh_FXF_EXCL + } + return out +} diff --git a/vendor/github.com/pkg/sftp/debug.go b/vendor/github.com/pkg/sftp/debug.go new file mode 100644 index 000000000..3e264abe3 --- /dev/null +++ b/vendor/github.com/pkg/sftp/debug.go @@ -0,0 +1,9 @@ +// +build debug + +package sftp + +import "log" + +func debug(fmt string, args ...interface{}) { + log.Printf(fmt, args...) +} diff --git a/vendor/github.com/pkg/sftp/examples/buffered-read-benchmark/main.go b/vendor/github.com/pkg/sftp/examples/buffered-read-benchmark/main.go new file mode 100644 index 000000000..32c4d1f3b --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/buffered-read-benchmark/main.go @@ -0,0 +1,77 @@ +// buffered-read-benchmark benchmarks the peformance of reading +// from /dev/zero on the server to a []byte on the client via io.Copy. +package main + +import ( + "flag" + "fmt" + "io" + "log" + "net" + "os" + "time" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + + "github.com/pkg/sftp" +) + +var ( + USER = flag.String("user", os.Getenv("USER"), "ssh username") + HOST = flag.String("host", "localhost", "ssh server hostname") + PORT = flag.Int("port", 22, "ssh server port") + PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") + SIZE = flag.Int("s", 1<<15, "set max packet size") +) + +func init() { + flag.Parse() +} + +func main() { + var auths []ssh.AuthMethod + if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { + auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) + + } + if *PASS != "" { + auths = append(auths, ssh.Password(*PASS)) + } + + config := ssh.ClientConfig{ + User: *USER, + Auth: auths, + } + addr := fmt.Sprintf("%s:%d", *HOST, *PORT) + conn, err := ssh.Dial("tcp", addr, &config) + if err != nil { + log.Fatalf("unable to connect to [%s]: %v", addr, err) + } + defer conn.Close() + + c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) + if err != nil { + log.Fatalf("unable to start sftp subsytem: %v", err) + } + defer c.Close() + + r, err := c.Open("/dev/zero") + if err != nil { + log.Fatal(err) + } + defer r.Close() + + const size = 1e9 + + log.Printf("reading %v bytes", size) + t1 := time.Now() + n, err := io.ReadFull(r, make([]byte, size)) + if err != nil { + log.Fatal(err) + } + if n != size { + log.Fatalf("copy: expected %v bytes, got %d", size, n) + } + log.Printf("read %v bytes in %s", size, time.Since(t1)) +} diff --git a/vendor/github.com/pkg/sftp/examples/buffered-write-benchmark/main.go b/vendor/github.com/pkg/sftp/examples/buffered-write-benchmark/main.go new file mode 100644 index 000000000..0c38db68c --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/buffered-write-benchmark/main.go @@ -0,0 +1,83 @@ +// buffered-write-benchmark benchmarks the peformance of writing +// a single large []byte on the client to /dev/null on the server via io.Copy. +package main + +import ( + "flag" + "fmt" + "log" + "net" + "os" + "syscall" + "time" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + + "github.com/pkg/sftp" +) + +var ( + USER = flag.String("user", os.Getenv("USER"), "ssh username") + HOST = flag.String("host", "localhost", "ssh server hostname") + PORT = flag.Int("port", 22, "ssh server port") + PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") + SIZE = flag.Int("s", 1<<15, "set max packet size") +) + +func init() { + flag.Parse() +} + +func main() { + var auths []ssh.AuthMethod + if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { + auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) + + } + if *PASS != "" { + auths = append(auths, ssh.Password(*PASS)) + } + + config := ssh.ClientConfig{ + User: *USER, + Auth: auths, + } + addr := fmt.Sprintf("%s:%d", *HOST, *PORT) + conn, err := ssh.Dial("tcp", addr, &config) + if err != nil { + log.Fatalf("unable to connect to [%s]: %v", addr, err) + } + defer conn.Close() + + c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) + if err != nil { + log.Fatalf("unable to start sftp subsytem: %v", err) + } + defer c.Close() + + w, err := c.OpenFile("/dev/null", syscall.O_WRONLY) + if err != nil { + log.Fatal(err) + } + defer w.Close() + + f, err := os.Open("/dev/zero") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + const size = 1e9 + + log.Printf("writing %v bytes", size) + t1 := time.Now() + n, err := w.Write(make([]byte, size)) + if err != nil { + log.Fatal(err) + } + if n != size { + log.Fatalf("copy: expected %v bytes, got %d", size, n) + } + log.Printf("wrote %v bytes in %s", size, time.Since(t1)) +} diff --git a/vendor/github.com/pkg/sftp/examples/sftp-server/README.md b/vendor/github.com/pkg/sftp/examples/sftp-server/README.md new file mode 100644 index 000000000..bd96f2d8a --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/sftp-server/README.md @@ -0,0 +1,12 @@ +Example SFTP server implementation +=== + +In order to use this example you will need an RSA key. + +On linux-like systems with openssh installed, you can use the command: + +``` +ssh-keygen -t rsa -f id_rsa +``` + +Then you will be able to run the sftp-server command in the current directory. diff --git a/vendor/github.com/pkg/sftp/examples/sftp-server/main.go b/vendor/github.com/pkg/sftp/examples/sftp-server/main.go new file mode 100644 index 000000000..115d35c35 --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/sftp-server/main.go @@ -0,0 +1,134 @@ +// An example SFTP server implementation using the golang SSH package. +// Serves the whole filesystem visible to the user, and has a hard-coded username and password, +// so not for real use! +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "net" + "os" + + "github.com/pkg/sftp" + "golang.org/x/crypto/ssh" +) + +// Based on example server code from golang.org/x/crypto/ssh and server_standalone +func main() { + + var ( + readOnly bool + debugStderr bool + ) + + flag.BoolVar(&readOnly, "R", false, "read-only server") + flag.BoolVar(&debugStderr, "e", false, "debug to stderr") + flag.Parse() + + debugStream := ioutil.Discard + if debugStderr { + debugStream = os.Stderr + } + + // An SSH server is represented by a ServerConfig, which holds + // certificate details and handles authentication of ServerConns. + config := &ssh.ServerConfig{ + PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + // Should use constant-time compare (or better, salt+hash) in + // a production setting. + fmt.Fprintf(debugStream, "Login: %s\n", c.User()) + if c.User() == "testuser" && string(pass) == "tiger" { + return nil, nil + } + return nil, fmt.Errorf("password rejected for %q", c.User()) + }, + } + + privateBytes, err := ioutil.ReadFile("id_rsa") + if err != nil { + log.Fatal("Failed to load private key", err) + } + + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + log.Fatal("Failed to parse private key", err) + } + + config.AddHostKey(private) + + // Once a ServerConfig has been configured, connections can be + // accepted. + listener, err := net.Listen("tcp", "0.0.0.0:2022") + if err != nil { + log.Fatal("failed to listen for connection", err) + } + fmt.Printf("Listening on %v\n", listener.Addr()) + + nConn, err := listener.Accept() + if err != nil { + log.Fatal("failed to accept incoming connection", err) + } + + // Before use, a handshake must be performed on the incoming + // net.Conn. + _, chans, reqs, err := ssh.NewServerConn(nConn, config) + if err != nil { + log.Fatal("failed to handshake", err) + } + fmt.Fprintf(debugStream, "SSH server established\n") + + // The incoming Request channel must be serviced. + go ssh.DiscardRequests(reqs) + + // Service the incoming Channel channel. + for newChannel := range chans { + // Channels have a type, depending on the application level + // protocol intended. In the case of an SFTP session, this is "subsystem" + // with a payload string of "sftp" + fmt.Fprintf(debugStream, "Incoming channel: %s\n", newChannel.ChannelType()) + if newChannel.ChannelType() != "session" { + newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") + fmt.Fprintf(debugStream, "Unknown channel type: %s\n", newChannel.ChannelType()) + continue + } + channel, requests, err := newChannel.Accept() + if err != nil { + log.Fatal("could not accept channel.", err) + } + fmt.Fprintf(debugStream, "Channel accepted\n") + + // Sessions have out-of-band requests such as "shell", + // "pty-req" and "env". Here we handle only the + // "subsystem" request. + go func(in <-chan *ssh.Request) { + for req := range in { + fmt.Fprintf(debugStream, "Request: %v\n", req.Type) + ok := false + switch req.Type { + case "subsystem": + fmt.Fprintf(debugStream, "Subsystem: %s\n", req.Payload[4:]) + if string(req.Payload[4:]) == "sftp" { + ok = true + } + } + fmt.Fprintf(debugStream, " - accepted: %v\n", ok) + req.Reply(ok, nil) + } + }(requests) + + server, err := sftp.NewServer( + channel, + channel, + sftp.WithDebug(debugStream), + sftp.ReadOnly(), + ) + if err != nil { + log.Fatal(err) + } + if err := server.Serve(); err != nil { + log.Fatal("sftp server completed with error:", err) + } + } +} diff --git a/vendor/github.com/pkg/sftp/examples/streaming-read-benchmark/main.go b/vendor/github.com/pkg/sftp/examples/streaming-read-benchmark/main.go new file mode 100644 index 000000000..dc901e976 --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/streaming-read-benchmark/main.go @@ -0,0 +1,84 @@ +// streaming-read-benchmark benchmarks the peformance of reading +// from /dev/zero on the server to /dev/null on the client via io.Copy. +package main + +import ( + "flag" + "fmt" + "io" + "log" + "net" + "os" + "syscall" + "time" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + + "github.com/pkg/sftp" +) + +var ( + USER = flag.String("user", os.Getenv("USER"), "ssh username") + HOST = flag.String("host", "localhost", "ssh server hostname") + PORT = flag.Int("port", 22, "ssh server port") + PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") + SIZE = flag.Int("s", 1<<15, "set max packet size") +) + +func init() { + flag.Parse() +} + +func main() { + var auths []ssh.AuthMethod + if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { + auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) + + } + if *PASS != "" { + auths = append(auths, ssh.Password(*PASS)) + } + + config := ssh.ClientConfig{ + User: *USER, + Auth: auths, + } + addr := fmt.Sprintf("%s:%d", *HOST, *PORT) + conn, err := ssh.Dial("tcp", addr, &config) + if err != nil { + log.Fatalf("unable to connect to [%s]: %v", addr, err) + } + defer conn.Close() + + c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) + if err != nil { + log.Fatalf("unable to start sftp subsytem: %v", err) + } + defer c.Close() + + r, err := c.Open("/dev/zero") + if err != nil { + log.Fatal(err) + } + defer r.Close() + + w, err := os.OpenFile("/dev/null", syscall.O_WRONLY, 0600) + if err != nil { + log.Fatal(err) + } + defer w.Close() + + const size int64 = 1e9 + + log.Printf("reading %v bytes", size) + t1 := time.Now() + n, err := io.Copy(w, io.LimitReader(r, size)) + if err != nil { + log.Fatal(err) + } + if n != size { + log.Fatalf("copy: expected %v bytes, got %d", size, n) + } + log.Printf("read %v bytes in %s", size, time.Since(t1)) +} diff --git a/vendor/github.com/pkg/sftp/examples/streaming-write-benchmark/main.go b/vendor/github.com/pkg/sftp/examples/streaming-write-benchmark/main.go new file mode 100644 index 000000000..07a9ddb7c --- /dev/null +++ b/vendor/github.com/pkg/sftp/examples/streaming-write-benchmark/main.go @@ -0,0 +1,84 @@ +// streaming-write-benchmark benchmarks the peformance of writing +// from /dev/zero on the client to /dev/null on the server via io.Copy. +package main + +import ( + "flag" + "fmt" + "io" + "log" + "net" + "os" + "syscall" + "time" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + + "github.com/pkg/sftp" +) + +var ( + USER = flag.String("user", os.Getenv("USER"), "ssh username") + HOST = flag.String("host", "localhost", "ssh server hostname") + PORT = flag.Int("port", 22, "ssh server port") + PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") + SIZE = flag.Int("s", 1<<15, "set max packet size") +) + +func init() { + flag.Parse() +} + +func main() { + var auths []ssh.AuthMethod + if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { + auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) + + } + if *PASS != "" { + auths = append(auths, ssh.Password(*PASS)) + } + + config := ssh.ClientConfig{ + User: *USER, + Auth: auths, + } + addr := fmt.Sprintf("%s:%d", *HOST, *PORT) + conn, err := ssh.Dial("tcp", addr, &config) + if err != nil { + log.Fatalf("unable to connect to [%s]: %v", addr, err) + } + defer conn.Close() + + c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) + if err != nil { + log.Fatalf("unable to start sftp subsytem: %v", err) + } + defer c.Close() + + w, err := c.OpenFile("/dev/null", syscall.O_WRONLY) + if err != nil { + log.Fatal(err) + } + defer w.Close() + + f, err := os.Open("/dev/zero") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + const size int64 = 1e9 + + log.Printf("writing %v bytes", size) + t1 := time.Now() + n, err := io.Copy(w, io.LimitReader(f, size)) + if err != nil { + log.Fatal(err) + } + if n != size { + log.Fatalf("copy: expected %v bytes, got %d", size, n) + } + log.Printf("wrote %v bytes in %s", size, time.Since(t1)) +} diff --git a/vendor/github.com/pkg/sftp/packet.go b/vendor/github.com/pkg/sftp/packet.go new file mode 100644 index 000000000..cd95c7246 --- /dev/null +++ b/vendor/github.com/pkg/sftp/packet.go @@ -0,0 +1,840 @@ +package sftp + +import ( + "encoding" + "errors" + "fmt" + "io" + "os" + "reflect" +) + +var ( + errShortPacket = errors.New("packet too short") +) + +const ( + debugDumpTxPacket = false + debugDumpRxPacket = false + debugDumpTxPacketBytes = false + debugDumpRxPacketBytes = false +) + +func marshalUint32(b []byte, v uint32) []byte { + return append(b, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +func marshalUint64(b []byte, v uint64) []byte { + return marshalUint32(marshalUint32(b, uint32(v>>32)), uint32(v)) +} + +func marshalString(b []byte, v string) []byte { + return append(marshalUint32(b, uint32(len(v))), v...) +} + +func marshal(b []byte, v interface{}) []byte { + if v == nil { + return b + } + switch v := v.(type) { + case uint8: + return append(b, v) + case uint32: + return marshalUint32(b, v) + case uint64: + return marshalUint64(b, v) + case string: + return marshalString(b, v) + case os.FileInfo: + return marshalFileInfo(b, v) + default: + switch d := reflect.ValueOf(v); d.Kind() { + case reflect.Struct: + for i, n := 0, d.NumField(); i < n; i++ { + b = append(marshal(b, d.Field(i).Interface())) + } + return b + case reflect.Slice: + for i, n := 0, d.Len(); i < n; i++ { + b = append(marshal(b, d.Index(i).Interface())) + } + return b + default: + panic(fmt.Sprintf("marshal(%#v): cannot handle type %T", v, v)) + } + } +} + +func unmarshalUint32(b []byte) (uint32, []byte) { + v := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 + return v, b[4:] +} + +func unmarshalUint32Safe(b []byte) (uint32, []byte, error) { + var v uint32 + if len(b) < 4 { + return 0, nil, errShortPacket + } + v, b = unmarshalUint32(b) + return v, b, nil +} + +func unmarshalUint64(b []byte) (uint64, []byte) { + h, b := unmarshalUint32(b) + l, b := unmarshalUint32(b) + return uint64(h)<<32 | uint64(l), b +} + +func unmarshalUint64Safe(b []byte) (uint64, []byte, error) { + var v uint64 + if len(b) < 8 { + return 0, nil, errShortPacket + } + v, b = unmarshalUint64(b) + return v, b, nil +} + +func unmarshalString(b []byte) (string, []byte) { + n, b := unmarshalUint32(b) + return string(b[:n]), b[n:] +} + +func unmarshalStringSafe(b []byte) (string, []byte, error) { + n, b, err := unmarshalUint32Safe(b) + if err != nil { + return "", nil, err + } + if int64(n) > int64(len(b)) { + return "", nil, errShortPacket + } + return string(b[:n]), b[n:], nil +} + +// sendPacket marshals p according to RFC 4234. +func sendPacket(w io.Writer, m encoding.BinaryMarshaler) error { + bb, err := m.MarshalBinary() + if err != nil { + return fmt.Errorf("marshal2(%#v): binary marshaller failed", err) + } + if debugDumpTxPacketBytes { + debug("send packet: %s %d bytes %x", fxp(bb[0]), len(bb), bb[1:]) + } else if debugDumpTxPacket { + debug("send packet: %s %d bytes", fxp(bb[0]), len(bb)) + } + l := uint32(len(bb)) + hdr := []byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)} + _, err = w.Write(hdr) + if err != nil { + return err + } + _, err = w.Write(bb) + return err +} + +func (svr *Server) sendPacket(m encoding.BinaryMarshaler) error { + // any responder can call sendPacket(); actual socket access must be serialized + svr.outMutex.Lock() + defer svr.outMutex.Unlock() + return sendPacket(svr.out, m) +} + +func recvPacket(r io.Reader) (uint8, []byte, error) { + var b = []byte{0, 0, 0, 0} + if _, err := io.ReadFull(r, b); err != nil { + return 0, nil, err + } + l, _ := unmarshalUint32(b) + b = make([]byte, l) + if _, err := io.ReadFull(r, b); err != nil { + debug("recv packet %d bytes: err %v", l, err) + return 0, nil, err + } + if debugDumpRxPacketBytes { + debug("recv packet: %s %d bytes %x", fxp(b[0]), l, b[1:]) + } else if debugDumpRxPacket { + debug("recv packet: %s %d bytes", fxp(b[0]), l) + } + return b[0], b[1:], nil +} + +type extensionPair struct { + Name string + Data string +} + +func unmarshalExtensionPair(b []byte) (extensionPair, []byte, error) { + var ep extensionPair + var err error + ep.Name, b, err = unmarshalStringSafe(b) + if err != nil { + return ep, b, err + } + ep.Data, b, err = unmarshalStringSafe(b) + if err != nil { + return ep, b, err + } + return ep, b, err +} + +// Here starts the definition of packets along with their MarshalBinary +// implementations. +// Manually writing the marshalling logic wins us a lot of time and +// allocation. + +type sshFxInitPacket struct { + Version uint32 + Extensions []extensionPair +} + +func (p sshFxInitPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 // byte + uint32 + for _, e := range p.Extensions { + l += 4 + len(e.Name) + 4 + len(e.Data) + } + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_INIT) + b = marshalUint32(b, p.Version) + for _, e := range p.Extensions { + b = marshalString(b, e.Name) + b = marshalString(b, e.Data) + } + return b, nil +} + +func (p *sshFxInitPacket) UnmarshalBinary(b []byte) error { + var err error + if p.Version, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + for len(b) > 0 { + var ep extensionPair + ep, b, err = unmarshalExtensionPair(b) + if err != nil { + return err + } + p.Extensions = append(p.Extensions, ep) + } + return nil +} + +type sshFxVersionPacket struct { + Version uint32 + Extensions []struct { + Name, Data string + } +} + +func (p sshFxVersionPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 // byte + uint32 + for _, e := range p.Extensions { + l += 4 + len(e.Name) + 4 + len(e.Data) + } + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_VERSION) + b = marshalUint32(b, p.Version) + for _, e := range p.Extensions { + b = marshalString(b, e.Name) + b = marshalString(b, e.Data) + } + return b, nil +} + +func marshalIDString(packetType byte, id uint32, str string) ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(str) + + b := make([]byte, 0, l) + b = append(b, packetType) + b = marshalUint32(b, id) + b = marshalString(b, str) + return b, nil +} + +func unmarshalIDString(b []byte, id *uint32, str *string) error { + var err error + *id, b, err = unmarshalUint32Safe(b) + if err != nil { + return err + } + *str, b, err = unmarshalStringSafe(b) + if err != nil { + return err + } + return nil +} + +type sshFxpReaddirPacket struct { + ID uint32 + Handle string +} + +func (p sshFxpReaddirPacket) id() uint32 { return p.ID } + +func (p sshFxpReaddirPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_READDIR, p.ID, p.Handle) +} + +func (p *sshFxpReaddirPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Handle) +} + +type sshFxpOpendirPacket struct { + ID uint32 + Path string +} + +func (p sshFxpOpendirPacket) id() uint32 { return p.ID } + +func (p sshFxpOpendirPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_OPENDIR, p.ID, p.Path) +} + +func (p *sshFxpOpendirPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpLstatPacket struct { + ID uint32 + Path string +} + +func (p sshFxpLstatPacket) id() uint32 { return p.ID } + +func (p sshFxpLstatPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_LSTAT, p.ID, p.Path) +} + +func (p *sshFxpLstatPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpStatPacket struct { + ID uint32 + Path string +} + +func (p sshFxpStatPacket) id() uint32 { return p.ID } + +func (p sshFxpStatPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_LSTAT, p.ID, p.Path) +} + +func (p *sshFxpStatPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpFstatPacket struct { + ID uint32 + Handle string +} + +func (p sshFxpFstatPacket) id() uint32 { return p.ID } + +func (p sshFxpFstatPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_FSTAT, p.ID, p.Handle) +} + +func (p *sshFxpFstatPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Handle) +} + +type sshFxpClosePacket struct { + ID uint32 + Handle string +} + +func (p sshFxpClosePacket) id() uint32 { return p.ID } + +func (p sshFxpClosePacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_CLOSE, p.ID, p.Handle) +} + +func (p *sshFxpClosePacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Handle) +} + +type sshFxpRemovePacket struct { + ID uint32 + Filename string +} + +func (p sshFxpRemovePacket) id() uint32 { return p.ID } + +func (p sshFxpRemovePacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_REMOVE, p.ID, p.Filename) +} + +func (p *sshFxpRemovePacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Filename) +} + +type sshFxpRmdirPacket struct { + ID uint32 + Path string +} + +func (p sshFxpRmdirPacket) id() uint32 { return p.ID } + +func (p sshFxpRmdirPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_RMDIR, p.ID, p.Path) +} + +func (p *sshFxpRmdirPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpSymlinkPacket struct { + ID uint32 + Targetpath string + Linkpath string +} + +func (p sshFxpSymlinkPacket) id() uint32 { return p.ID } + +func (p sshFxpSymlinkPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Targetpath) + + 4 + len(p.Linkpath) + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_SYMLINK) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Targetpath) + b = marshalString(b, p.Linkpath) + return b, nil +} + +func (p *sshFxpSymlinkPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Targetpath, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Linkpath, b, err = unmarshalStringSafe(b); err != nil { + return err + } + return nil +} + +type sshFxpReadlinkPacket struct { + ID uint32 + Path string +} + +func (p sshFxpReadlinkPacket) id() uint32 { return p.ID } + +func (p sshFxpReadlinkPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_READLINK, p.ID, p.Path) +} + +func (p *sshFxpReadlinkPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpRealpathPacket struct { + ID uint32 + Path string +} + +func (p sshFxpRealpathPacket) id() uint32 { return p.ID } + +func (p sshFxpRealpathPacket) MarshalBinary() ([]byte, error) { + return marshalIDString(ssh_FXP_REALPATH, p.ID, p.Path) +} + +func (p *sshFxpRealpathPacket) UnmarshalBinary(b []byte) error { + return unmarshalIDString(b, &p.ID, &p.Path) +} + +type sshFxpNameAttr struct { + Name string + LongName string + Attrs []interface{} +} + +func (p sshFxpNameAttr) MarshalBinary() ([]byte, error) { + b := []byte{} + b = marshalString(b, p.Name) + b = marshalString(b, p.LongName) + for _, attr := range p.Attrs { + b = marshal(b, attr) + } + return b, nil +} + +type sshFxpNamePacket struct { + ID uint32 + NameAttrs []sshFxpNameAttr +} + +func (p sshFxpNamePacket) MarshalBinary() ([]byte, error) { + b := []byte{} + b = append(b, ssh_FXP_NAME) + b = marshalUint32(b, p.ID) + b = marshalUint32(b, uint32(len(p.NameAttrs))) + for _, na := range p.NameAttrs { + ab, err := na.MarshalBinary() + if err != nil { + return nil, err + } + + b = append(b, ab...) + } + return b, nil +} + +type sshFxpOpenPacket struct { + ID uint32 + Path string + Pflags uint32 + Flags uint32 // ignored +} + +func (p sshFxpOpenPacket) id() uint32 { return p.ID } + +func (p sshFxpOpenPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + + 4 + len(p.Path) + + 4 + 4 + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_OPEN) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Path) + b = marshalUint32(b, p.Pflags) + b = marshalUint32(b, p.Flags) + return b, nil +} + +func (p *sshFxpOpenPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Path, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Pflags, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Flags, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + return nil +} + +type sshFxpReadPacket struct { + ID uint32 + Handle string + Offset uint64 + Len uint32 +} + +func (p sshFxpReadPacket) id() uint32 { return p.ID } + +func (p sshFxpReadPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Handle) + + 8 + 4 // uint64 + uint32 + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_READ) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Handle) + b = marshalUint64(b, p.Offset) + b = marshalUint32(b, p.Len) + return b, nil +} + +func (p *sshFxpReadPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Handle, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Offset, b, err = unmarshalUint64Safe(b); err != nil { + return err + } else if p.Len, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + return nil +} + +type sshFxpRenamePacket struct { + ID uint32 + Oldpath string + Newpath string +} + +func (p sshFxpRenamePacket) id() uint32 { return p.ID } + +func (p sshFxpRenamePacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Oldpath) + + 4 + len(p.Newpath) + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_RENAME) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Oldpath) + b = marshalString(b, p.Newpath) + return b, nil +} + +func (p *sshFxpRenamePacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Oldpath, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Newpath, b, err = unmarshalStringSafe(b); err != nil { + return err + } + return nil +} + +type sshFxpWritePacket struct { + ID uint32 + Handle string + Offset uint64 + Length uint32 + Data []byte +} + +func (p sshFxpWritePacket) id() uint32 { return p.ID } + +func (p sshFxpWritePacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Handle) + + 8 + 4 + // uint64 + uint32 + len(p.Data) + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_WRITE) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Handle) + b = marshalUint64(b, p.Offset) + b = marshalUint32(b, p.Length) + b = append(b, p.Data...) + return b, nil +} + +func (p *sshFxpWritePacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Handle, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Offset, b, err = unmarshalUint64Safe(b); err != nil { + return err + } else if p.Length, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if uint32(len(b)) < p.Length { + return errShortPacket + } + + p.Data = append([]byte{}, b[:p.Length]...) + return nil +} + +type sshFxpMkdirPacket struct { + ID uint32 + Path string + Flags uint32 // ignored +} + +func (p sshFxpMkdirPacket) id() uint32 { return p.ID } + +func (p sshFxpMkdirPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Path) + + 4 // uint32 + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_MKDIR) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Path) + b = marshalUint32(b, p.Flags) + return b, nil +} + +func (p *sshFxpMkdirPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Path, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Flags, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + return nil +} + +type sshFxpSetstatPacket struct { + ID uint32 + Path string + Flags uint32 + Attrs interface{} +} + +type sshFxpFsetstatPacket struct { + ID uint32 + Handle string + Flags uint32 + Attrs interface{} +} + +func (p sshFxpSetstatPacket) id() uint32 { return p.ID } +func (p sshFxpFsetstatPacket) id() uint32 { return p.ID } + +func (p sshFxpSetstatPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Path) + + 4 // uint32 + uint64 + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_SETSTAT) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Path) + b = marshalUint32(b, p.Flags) + b = marshal(b, p.Attrs) + return b, nil +} + +func (p sshFxpFsetstatPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + 4 + len(p.Handle) + + 4 // uint32 + uint64 + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_FSETSTAT) + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Handle) + b = marshalUint32(b, p.Flags) + b = marshal(b, p.Attrs) + return b, nil +} + +func (p *sshFxpSetstatPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Path, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Flags, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + p.Attrs = b + return nil +} + +func (p *sshFxpFsetstatPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Handle, b, err = unmarshalStringSafe(b); err != nil { + return err + } else if p.Flags, b, err = unmarshalUint32Safe(b); err != nil { + return err + } + p.Attrs = b + return nil +} + +type sshFxpHandlePacket struct { + ID uint32 + Handle string +} + +func (p sshFxpHandlePacket) MarshalBinary() ([]byte, error) { + b := []byte{ssh_FXP_HANDLE} + b = marshalUint32(b, p.ID) + b = marshalString(b, p.Handle) + return b, nil +} + +type sshFxpStatusPacket struct { + ID uint32 + StatusError +} + +func (p sshFxpStatusPacket) MarshalBinary() ([]byte, error) { + b := []byte{ssh_FXP_STATUS} + b = marshalUint32(b, p.ID) + b = marshalStatus(b, p.StatusError) + return b, nil +} + +type sshFxpDataPacket struct { + ID uint32 + Length uint32 + Data []byte +} + +func (p sshFxpDataPacket) MarshalBinary() ([]byte, error) { + b := []byte{ssh_FXP_DATA} + b = marshalUint32(b, p.ID) + b = marshalUint32(b, p.Length) + b = append(b, p.Data[:p.Length]...) + return b, nil +} + +func (p *sshFxpDataPacket) UnmarshalBinary(b []byte) error { + var err error + if p.ID, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if p.Length, b, err = unmarshalUint32Safe(b); err != nil { + return err + } else if uint32(len(b)) < p.Length { + return errors.New("truncated packet") + } + + p.Data = make([]byte, p.Length) + copy(p.Data, b) + return nil +} + +type sshFxpStatvfsPacket struct { + ID uint32 + Path string +} + +func (p sshFxpStatvfsPacket) id() uint32 { return p.ID } + +func (p sshFxpStatvfsPacket) MarshalBinary() ([]byte, error) { + l := 1 + 4 + // type(byte) + uint32 + len(p.Path) + + len("statvfs@openssh.com") + + b := make([]byte, 0, l) + b = append(b, ssh_FXP_EXTENDED) + b = marshalUint32(b, p.ID) + b = marshalString(b, "statvfs@openssh.com") + b = marshalString(b, p.Path) + return b, nil +} + +// A StatVFS contains statistics about a filesystem. +type StatVFS struct { + ID uint32 + Bsize uint64 /* file system block size */ + Frsize uint64 /* fundamental fs block size */ + Blocks uint64 /* number of blocks (unit f_frsize) */ + Bfree uint64 /* free blocks in file system */ + Bavail uint64 /* free blocks for non-root */ + Files uint64 /* total file inodes */ + Ffree uint64 /* free file inodes */ + Favail uint64 /* free file inodes for to non-root */ + Fsid uint64 /* file system id */ + Flag uint64 /* bit mask of f_flag values */ + Namemax uint64 /* maximum filename length */ +} + +// TotalSpace calculates the amount of total space in a filesystem. +func (p *StatVFS) TotalSpace() uint64 { + return p.Frsize * p.Blocks +} + +// FreeSpace calculates the amount of free space in a filesystem. +func (p *StatVFS) FreeSpace() uint64 { + return p.Frsize * p.Bfree +} diff --git a/vendor/github.com/pkg/sftp/release.go b/vendor/github.com/pkg/sftp/release.go new file mode 100644 index 000000000..b695528fd --- /dev/null +++ b/vendor/github.com/pkg/sftp/release.go @@ -0,0 +1,5 @@ +// +build !debug + +package sftp + +func debug(fmt string, args ...interface{}) {} diff --git a/vendor/github.com/pkg/sftp/server.go b/vendor/github.com/pkg/sftp/server.go new file mode 100644 index 000000000..81b165917 --- /dev/null +++ b/vendor/github.com/pkg/sftp/server.go @@ -0,0 +1,648 @@ +package sftp + +// sftp server counterpart + +import ( + "encoding" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "sync" + "syscall" + "time" +) + +const ( + sftpServerWorkerCount = 8 +) + +// Server is an SSH File Transfer Protocol (sftp) server. +// This is intended to provide the sftp subsystem to an ssh server daemon. +// This implementation currently supports most of sftp server protocol version 3, +// as specified at http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 +type Server struct { + in io.Reader + out io.WriteCloser + outMutex *sync.Mutex + debugStream io.Writer + readOnly bool + lastID uint32 + pktChan chan rxPacket + openFiles map[string]*os.File + openFilesLock *sync.RWMutex + handleCount int + maxTxPacket uint32 + workerCount int +} + +func (svr *Server) nextHandle(f *os.File) string { + svr.openFilesLock.Lock() + defer svr.openFilesLock.Unlock() + svr.handleCount++ + handle := strconv.Itoa(svr.handleCount) + svr.openFiles[handle] = f + return handle +} + +func (svr *Server) closeHandle(handle string) error { + svr.openFilesLock.Lock() + defer svr.openFilesLock.Unlock() + if f, ok := svr.openFiles[handle]; ok { + delete(svr.openFiles, handle) + return f.Close() + } + + return syscall.EBADF +} + +func (svr *Server) getHandle(handle string) (*os.File, bool) { + svr.openFilesLock.RLock() + defer svr.openFilesLock.RUnlock() + f, ok := svr.openFiles[handle] + return f, ok +} + +type serverRespondablePacket interface { + encoding.BinaryUnmarshaler + id() uint32 + respond(svr *Server) error + readonly() bool +} + +// NewServer creates a new Server instance around the provided streams, serving +// content from the root of the filesystem. Optionally, ServerOption +// functions may be specified to further configure the Server. +// +// A subsequent call to Serve() is required to begin serving files over SFTP. +func NewServer(in io.Reader, out io.WriteCloser, options ...ServerOption) (*Server, error) { + s := &Server{ + in: in, + out: out, + outMutex: &sync.Mutex{}, + debugStream: ioutil.Discard, + pktChan: make(chan rxPacket, sftpServerWorkerCount), + openFiles: map[string]*os.File{}, + openFilesLock: &sync.RWMutex{}, + maxTxPacket: 1 << 15, + workerCount: sftpServerWorkerCount, + } + + for _, o := range options { + if err := o(s); err != nil { + return nil, err + } + } + + return s, nil +} + +// A ServerOption is a function which applies configuration to a Server. +type ServerOption func(*Server) error + +// WithDebug enables Server debugging output to the supplied io.Writer. +func WithDebug(w io.Writer) ServerOption { + return func(s *Server) error { + s.debugStream = w + return nil + } +} + +// ReadOnly configures a Server to serve files in read-only mode. +func ReadOnly() ServerOption { + return func(s *Server) error { + s.readOnly = true + return nil + } +} + +type rxPacket struct { + pktType fxp + pktBytes []byte +} + +// Unmarshal a single logical packet from the secure channel +func (svr *Server) rxPackets() error { + defer close(svr.pktChan) + + for { + pktType, pktBytes, err := recvPacket(svr.in) + switch err { + case nil: + svr.pktChan <- rxPacket{fxp(pktType), pktBytes} + case io.EOF: + return nil + default: + fmt.Fprintf(svr.debugStream, "recvPacket error: %v\n", err) + return err + } + } +} + +// Up to N parallel servers +func (svr *Server) sftpServerWorker(doneChan chan error) { + for pkt := range svr.pktChan { + dPkt, err := svr.decodePacket(pkt.pktType, pkt.pktBytes) + if err != nil { + fmt.Fprintf(svr.debugStream, "decodePacket error: %v\n", err) + doneChan <- err + return + } + + // If server is operating read-only and a write operation is requested, + // return permission denied + if !dPkt.readonly() && svr.readOnly { + _ = svr.sendPacket(statusFromError(dPkt.id(), syscall.EPERM)) + continue + } + + _ = dPkt.respond(svr) + } + doneChan <- nil +} + +// Serve serves SFTP connections until the streams stop or the SFTP subsystem +// is stopped. +func (svr *Server) Serve() error { + go svr.rxPackets() + doneChan := make(chan error) + for i := 0; i < svr.workerCount; i++ { + go svr.sftpServerWorker(doneChan) + } + for i := 0; i < svr.workerCount; i++ { + if err := <-doneChan; err != nil { + // abort early and shut down the session on un-decodable packets + break + } + } + // close any still-open files + for handle, file := range svr.openFiles { + fmt.Fprintf(svr.debugStream, "sftp server file with handle '%v' left open: %v\n", handle, file.Name()) + file.Close() + } + return svr.out.Close() +} + +func (svr *Server) decodePacket(pktType fxp, pktBytes []byte) (serverRespondablePacket, error) { + var pkt serverRespondablePacket + switch pktType { + case ssh_FXP_INIT: + pkt = &sshFxInitPacket{} + case ssh_FXP_LSTAT: + pkt = &sshFxpLstatPacket{} + case ssh_FXP_OPEN: + pkt = &sshFxpOpenPacket{} + case ssh_FXP_CLOSE: + pkt = &sshFxpClosePacket{} + case ssh_FXP_READ: + pkt = &sshFxpReadPacket{} + case ssh_FXP_WRITE: + pkt = &sshFxpWritePacket{} + case ssh_FXP_FSTAT: + pkt = &sshFxpFstatPacket{} + case ssh_FXP_SETSTAT: + pkt = &sshFxpSetstatPacket{} + case ssh_FXP_FSETSTAT: + pkt = &sshFxpFsetstatPacket{} + case ssh_FXP_OPENDIR: + pkt = &sshFxpOpendirPacket{} + case ssh_FXP_READDIR: + pkt = &sshFxpReaddirPacket{} + case ssh_FXP_REMOVE: + pkt = &sshFxpRemovePacket{} + case ssh_FXP_MKDIR: + pkt = &sshFxpMkdirPacket{} + case ssh_FXP_RMDIR: + pkt = &sshFxpRmdirPacket{} + case ssh_FXP_REALPATH: + pkt = &sshFxpRealpathPacket{} + case ssh_FXP_STAT: + pkt = &sshFxpStatPacket{} + case ssh_FXP_RENAME: + pkt = &sshFxpRenamePacket{} + case ssh_FXP_READLINK: + pkt = &sshFxpReadlinkPacket{} + case ssh_FXP_SYMLINK: + pkt = &sshFxpSymlinkPacket{} + default: + return nil, fmt.Errorf("unhandled packet type: %s", pktType) + } + err := pkt.UnmarshalBinary(pktBytes) + return pkt, err +} + +func (p sshFxInitPacket) respond(svr *Server) error { + return svr.sendPacket(sshFxVersionPacket{sftpProtocolVersion, nil}) +} + +// The init packet has no ID, so we just return a zero-value ID +func (p sshFxInitPacket) id() uint32 { return 0 } +func (p sshFxInitPacket) readonly() bool { return true } + +type sshFxpStatResponse struct { + ID uint32 + info os.FileInfo +} + +func (p sshFxpStatResponse) MarshalBinary() ([]byte, error) { + b := []byte{ssh_FXP_ATTRS} + b = marshalUint32(b, p.ID) + b = marshalFileInfo(b, p.info) + return b, nil +} + +func (p sshFxpLstatPacket) readonly() bool { return true } + +func (p sshFxpLstatPacket) respond(svr *Server) error { + // stat the requested file + info, err := os.Lstat(p.Path) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + return svr.sendPacket(sshFxpStatResponse{ + ID: p.ID, + info: info, + }) +} + +func (p sshFxpStatPacket) readonly() bool { return true } + +func (p sshFxpStatPacket) respond(svr *Server) error { + // stat the requested file + info, err := os.Stat(p.Path) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + return svr.sendPacket(sshFxpStatResponse{ + ID: p.ID, + info: info, + }) +} + +func (p sshFxpFstatPacket) readonly() bool { return true } + +func (p sshFxpFstatPacket) respond(svr *Server) error { + f, ok := svr.getHandle(p.Handle) + if !ok { + return svr.sendPacket(statusFromError(p.ID, syscall.EBADF)) + } + + info, err := f.Stat() + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + return svr.sendPacket(sshFxpStatResponse{ + ID: p.ID, + info: info, + }) +} + +func (p sshFxpMkdirPacket) readonly() bool { return false } + +func (p sshFxpMkdirPacket) respond(svr *Server) error { + // TODO FIXME: ignore flags field + err := os.Mkdir(p.Path, 0755) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpRmdirPacket) readonly() bool { return false } + +func (p sshFxpRmdirPacket) respond(svr *Server) error { + err := os.Remove(p.Path) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpRemovePacket) readonly() bool { return false } + +func (p sshFxpRemovePacket) respond(svr *Server) error { + err := os.Remove(p.Filename) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpRenamePacket) readonly() bool { return false } + +func (p sshFxpRenamePacket) respond(svr *Server) error { + err := os.Rename(p.Oldpath, p.Newpath) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpSymlinkPacket) readonly() bool { return false } + +func (p sshFxpSymlinkPacket) respond(svr *Server) error { + err := os.Symlink(p.Targetpath, p.Linkpath) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +var emptyFileStat = []interface{}{uint32(0)} + +func (p sshFxpReadlinkPacket) readonly() bool { return true } + +func (p sshFxpReadlinkPacket) respond(svr *Server) error { + f, err := os.Readlink(p.Path) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + return svr.sendPacket(sshFxpNamePacket{ + ID: p.ID, + NameAttrs: []sshFxpNameAttr{{ + Name: f, + LongName: f, + Attrs: emptyFileStat, + }}, + }) +} + +func (p sshFxpRealpathPacket) readonly() bool { return true } + +func (p sshFxpRealpathPacket) respond(svr *Server) error { + f, err := filepath.Abs(p.Path) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + f = filepath.Clean(f) + + return svr.sendPacket(sshFxpNamePacket{ + ID: p.ID, + NameAttrs: []sshFxpNameAttr{{ + Name: f, + LongName: f, + Attrs: emptyFileStat, + }}, + }) +} + +func (p sshFxpOpendirPacket) readonly() bool { return true } + +func (p sshFxpOpendirPacket) respond(svr *Server) error { + return sshFxpOpenPacket{ + ID: p.ID, + Path: p.Path, + Pflags: ssh_FXF_READ, + }.respond(svr) +} + +func (p sshFxpOpenPacket) readonly() bool { + return !p.hasPflags(ssh_FXF_WRITE) +} + +func (p sshFxpOpenPacket) hasPflags(flags ...uint32) bool { + for _, f := range flags { + if p.Pflags&f == 0 { + return false + } + } + + return true +} + +func (p sshFxpOpenPacket) respond(svr *Server) error { + var osFlags int + if p.hasPflags(ssh_FXF_READ, ssh_FXF_WRITE) { + osFlags |= os.O_RDWR + } else if p.hasPflags(ssh_FXF_WRITE) { + osFlags |= os.O_WRONLY + } else if p.hasPflags(ssh_FXF_READ) { + osFlags |= os.O_RDONLY + } else { + // how are they opening? + return svr.sendPacket(statusFromError(p.ID, syscall.EINVAL)) + } + + if p.hasPflags(ssh_FXF_APPEND) { + osFlags |= os.O_APPEND + } + if p.hasPflags(ssh_FXF_CREAT) { + osFlags |= os.O_CREATE + } + if p.hasPflags(ssh_FXF_TRUNC) { + osFlags |= os.O_TRUNC + } + if p.hasPflags(ssh_FXF_EXCL) { + osFlags |= os.O_EXCL + } + + f, err := os.OpenFile(p.Path, osFlags, 0644) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + handle := svr.nextHandle(f) + return svr.sendPacket(sshFxpHandlePacket{p.ID, handle}) +} + +func (p sshFxpClosePacket) readonly() bool { return true } + +func (p sshFxpClosePacket) respond(svr *Server) error { + return svr.sendPacket(statusFromError(p.ID, svr.closeHandle(p.Handle))) +} + +func (p sshFxpReadPacket) readonly() bool { return true } + +func (p sshFxpReadPacket) respond(svr *Server) error { + f, ok := svr.getHandle(p.Handle) + if !ok { + return svr.sendPacket(statusFromError(p.ID, syscall.EBADF)) + } + + if p.Len > svr.maxTxPacket { + p.Len = svr.maxTxPacket + } + ret := sshFxpDataPacket{ + ID: p.ID, + Length: p.Len, + Data: make([]byte, p.Len), + } + + n, err := f.ReadAt(ret.Data, int64(p.Offset)) + if err != nil && (err != io.EOF || n == 0) { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + ret.Length = uint32(n) + return svr.sendPacket(ret) +} + +func (p sshFxpWritePacket) readonly() bool { return false } + +func (p sshFxpWritePacket) respond(svr *Server) error { + f, ok := svr.getHandle(p.Handle) + if !ok { + return svr.sendPacket(statusFromError(p.ID, syscall.EBADF)) + } + + _, err := f.WriteAt(p.Data, int64(p.Offset)) + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpReaddirPacket) readonly() bool { return true } + +func (p sshFxpReaddirPacket) respond(svr *Server) error { + f, ok := svr.getHandle(p.Handle) + if !ok { + return svr.sendPacket(statusFromError(p.ID, syscall.EBADF)) + } + + dirname := f.Name() + dirents, err := f.Readdir(128) + if err != nil { + return svr.sendPacket(statusFromError(p.ID, err)) + } + + ret := sshFxpNamePacket{ID: p.ID} + for _, dirent := range dirents { + ret.NameAttrs = append(ret.NameAttrs, sshFxpNameAttr{ + Name: dirent.Name(), + LongName: runLs(dirname, dirent), + Attrs: []interface{}{dirent}, + }) + } + return svr.sendPacket(ret) +} + +func (p sshFxpSetstatPacket) readonly() bool { return false } + +func (p sshFxpSetstatPacket) respond(svr *Server) error { + // additional unmarshalling is required for each possibility here + b := p.Attrs.([]byte) + var err error + + debug("setstat name \"%s\"", p.Path) + if (p.Flags & ssh_FILEXFER_ATTR_SIZE) != 0 { + var size uint64 + if size, b, err = unmarshalUint64Safe(b); err == nil { + err = os.Truncate(p.Path, int64(size)) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_PERMISSIONS) != 0 { + var mode uint32 + if mode, b, err = unmarshalUint32Safe(b); err == nil { + err = os.Chmod(p.Path, os.FileMode(mode)) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_ACMODTIME) != 0 { + var atime uint32 + var mtime uint32 + if atime, b, err = unmarshalUint32Safe(b); err != nil { + } else if mtime, b, err = unmarshalUint32Safe(b); err != nil { + } else { + atimeT := time.Unix(int64(atime), 0) + mtimeT := time.Unix(int64(mtime), 0) + err = os.Chtimes(p.Path, atimeT, mtimeT) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_UIDGID) != 0 { + var uid uint32 + var gid uint32 + if uid, b, err = unmarshalUint32Safe(b); err != nil { + } else if gid, b, err = unmarshalUint32Safe(b); err != nil { + } else { + err = os.Chown(p.Path, int(uid), int(gid)) + } + } + + return svr.sendPacket(statusFromError(p.ID, err)) +} + +func (p sshFxpFsetstatPacket) readonly() bool { return false } + +func (p sshFxpFsetstatPacket) respond(svr *Server) error { + f, ok := svr.getHandle(p.Handle) + if !ok { + return svr.sendPacket(statusFromError(p.ID, syscall.EBADF)) + } + + // additional unmarshalling is required for each possibility here + b := p.Attrs.([]byte) + var err error + + debug("fsetstat name \"%s\"", f.Name()) + if (p.Flags & ssh_FILEXFER_ATTR_SIZE) != 0 { + var size uint64 + if size, b, err = unmarshalUint64Safe(b); err == nil { + err = f.Truncate(int64(size)) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_PERMISSIONS) != 0 { + var mode uint32 + if mode, b, err = unmarshalUint32Safe(b); err == nil { + err = f.Chmod(os.FileMode(mode)) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_ACMODTIME) != 0 { + var atime uint32 + var mtime uint32 + if atime, b, err = unmarshalUint32Safe(b); err != nil { + } else if mtime, b, err = unmarshalUint32Safe(b); err != nil { + } else { + atimeT := time.Unix(int64(atime), 0) + mtimeT := time.Unix(int64(mtime), 0) + err = os.Chtimes(f.Name(), atimeT, mtimeT) + } + } + if (p.Flags & ssh_FILEXFER_ATTR_UIDGID) != 0 { + var uid uint32 + var gid uint32 + if uid, b, err = unmarshalUint32Safe(b); err != nil { + } else if gid, b, err = unmarshalUint32Safe(b); err != nil { + } else { + err = f.Chown(int(uid), int(gid)) + } + } + + return svr.sendPacket(statusFromError(p.ID, err)) +} + +// translateErrno translates a syscall error number to a SFTP error code. +func translateErrno(errno syscall.Errno) uint32 { + switch errno { + case 0: + return ssh_FX_OK + case syscall.ENOENT: + return ssh_FX_NO_SUCH_FILE + case syscall.EPERM: + return ssh_FX_PERMISSION_DENIED + } + + return ssh_FX_FAILURE +} + +func statusFromError(id uint32, err error) sshFxpStatusPacket { + ret := sshFxpStatusPacket{ + ID: id, + StatusError: StatusError{ + // ssh_FX_OK = 0 + // ssh_FX_EOF = 1 + // ssh_FX_NO_SUCH_FILE = 2 ENOENT + // ssh_FX_PERMISSION_DENIED = 3 + // ssh_FX_FAILURE = 4 + // ssh_FX_BAD_MESSAGE = 5 + // ssh_FX_NO_CONNECTION = 6 + // ssh_FX_CONNECTION_LOST = 7 + // ssh_FX_OP_UNSUPPORTED = 8 + Code: ssh_FX_OK, + }, + } + if err != nil { + debug("statusFromError: error is %T %#v", err, err) + ret.StatusError.Code = ssh_FX_FAILURE + ret.StatusError.msg = err.Error() + if err == io.EOF { + ret.StatusError.Code = ssh_FX_EOF + } else if errno, ok := err.(syscall.Errno); ok { + ret.StatusError.Code = translateErrno(errno) + } else if pathError, ok := err.(*os.PathError); ok { + debug("statusFromError: error is %T %#v", pathError.Err, pathError.Err) + if errno, ok := pathError.Err.(syscall.Errno); ok { + ret.StatusError.Code = translateErrno(errno) + } + } + } + return ret +} diff --git a/vendor/github.com/pkg/sftp/server_standalone/main.go b/vendor/github.com/pkg/sftp/server_standalone/main.go new file mode 100644 index 000000000..f7fcccdee --- /dev/null +++ b/vendor/github.com/pkg/sftp/server_standalone/main.go @@ -0,0 +1,40 @@ +package main + +// small wrapper around sftp server that allows it to be used as a separate process subsystem call by the ssh server. +// in practice this will statically link; however this allows unit testing from the sftp client. + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + + "github.com/pkg/sftp" +) + +func main() { + var ( + readOnly bool + debugStderr bool + ) + + flag.BoolVar(&readOnly, "R", false, "read-only server") + flag.BoolVar(&debugStderr, "e", false, "debug to stderr") + flag.Parse() + + debugStream := ioutil.Discard + if debugStderr { + debugStream = os.Stderr + } + + svr, _ := sftp.NewServer( + os.Stdin, + os.Stdout, + sftp.WithDebug(debugStream), + sftp.ReadOnly(), + ) + if err := svr.Serve(); err != nil { + fmt.Fprintf(debugStream, "sftp server completed with error: %v", err) + os.Exit(1) + } +} diff --git a/vendor/github.com/pkg/sftp/server_stubs.go b/vendor/github.com/pkg/sftp/server_stubs.go new file mode 100644 index 000000000..3b1ddbdbb --- /dev/null +++ b/vendor/github.com/pkg/sftp/server_stubs.go @@ -0,0 +1,12 @@ +// +build !cgo,!plan9 windows android + +package sftp + +import ( + "os" + "path" +) + +func runLs(dirname string, dirent os.FileInfo) string { + return path.Join(dirname, dirent.Name()) +} diff --git a/vendor/github.com/pkg/sftp/server_unix.go b/vendor/github.com/pkg/sftp/server_unix.go new file mode 100644 index 000000000..8c3f0b44e --- /dev/null +++ b/vendor/github.com/pkg/sftp/server_unix.go @@ -0,0 +1,143 @@ +// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris +// +build cgo + +package sftp + +import ( + "fmt" + "os" + "path" + "syscall" + "time" +) + +func runLsTypeWord(dirent os.FileInfo) string { + // find first character, the type char + // b Block special file. + // c Character special file. + // d Directory. + // l Symbolic link. + // s Socket link. + // p FIFO. + // - Regular file. + tc := '-' + mode := dirent.Mode() + if (mode & os.ModeDir) != 0 { + tc = 'd' + } else if (mode & os.ModeDevice) != 0 { + tc = 'b' + if (mode & os.ModeCharDevice) != 0 { + tc = 'c' + } + } else if (mode & os.ModeSymlink) != 0 { + tc = 'l' + } else if (mode & os.ModeSocket) != 0 { + tc = 's' + } else if (mode & os.ModeNamedPipe) != 0 { + tc = 'p' + } + + // owner + orc := '-' + if (mode & 0400) != 0 { + orc = 'r' + } + owc := '-' + if (mode & 0200) != 0 { + owc = 'w' + } + oxc := '-' + ox := (mode & 0100) != 0 + setuid := (mode & os.ModeSetuid) != 0 + if ox && setuid { + oxc = 's' + } else if setuid { + oxc = 'S' + } else if ox { + oxc = 'x' + } + + // group + grc := '-' + if (mode & 040) != 0 { + grc = 'r' + } + gwc := '-' + if (mode & 020) != 0 { + gwc = 'w' + } + gxc := '-' + gx := (mode & 010) != 0 + setgid := (mode & os.ModeSetgid) != 0 + if gx && setgid { + gxc = 's' + } else if setgid { + gxc = 'S' + } else if gx { + gxc = 'x' + } + + // all / others + arc := '-' + if (mode & 04) != 0 { + arc = 'r' + } + awc := '-' + if (mode & 02) != 0 { + awc = 'w' + } + axc := '-' + ax := (mode & 01) != 0 + sticky := (mode & os.ModeSticky) != 0 + if ax && sticky { + axc = 't' + } else if sticky { + axc = 'T' + } else if ax { + axc = 'x' + } + + return fmt.Sprintf("%c%c%c%c%c%c%c%c%c%c", tc, orc, owc, oxc, grc, gwc, gxc, arc, awc, axc) +} + +func runLsStatt(dirname string, dirent os.FileInfo, statt *syscall.Stat_t) string { + // example from openssh sftp server: + // crw-rw-rw- 1 root wheel 0 Jul 31 20:52 ttyvd + // format: + // {directory / char device / etc}{rwxrwxrwx} {number of links} owner group size month day [time (this year) | year (otherwise)] name + + typeword := runLsTypeWord(dirent) + numLinks := statt.Nlink + uid := statt.Uid + gid := statt.Gid + username := fmt.Sprintf("%d", uid) + groupname := fmt.Sprintf("%d", gid) + // TODO FIXME: uid -> username, gid -> groupname lookup for ls -l format output + + mtime := dirent.ModTime() + monthStr := mtime.Month().String()[0:3] + day := mtime.Day() + year := mtime.Year() + now := time.Now() + isOld := mtime.Before(now.Add(-time.Hour * 24 * 365 / 2)) + + yearOrTime := fmt.Sprintf("%02d:%02d", mtime.Hour(), mtime.Minute()) + if isOld { + yearOrTime = fmt.Sprintf("%d", year) + } + + return fmt.Sprintf("%s %4d %-8s %-8s %8d %s %2d %5s %s", typeword, numLinks, username, groupname, dirent.Size(), monthStr, day, yearOrTime, dirent.Name()) +} + +// ls -l style output for a file, which is in the 'long output' section of a readdir response packet +// this is a very simple (lazy) implementation, just enough to look almost like openssh in a few basic cases +func runLs(dirname string, dirent os.FileInfo) string { + dsys := dirent.Sys() + if dsys == nil { + } else if statt, ok := dsys.(*syscall.Stat_t); !ok { + } else { + return runLsStatt(dirname, dirent, statt) + } + + return path.Join(dirname, dirent.Name()) +} diff --git a/vendor/github.com/pkg/sftp/sftp.go b/vendor/github.com/pkg/sftp/sftp.go new file mode 100644 index 000000000..7d96660f8 --- /dev/null +++ b/vendor/github.com/pkg/sftp/sftp.go @@ -0,0 +1,215 @@ +// Package sftp implements the SSH File Transfer Protocol as described in +// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt +package sftp + +import ( + "fmt" +) + +const ( + ssh_FXP_INIT = 1 + ssh_FXP_VERSION = 2 + ssh_FXP_OPEN = 3 + ssh_FXP_CLOSE = 4 + ssh_FXP_READ = 5 + ssh_FXP_WRITE = 6 + ssh_FXP_LSTAT = 7 + ssh_FXP_FSTAT = 8 + ssh_FXP_SETSTAT = 9 + ssh_FXP_FSETSTAT = 10 + ssh_FXP_OPENDIR = 11 + ssh_FXP_READDIR = 12 + ssh_FXP_REMOVE = 13 + ssh_FXP_MKDIR = 14 + ssh_FXP_RMDIR = 15 + ssh_FXP_REALPATH = 16 + ssh_FXP_STAT = 17 + ssh_FXP_RENAME = 18 + ssh_FXP_READLINK = 19 + ssh_FXP_SYMLINK = 20 + ssh_FXP_STATUS = 101 + ssh_FXP_HANDLE = 102 + ssh_FXP_DATA = 103 + ssh_FXP_NAME = 104 + ssh_FXP_ATTRS = 105 + ssh_FXP_EXTENDED = 200 + ssh_FXP_EXTENDED_REPLY = 201 +) + +const ( + ssh_FX_OK = 0 + ssh_FX_EOF = 1 + ssh_FX_NO_SUCH_FILE = 2 + ssh_FX_PERMISSION_DENIED = 3 + ssh_FX_FAILURE = 4 + ssh_FX_BAD_MESSAGE = 5 + ssh_FX_NO_CONNECTION = 6 + ssh_FX_CONNECTION_LOST = 7 + ssh_FX_OP_UNSUPPORTED = 8 + + // see draft-ietf-secsh-filexfer-13 + // https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1 + ssh_FX_INVALID_HANDLE = 9 + ssh_FX_NO_SUCH_PATH = 10 + ssh_FX_FILE_ALREADY_EXISTS = 11 + ssh_FX_WRITE_PROTECT = 12 + ssh_FX_NO_MEDIA = 13 + ssh_FX_NO_SPACE_ON_FILESYSTEM = 14 + ssh_FX_QUOTA_EXCEEDED = 15 + ssh_FX_UNKNOWN_PRINCIPAL = 16 + ssh_FX_LOCK_CONFLICT = 17 + ssh_FX_DIR_NOT_EMPTY = 18 + ssh_FX_NOT_A_DIRECTORY = 19 + ssh_FX_INVALID_FILENAME = 20 + ssh_FX_LINK_LOOP = 21 + ssh_FX_CANNOT_DELETE = 22 + ssh_FX_INVALID_PARAMETER = 23 + ssh_FX_FILE_IS_A_DIRECTORY = 24 + ssh_FX_BYTE_RANGE_LOCK_CONFLICT = 25 + ssh_FX_BYTE_RANGE_LOCK_REFUSED = 26 + ssh_FX_DELETE_PENDING = 27 + ssh_FX_FILE_CORRUPT = 28 + ssh_FX_OWNER_INVALID = 29 + ssh_FX_GROUP_INVALID = 30 + ssh_FX_NO_MATCHING_BYTE_RANGE_LOCK = 31 +) + +const ( + ssh_FXF_READ = 0x00000001 + ssh_FXF_WRITE = 0x00000002 + ssh_FXF_APPEND = 0x00000004 + ssh_FXF_CREAT = 0x00000008 + ssh_FXF_TRUNC = 0x00000010 + ssh_FXF_EXCL = 0x00000020 +) + +type fxp uint8 + +func (f fxp) String() string { + switch f { + case ssh_FXP_INIT: + return "SSH_FXP_INIT" + case ssh_FXP_VERSION: + return "SSH_FXP_VERSION" + case ssh_FXP_OPEN: + return "SSH_FXP_OPEN" + case ssh_FXP_CLOSE: + return "SSH_FXP_CLOSE" + case ssh_FXP_READ: + return "SSH_FXP_READ" + case ssh_FXP_WRITE: + return "SSH_FXP_WRITE" + case ssh_FXP_LSTAT: + return "SSH_FXP_LSTAT" + case ssh_FXP_FSTAT: + return "SSH_FXP_FSTAT" + case ssh_FXP_SETSTAT: + return "SSH_FXP_SETSTAT" + case ssh_FXP_FSETSTAT: + return "SSH_FXP_FSETSTAT" + case ssh_FXP_OPENDIR: + return "SSH_FXP_OPENDIR" + case ssh_FXP_READDIR: + return "SSH_FXP_READDIR" + case ssh_FXP_REMOVE: + return "SSH_FXP_REMOVE" + case ssh_FXP_MKDIR: + return "SSH_FXP_MKDIR" + case ssh_FXP_RMDIR: + return "SSH_FXP_RMDIR" + case ssh_FXP_REALPATH: + return "SSH_FXP_REALPATH" + case ssh_FXP_STAT: + return "SSH_FXP_STAT" + case ssh_FXP_RENAME: + return "SSH_FXP_RENAME" + case ssh_FXP_READLINK: + return "SSH_FXP_READLINK" + case ssh_FXP_SYMLINK: + return "SSH_FXP_SYMLINK" + case ssh_FXP_STATUS: + return "SSH_FXP_STATUS" + case ssh_FXP_HANDLE: + return "SSH_FXP_HANDLE" + case ssh_FXP_DATA: + return "SSH_FXP_DATA" + case ssh_FXP_NAME: + return "SSH_FXP_NAME" + case ssh_FXP_ATTRS: + return "SSH_FXP_ATTRS" + case ssh_FXP_EXTENDED: + return "SSH_FXP_EXTENDED" + case ssh_FXP_EXTENDED_REPLY: + return "SSH_FXP_EXTENDED_REPLY" + default: + return "unknown" + } +} + +type fx uint8 + +func (f fx) String() string { + switch f { + case ssh_FX_OK: + return "SSH_FX_OK" + case ssh_FX_EOF: + return "SSH_FX_EOF" + case ssh_FX_NO_SUCH_FILE: + return "SSH_FX_NO_SUCH_FILE" + case ssh_FX_PERMISSION_DENIED: + return "SSH_FX_PERMISSION_DENIED" + case ssh_FX_FAILURE: + return "SSH_FX_FAILURE" + case ssh_FX_BAD_MESSAGE: + return "SSH_FX_BAD_MESSAGE" + case ssh_FX_NO_CONNECTION: + return "SSH_FX_NO_CONNECTION" + case ssh_FX_CONNECTION_LOST: + return "SSH_FX_CONNECTION_LOST" + case ssh_FX_OP_UNSUPPORTED: + return "SSH_FX_OP_UNSUPPORTED" + default: + return "unknown" + } +} + +type unexpectedPacketErr struct { + want, got uint8 +} + +func (u *unexpectedPacketErr) Error() string { + return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got)) +} + +func unimplementedPacketErr(u uint8) error { + return fmt.Errorf("sftp: unimplemented packet type: got %v", fxp(u)) +} + +type unexpectedIDErr struct{ want, got uint32 } + +func (u *unexpectedIDErr) Error() string { + return fmt.Sprintf("sftp: unexpected id: want %v, got %v", u.want, u.got) +} + +func unimplementedSeekWhence(whence int) error { + return fmt.Errorf("sftp: unimplemented seek whence %v", whence) +} + +func unexpectedCount(want, got uint32) error { + return fmt.Errorf("sftp: unexpected count: want %v, got %v", want, got) +} + +type unexpectedVersionErr struct{ want, got uint32 } + +func (u *unexpectedVersionErr) Error() string { + return fmt.Sprintf("sftp: unexpected server version: want %v, got %v", u.want, u.got) +} + +// A StatusError is returned when an SFTP operation fails, and provides +// additional information about the failure. +type StatusError struct { + Code uint32 + msg, lang string +} + +func (s *StatusError) Error() string { return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code)) } diff --git a/vendor/github.com/rackspace/gophercloud/.travis.yml b/vendor/github.com/rackspace/gophercloud/.travis.yml new file mode 100644 index 000000000..325b90ac8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/.travis.yml @@ -0,0 +1,16 @@ +language: go +install: + - go get -v -tags 'fixtures acceptance' ./... +go: + - 1.2 + - 1.3 + - 1.4 + - 1.5 +script: script/cibuild +after_success: + - go get golang.org/x/tools/cmd/cover + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - export PATH=$PATH:$HOME/gopath/bin/ + - goveralls 2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8 +sudo: false diff --git a/vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md b/vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md new file mode 100644 index 000000000..6ba5beb85 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md @@ -0,0 +1,274 @@ +# Contributing to gophercloud + +- [Getting started](#getting-started) +- [Tests](#tests) +- [Style guide](#basic-style-guide) +- [5 ways to get involved](#5-ways-to-get-involved) + +## Setting up your git workspace + +As a contributor you will need to setup your workspace in a slightly different +way than just downloading it. Here are the basic installation instructions: + +1. Configure your `$GOPATH` and run `go get` as described in the main +[README](/README.md#how-to-install). + +2. Move into the directory that houses your local repository: + + ```bash + cd ${GOPATH}/src/github.com/rackspace/gophercloud + ``` + +3. Fork the `rackspace/gophercloud` repository and update your remote refs. You +will need to rename the `origin` remote branch to `upstream`, and add your +fork as `origin` instead: + + ```bash + git remote rename origin upstream + git remote add origin git@github.com//gophercloud + ``` + +4. Checkout the latest development branch: + + ```bash + git checkout master + ``` + +5. If you're working on something (discussed more in detail below), you will +need to checkout a new feature branch: + + ```bash + git checkout -b my-new-feature + ``` + +Another thing to bear in mind is that you will need to add a few extra +environment variables for acceptance tests - this is documented in our +[acceptance tests readme](/acceptance). + +## Tests + +When working on a new or existing feature, testing will be the backbone of your +work since it helps uncover and prevent regressions in the codebase. There are +two types of test we use in gophercloud: unit tests and acceptance tests, which +are both described below. + +### Unit tests + +Unit tests are the fine-grained tests that establish and ensure the behaviour +of individual units of functionality. We usually test on an +operation-by-operation basis (an operation typically being an API action) with +the use of mocking to set up explicit expectations. Each operation will set up +its HTTP response expectation, and then test how the system responds when fed +this controlled, pre-determined input. + +To make life easier, we've introduced a bunch of test helpers to simplify the +process of testing expectations with assertions: + +```go +import ( + "testing" + + "github.com/rackspace/gophercloud/testhelper" +) + +func TestSomething(t *testing.T) { + result, err := Operation() + + testhelper.AssertEquals(t, "foo", result.Bar) + testhelper.AssertNoErr(t, err) +} + +func TestSomethingElse(t *testing.T) { + testhelper.CheckEquals(t, "expected", "actual") +} +``` + +`AssertEquals` and `AssertNoErr` will throw a fatal error if a value does not +match an expected value or if an error has been declared, respectively. You can +also use `CheckEquals` and `CheckNoErr` for the same purpose; the only difference +being that `t.Errorf` is raised rather than `t.Fatalf`. + +Here is a truncated example of mocked HTTP responses: + +```go +import ( + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func TestGet(t *testing.T) { + // Setup the HTTP request multiplexer and server + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/networks/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + // Test we're using the correct HTTP method + th.TestMethod(t, r, "GET") + + // Test we're setting the auth token + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + // Set the appropriate headers for our mocked response + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + // Set the HTTP body + fmt.Fprintf(w, ` +{ + "network": { + "status": "ACTIVE", + "name": "private-network", + "admin_state_up": true, + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "shared": true, + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" + } +} + `) + }) + + // Call our API operation + network, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract() + + // Assert no errors and equality + th.AssertNoErr(t, err) + th.AssertEquals(t, n.Status, "ACTIVE") +} +``` + +### Acceptance tests + +As we've already mentioned, unit tests have a very narrow and confined focus - +they test small units of behaviour. Acceptance tests on the other hand have a +far larger scope: they are fully functional tests that test the entire API of a +service in one fell swoop. They don't care about unit isolation or mocking +expectations, they instead do a full run-through and consequently test how the +entire system _integrates_ together. When an API satisfies expectations, it +proves by default that the requirements for a contract have been met. + +Please be aware that acceptance tests will hit a live API - and may incur +service charges from your provider. Although most tests handle their own +teardown procedures, it is always worth manually checking that resources are +deleted after the test suite finishes. + +### Running tests + +To run all tests: + +```bash +go test ./... +``` + +To run all tests with verbose output: + +```bash +go test -v ./... +``` + +To run tests that match certain [build tags](): + +```bash +go test -tags "foo bar" ./... +``` + +To run tests for a particular sub-package: + +```bash +cd ./path/to/package && go test . +``` + +## Basic style guide + +We follow the standard formatting recommendations and language idioms set out +in the [Effective Go](https://golang.org/doc/effective_go.html) guide. It's +definitely worth reading - but the relevant sections are +[formatting](https://golang.org/doc/effective_go.html#formatting) +and [names](https://golang.org/doc/effective_go.html#names). + +## 5 ways to get involved + +There are five main ways you can get involved in our open-source project, and +each is described briefly below. Once you've made up your mind and decided on +your fix, you will need to follow the same basic steps that all submissions are +required to adhere to: + +1. [fork](https://help.github.com/articles/fork-a-repo/) the `rackspace/gophercloud` repository +2. checkout a [new branch](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches) +3. submit your branch as a [pull request](https://help.github.com/articles/creating-a-pull-request/) + +### 1. Providing feedback + +On of the easiest ways to get readily involved in our project is to let us know +about your experiences using our SDK. Feedback like this is incredibly useful +to us, because it allows us to refine and change features based on what our +users want and expect of us. There are a bunch of ways to get in contact! You +can [ping us](https://developer.rackspace.com/support/) via e-mail, talk to us on irc +(#rackspace-dev on freenode), [tweet us](https://twitter.com/rackspace), or +submit an issue on our [bug tracker](/issues). Things you might like to tell us +are: + +* how easy was it to start using our SDK? +* did it meet your expectations? If not, why not? +* did our documentation help or hinder you? +* what could we improve in general? + +### 2. Fixing bugs + +If you want to start fixing open bugs, we'd really appreciate that! Bug fixing +is central to any project. The best way to get started is by heading to our +[bug tracker](https://github.com/rackspace/gophercloud/issues) and finding open +bugs that you think nobody is working on. It might be useful to comment on the +thread to see the current state of the issue and if anybody has made any +breakthroughs on it so far. + +### 3. Improving documentation + +We have three forms of documentation: + +* short README documents that briefly introduce a topic +* reference documentation on [godoc.org](http://godoc.org) that is automatically +generated from source code comments +* user documentation on our [homepage](http://gophercloud.io) that includes +getting started guides, installation guides and code samples + +If you feel that a certain section could be improved - whether it's to clarify +ambiguity, correct a technical mistake, or to fix a grammatical error - please +feel entitled to do so! We welcome doc pull requests with the same childlike +enthusiasm as any other contribution! + +### 4. Optimizing existing features + +If you would like to improve or optimize an existing feature, please be aware +that we adhere to [semantic versioning](http://semver.org) - which means that +we cannot introduce breaking changes to the API without a major version change +(v1.x -> v2.x). Making that leap is a big step, so we encourage contributors to +refactor rather than rewrite. Running tests will prevent regression and avoid +the possibility of breaking somebody's current implementation. + +Another tip is to keep the focus of your work as small as possible - try not to +introduce a change that affects lots and lots of files because it introduces +added risk and increases the cognitive load on the reviewers checking your +work. Change-sets which are easily understood and will not negatively impact +users are more likely to be integrated quickly. + +Lastly, if you're seeking to optimize a particular operation, you should try to +demonstrate a negative performance impact - perhaps using go's inbuilt +[benchmark capabilities](http://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go). + +### 5. Working on a new feature + +If you've found something we've left out, definitely feel free to start work on +introducing that feature. It's always useful to open an issue or submit a pull +request early on to indicate your intent to a core contributor - this enables +quick/early feedback and can help steer you in the right direction by avoiding +known issues. It might also help you avoid losing time implementing something +that might not ever work. One tip is to prefix your Pull Request issue title +with [wip] - then people know it's a work in progress. + +You must ensure that all of your work is well tested - both in terms of unit +and acceptance tests. Untested code will not be merged because it introduces +too much of a risk to end-users. + +Happy hacking! diff --git a/vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md b/vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md new file mode 100644 index 000000000..63beb30b2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md @@ -0,0 +1,13 @@ +Contributors +============ + +| Name | Email | +| ---- | ----- | +| Samuel A. Falvo II | +| Glen Campbell | +| Jesse Noller | +| Jon Perritt | +| Ash Wilson | +| Jamie Hannaford | +| Don Schenck | don.schenck@rackspace.com> +| Joe Topjian | diff --git a/vendor/github.com/rackspace/gophercloud/LICENSE b/vendor/github.com/rackspace/gophercloud/LICENSE new file mode 100644 index 000000000..fbbbc9e4c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/LICENSE @@ -0,0 +1,191 @@ +Copyright 2012-2013 Rackspace, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +------ + + 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. + + END OF TERMS AND CONDITIONS diff --git a/vendor/github.com/rackspace/gophercloud/README.md b/vendor/github.com/rackspace/gophercloud/README.md new file mode 100644 index 000000000..0a0da59f6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/README.md @@ -0,0 +1,160 @@ +# Gophercloud: an OpenStack SDK for Go +[![Build Status](https://travis-ci.org/rackspace/gophercloud.svg?branch=master)](https://travis-ci.org/rackspace/gophercloud) + +Gophercloud is a flexible SDK that allows you to consume and work with OpenStack +clouds in a simple and idiomatic way using golang. Many services are supported, +including Compute, Block Storage, Object Storage, Networking, and Identity. +Each service API is backed with getting started guides, code samples, reference +documentation, unit tests and acceptance tests. + +## Useful links + +* [Gophercloud homepage](http://gophercloud.io) +* [Reference documentation](http://godoc.org/github.com/rackspace/gophercloud) +* [Getting started guides](http://gophercloud.io/docs) +* [Effective Go](https://golang.org/doc/effective_go.html) + +## How to install + +Before installing, you need to ensure that your [GOPATH environment variable](https://golang.org/doc/code.html#GOPATH) +is pointing to an appropriate directory where you want to install Gophercloud: + +```bash +mkdir $HOME/go +export GOPATH=$HOME/go +``` + +To protect yourself against changes in your dependencies, we highly recommend choosing a +[dependency management solution](https://github.com/golang/go/wiki/PackageManagementTools) for +your projects, such as [godep](https://github.com/tools/godep). Once this is set up, you can install +Gophercloud as a dependency like so: + +```bash +go get github.com/rackspace/gophercloud + +# Edit your code to import relevant packages from "github.com/rackspace/gophercloud" + +godep save ./... +``` + +This will install all the source files you need into a `Godeps/_workspace` directory, which is +referenceable from your own source files when you use the `godep go` command. + +## Getting started + +### Credentials + +Because you'll be hitting an API, you will need to retrieve your OpenStack +credentials and either store them as environment variables or in your local Go +files. The first method is recommended because it decouples credential +information from source code, allowing you to push the latter to your version +control system without any security risk. + +You will need to retrieve the following: + +* username +* password +* tenant name or tenant ID +* a valid Keystone identity URL + +For users that have the OpenStack dashboard installed, there's a shortcut. If +you visit the `project/access_and_security` path in Horizon and click on the +"Download OpenStack RC File" button at the top right hand corner, you will +download a bash file that exports all of your access details to environment +variables. To execute the file, run `source admin-openrc.sh` and you will be +prompted for your password. + +### Authentication + +Once you have access to your credentials, you can begin plugging them into +Gophercloud. The next step is authentication, and this is handled by a base +"Provider" struct. To get one, you can either pass in your credentials +explicitly, or tell Gophercloud to use environment variables: + +```go +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + "github.com/rackspace/gophercloud/openstack/utils" +) + +// Option 1: Pass in the values yourself +opts := gophercloud.AuthOptions{ + IdentityEndpoint: "https://my-openstack.com:5000/v2.0", + Username: "{username}", + Password: "{password}", + TenantID: "{tenant_id}", +} + +// Option 2: Use a utility function to retrieve all your environment variables +opts, err := openstack.AuthOptionsFromEnv() +``` + +Once you have the `opts` variable, you can pass it in and get back a +`ProviderClient` struct: + +```go +provider, err := openstack.AuthenticatedClient(opts) +``` + +The `ProviderClient` is the top-level client that all of your OpenStack services +derive from. The provider contains all of the authentication details that allow +your Go code to access the API - such as the base URL and token ID. + +### Provision a server + +Once we have a base Provider, we inject it as a dependency into each OpenStack +service. In order to work with the Compute API, we need a Compute service +client; which can be created like so: + +```go +client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{ + Region: os.Getenv("OS_REGION_NAME"), +}) +``` + +We then use this `client` for any Compute API operation we want. In our case, +we want to provision a new server - so we invoke the `Create` method and pass +in the flavor ID (hardware specification) and image ID (operating system) we're +interested in: + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +server, err := servers.Create(client, servers.CreateOpts{ + Name: "My new server!", + FlavorRef: "flavor_id", + ImageRef: "image_id", +}).Extract() +``` + +If you are unsure about what images and flavors are, you can read our [Compute +Getting Started guide](http://gophercloud.io/docs/compute). The above code +sample creates a new server with the parameters, and embodies the new resource +in the `server` variable (a +[`servers.Server`](http://godoc.org/github.com/rackspace/gophercloud) struct). + +### Next steps + +Cool! You've handled authentication, got your `ProviderClient` and provisioned +a new server. You're now ready to use more OpenStack services. + +* [Getting started with Compute](http://gophercloud.io/docs/compute) +* [Getting started with Object Storage](http://gophercloud.io/docs/object-storage) +* [Getting started with Networking](http://gophercloud.io/docs/networking) +* [Getting started with Block Storage](http://gophercloud.io/docs/block-storage) +* [Getting started with Identity](http://gophercloud.io/docs/identity) + +## Contributing + +Engaging the community and lowering barriers for contributors is something we +care a lot about. For this reason, we've taken the time to write a [contributing +guide](./CONTRIBUTING.md) for folks interested in getting involved in our project. +If you're not sure how you can get involved, feel free to submit an issue or +[contact us](https://developer.rackspace.com/support/). You don't need to be a +Go expert - all members of the community are welcome! + +## Help and feedback + +If you're struggling with something or have spotted a potential bug, feel free +to submit an issue to our [bug tracker](/issues) or [contact us directly](https://developer.rackspace.com/support/). diff --git a/vendor/github.com/rackspace/gophercloud/UPGRADING.md b/vendor/github.com/rackspace/gophercloud/UPGRADING.md new file mode 100644 index 000000000..76a94d570 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/UPGRADING.md @@ -0,0 +1,338 @@ +# Upgrading to v1.0.0 + +With the arrival of this new major version increment, the unfortunate news is +that breaking changes have been introduced to existing services. The API +has been completely rewritten from the ground up to make the library more +extensible, maintainable and easy-to-use. + +Below we've compiled upgrade instructions for the various services that +existed before. If you have a specific issue that is not addressed below, +please [submit an issue](/issues/new) or +[e-mail our support team](https://developer.rackspace.com/support/). + +* [Authentication](#authentication) +* [Servers](#servers) + * [List servers](#list-servers) + * [Get server details](#get-server-details) + * [Create server](#create-server) + * [Resize server](#resize-server) + * [Reboot server](#reboot-server) + * [Update server](#update-server) + * [Rebuild server](#rebuild-server) + * [Change admin password](#change-admin-password) + * [Delete server](#delete-server) + * [Rescue server](#rescue-server) +* [Images and flavors](#images-and-flavors) + * [List images](#list-images) + * [List flavors](#list-flavors) + * [Create/delete image](#createdelete-image) +* [Other](#other) + * [List keypairs](#list-keypairs) + * [Create/delete keypair](#createdelete-keypair) + * [List IP addresses](#list-ip-addresses) + +# Authentication + +One of the major differences that this release introduces is the level of +sub-packaging to differentiate between services and providers. You now have +the option of authenticating with OpenStack and other providers (like Rackspace). + +To authenticate with a vanilla OpenStack installation, you can either specify +your credentials like this: + +```go +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" +) + +opts := gophercloud.AuthOptions{ + IdentityEndpoint: "https://my-openstack.com:5000/v2.0", + Username: "{username}", + Password: "{password}", + TenantID: "{tenant_id}", +} +``` + +Or have them pulled in through environment variables, like this: + +```go +opts, err := openstack.AuthOptionsFromEnv() +``` + +Once you have your `AuthOptions` struct, you pass it in to get back a `Provider`, +like so: + +```go +provider, err := openstack.AuthenticatedClient(opts) +``` + +This provider is the top-level structure that all services are created from. + +# Servers + +Before you can interact with the Compute API, you need to retrieve a +`gophercloud.ServiceClient`. To do this: + +```go +// Define your region, etc. +opts := gophercloud.EndpointOpts{Region: "RegionOne"} + +client, err := openstack.NewComputeV2(provider, opts) +``` + +## List servers + +All operations that involve API collections (servers, flavors, images) now use +the `pagination.Pager` interface. This interface represents paginated entities +that can be iterated over. + +Once you have a Pager, you can then pass a callback function into its `EachPage` +method, and this will allow you to traverse over the collection and execute +arbitrary functionality. So, an example with list servers: + +```go +import ( + "fmt" + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// We have the option of filtering the server list. If we want the full +// collection, leave it as an empty struct or nil +opts := servers.ListOpts{Name: "server_1"} + +// Retrieve a pager (i.e. a paginated collection) +pager := servers.List(client, opts) + +// Define an anonymous function to be executed on each page's iteration +err := pager.EachPage(func(page pagination.Page) (bool, error) { + serverList, err := servers.ExtractServers(page) + + // `s' will be a servers.Server struct + for _, s := range serverList { + fmt.Printf("We have a server. ID=%s, Name=%s", s.ID, s.Name) + } +}) +``` + +## Get server details + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +// Get the HTTP result +response := servers.Get(client, "server_id") + +// Extract a Server struct from the response +server, err := response.Extract() +``` + +## Create server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +// Define our options +opts := servers.CreateOpts{ + Name: "new_server", + FlavorRef: "flavorID", + ImageRef: "imageID", +} + +// Get our response +response := servers.Create(client, opts) + +// Extract +server, err := response.Extract() +``` + +## Change admin password + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +result := servers.ChangeAdminPassword(client, "server_id", "newPassword_&123") +``` + +## Resize server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +result := servers.Resize(client, "server_id", "new_flavor_id") +``` + +## Reboot server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +// You have a choice of two reboot methods: servers.SoftReboot or servers.HardReboot +result := servers.Reboot(client, "server_id", servers.SoftReboot) +``` + +## Update server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +opts := servers.UpdateOpts{Name: "new_name"} + +server, err := servers.Update(client, "server_id", opts).Extract() +``` + +## Rebuild server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +// You have the option of specifying additional options +opts := RebuildOpts{ + Name: "new_name", + AdminPass: "admin_password", + ImageID: "image_id", + Metadata: map[string]string{"owner": "me"}, +} + +result := servers.Rebuild(client, "server_id", opts) + +// You can extract a servers.Server struct from the HTTP response +server, err := result.Extract() +``` + +## Delete server + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + +response := servers.Delete(client, "server_id") +``` + +## Rescue server + +The server rescue extension for Compute is not currently supported. + +# Images and flavors + +## List images + +As with listing servers (see above), you first retrieve a Pager, and then pass +in a callback over each page: + +```go +import ( + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/openstack/compute/v2/images" +) + +// We have the option of filtering the image list. If we want the full +// collection, leave it as an empty struct +opts := images.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", Name: "Ubuntu 12.04"} + +// Retrieve a pager (i.e. a paginated collection) +pager := images.List(client, opts) + +// Define an anonymous function to be executed on each page's iteration +err := pager.EachPage(func(page pagination.Page) (bool, error) { + imageList, err := images.ExtractImages(page) + + for _, i := range imageList { + // "i" will be an images.Image + } +}) +``` + +## List flavors + +```go +import ( + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" +) + +// We have the option of filtering the flavor list. If we want the full +// collection, leave it as an empty struct +opts := flavors.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", MinRAM: 4} + +// Retrieve a pager (i.e. a paginated collection) +pager := flavors.List(client, opts) + +// Define an anonymous function to be executed on each page's iteration +err := pager.EachPage(func(page pagination.Page) (bool, error) { + flavorList, err := networks.ExtractFlavors(page) + + for _, f := range flavorList { + // "f" will be a flavors.Flavor + } +}) +``` + +## Create/delete image + +Image management has been shifted to Glance, but unfortunately this service is +not supported as of yet. You can, however, list Compute images like so: + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/images" + +// Retrieve a pager (i.e. a paginated collection) +pager := images.List(client, opts) + +// Define an anonymous function to be executed on each page's iteration +err := pager.EachPage(func(page pagination.Page) (bool, error) { + imageList, err := images.ExtractImages(page) + + for _, i := range imageList { + // "i" will be an images.Image + } +}) +``` + +# Other + +## List keypairs + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs" + +// Retrieve a pager (i.e. a paginated collection) +pager := keypairs.List(client, opts) + +// Define an anonymous function to be executed on each page's iteration +err := pager.EachPage(func(page pagination.Page) (bool, error) { + keyList, err := keypairs.ExtractKeyPairs(page) + + for _, k := range keyList { + // "k" will be a keypairs.KeyPair + } +}) +``` + +## Create/delete keypairs + +To create a new keypair, you need to specify its name and, optionally, a +pregenerated OpenSSH-formatted public key. + +```go +import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs" + +opts := keypairs.CreateOpts{ + Name: "new_key", + PublicKey: "...", +} + +response := keypairs.Create(client, opts) + +key, err := response.Extract() +``` + +To delete an existing keypair: + +```go +response := keypairs.Delete(client, "keypair_id") +``` + +## List IP addresses + +This operation is not currently supported. diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/README.md b/vendor/github.com/rackspace/gophercloud/acceptance/README.md new file mode 100644 index 000000000..3199837c2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/README.md @@ -0,0 +1,57 @@ +# Gophercloud Acceptance tests + +The purpose of these acceptance tests is to validate that SDK features meet +the requirements of a contract - to consumers, other parts of the library, and +to a remote API. + +> **Note:** Because every test will be run against a real API endpoint, you +> may incur bandwidth and service charges for all the resource usage. These +> tests *should* remove their remote products automatically. However, there may +> be certain cases where this does not happen; always double-check to make sure +> you have no stragglers left behind. + +### Step 1. Set environment variables + +A lot of tests rely on environment variables for configuration - so you will need +to set them before running the suite. If you're testing against pure OpenStack APIs, +you can download a file that contains all of these variables for you: just visit +the `project/access_and_security` page in your control panel and click the "Download +OpenStack RC File" button at the top right. For all other providers, you will need +to set them manually. + +#### Authentication + +|Name|Description| +|---|---| +|`OS_USERNAME`|Your API username| +|`OS_PASSWORD`|Your API password| +|`OS_AUTH_URL`|The identity URL you need to authenticate| +|`OS_TENANT_NAME`|Your API tenant name| +|`OS_TENANT_ID`|Your API tenant ID| +|`RS_USERNAME`|Your Rackspace username| +|`RS_API_KEY`|Your Rackspace API key| + +#### General + +|Name|Description| +|---|---| +|`OS_REGION_NAME`|The region you want your resources to reside in| +|`RS_REGION`|Rackspace region you want your resource to reside in| + +#### Compute + +|Name|Description| +|---|---| +|`OS_IMAGE_ID`|The ID of the image your want your server to be based on| +|`OS_FLAVOR_ID`|The ID of the flavor you want your server to be based on| +|`OS_FLAVOR_ID_RESIZE`|The ID of the flavor you want your server to be resized to| +|`RS_IMAGE_ID`|The ID of the image you want servers to be created with| +|`RS_FLAVOR_ID`|The ID of the flavor you want your server to be created with| + +### 2. Run the test suite + +From the root directory, run: + +``` +./script/acceptancetest +``` diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go new file mode 100644 index 000000000..bb158c3ee --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go @@ -0,0 +1,3 @@ +// The v2 package contains acceptance tests for the Openstack Compute V2 service. + +package v2 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go new file mode 100644 index 000000000..f7ffc37b2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go @@ -0,0 +1,70 @@ +// +build acceptance db + +package v1 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + "github.com/rackspace/gophercloud/openstack/db/v1/instances" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := openstack.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := openstack.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := openstack.NewDBV1(client, gophercloud.EndpointOpts{ + Region: os.Getenv("OS_REGION_NAME"), + }) + th.AssertNoErr(t, err) + + return c +} + +type context struct { + test *testing.T + client *gophercloud.ServiceClient + instanceID string + DBIDs []string + users []string +} + +func newContext(t *testing.T) context { + return context{ + test: t, + client: newClient(t), + } +} + +func (c context) Logf(msg string, args ...interface{}) { + if len(args) > 0 { + c.test.Logf(msg, args...) + } else { + c.test.Log(msg) + } +} + +func (c context) AssertNoErr(err error) { + th.AssertNoErr(c.test, err) +} + +func (c context) WaitUntilActive(id string) { + err := gophercloud.WaitFor(60, func() (bool, error) { + inst, err := instances.Get(c.client, id).Extract() + if err != nil { + return false, err + } + if inst.Status == "ACTIVE" { + return true, nil + } + return false, nil + }) + + c.AssertNoErr(err) +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go new file mode 100644 index 000000000..b7b1f993d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go @@ -0,0 +1 @@ +package v1 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go new file mode 100644 index 000000000..5ec3cc8e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go @@ -0,0 +1 @@ +package v2 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go new file mode 100644 index 000000000..eac3ae96a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go @@ -0,0 +1 @@ +package v3 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go new file mode 100644 index 000000000..1efac2c08 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go @@ -0,0 +1,39 @@ +package v2 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + th "github.com/rackspace/gophercloud/testhelper" +) + +var Client *gophercloud.ServiceClient + +func NewClient() (*gophercloud.ServiceClient, error) { + opts, err := openstack.AuthOptionsFromEnv() + if err != nil { + return nil, err + } + + provider, err := openstack.AuthenticatedClient(opts) + if err != nil { + return nil, err + } + + return openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ + Name: "neutron", + Region: os.Getenv("OS_REGION_NAME"), + }) +} + +func Setup(t *testing.T) { + client, err := NewClient() + th.AssertNoErr(t, err) + Client = client +} + +func Teardown() { + Client = nil +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go new file mode 100644 index 000000000..206bf3313 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go @@ -0,0 +1 @@ +package fwaas diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go new file mode 100644 index 000000000..27dfe5f8b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go @@ -0,0 +1,78 @@ +package lbaas + +import ( + "testing" + + base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools" + "github.com/rackspace/gophercloud/openstack/networking/v2/networks" + "github.com/rackspace/gophercloud/openstack/networking/v2/subnets" + th "github.com/rackspace/gophercloud/testhelper" +) + +func SetupTopology(t *testing.T) (string, string) { + // create network + n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract() + th.AssertNoErr(t, err) + + t.Logf("Created network %s", n.ID) + + // create subnet + s, err := subnets.Create(base.Client, subnets.CreateOpts{ + NetworkID: n.ID, + CIDR: "192.168.199.0/24", + IPVersion: subnets.IPv4, + Name: "tmp_subnet", + }).Extract() + th.AssertNoErr(t, err) + + t.Logf("Created subnet %s", s.ID) + + return n.ID, s.ID +} + +func DeleteTopology(t *testing.T, networkID string) { + res := networks.Delete(base.Client, networkID) + th.AssertNoErr(t, res.Err) + t.Logf("Deleted network %s", networkID) +} + +func CreatePool(t *testing.T, subnetID string) string { + p, err := pools.Create(base.Client, pools.CreateOpts{ + LBMethod: pools.LBMethodRoundRobin, + Protocol: "HTTP", + Name: "tmp_pool", + SubnetID: subnetID, + }).Extract() + + th.AssertNoErr(t, err) + + t.Logf("Created pool %s", p.ID) + + return p.ID +} + +func DeletePool(t *testing.T, poolID string) { + res := pools.Delete(base.Client, poolID) + th.AssertNoErr(t, res.Err) + t.Logf("Deleted pool %s", poolID) +} + +func CreateMonitor(t *testing.T) string { + m, err := monitors.Create(base.Client, monitors.CreateOpts{ + Delay: 10, + Timeout: 10, + MaxRetries: 3, + Type: monitors.TypeHTTP, + ExpectedCodes: "200", + URLPath: "/login", + HTTPMethod: "GET", + }).Extract() + + th.AssertNoErr(t, err) + + t.Logf("Created monitor ID [%s]", m.ID) + + return m.ID +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go new file mode 100644 index 000000000..f5a7df7b7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go @@ -0,0 +1 @@ +package lbaas diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go new file mode 100644 index 000000000..aeec0fa75 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go @@ -0,0 +1 @@ +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go new file mode 100644 index 000000000..5ec3cc8e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go @@ -0,0 +1 @@ +package v2 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go new file mode 100644 index 000000000..1eac681b5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go @@ -0,0 +1,28 @@ +// +build acceptance + +package v1 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + th "github.com/rackspace/gophercloud/testhelper" +) + +var metadata = map[string]string{"gopher": "cloud"} + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := openstack.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := openstack.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{ + Region: os.Getenv("OS_REGION_NAME"), + }) + th.AssertNoErr(t, err) + return c +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go new file mode 100644 index 000000000..2c28dcbcc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go @@ -0,0 +1,44 @@ +// +build acceptance + +package v1 + +import ( + "fmt" + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + th "github.com/rackspace/gophercloud/testhelper" +) + +var template = fmt.Sprintf(` +{ + "heat_template_version": "2013-05-23", + "description": "Simple template to test heat commands", + "parameters": {}, + "resources": { + "hello_world": { + "type":"OS::Nova::Server", + "properties": { + "flavor": "%s", + "image": "%s", + "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n" + } + } + } +}`, os.Getenv("OS_FLAVOR_ID"), os.Getenv("OS_IMAGE_ID")) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := openstack.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := openstack.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := openstack.NewOrchestrationV1(client, gophercloud.EndpointOpts{ + Region: os.Getenv("OS_REGION_NAME"), + }) + th.AssertNoErr(t, err) + return c +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json new file mode 100644 index 000000000..11cfc8053 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json @@ -0,0 +1,13 @@ +{ + "heat_template_version": "2013-05-23", + "resources": { + "compute_instance": { + "type": "OS::Nova::Server", + "properties": { + "flavor": "m1.small", + "image": "cirros-0.3.2-x86_64-disk", + "name": "Single Compute Instance" + } + } + } +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go new file mode 100644 index 000000000..3a8ecdb10 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go @@ -0,0 +1,4 @@ +// +build acceptance + +package openstack + diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go new file mode 100644 index 000000000..e9fdd9920 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go @@ -0,0 +1,38 @@ +// +build acceptance + +package v1 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/acceptance/tools" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newClient() (*gophercloud.ServiceClient, error) { + opts, err := rackspace.AuthOptionsFromEnv() + if err != nil { + return nil, err + } + opts = tools.OnlyRS(opts) + region := os.Getenv("RS_REGION") + + provider, err := rackspace.AuthenticatedClient(opts) + if err != nil { + return nil, err + } + + return rackspace.NewBlockStorageV1(provider, gophercloud.EndpointOpts{ + Region: region, + }) +} + +func setup(t *testing.T) *gophercloud.ServiceClient { + client, err := newClient() + th.AssertNoErr(t, err) + + return client +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go new file mode 100644 index 000000000..2333ca77b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go @@ -0,0 +1,23 @@ +// +build acceptance + +package v1 + +import ( + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := rackspace.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := rackspace.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := rackspace.NewCDNV1(client, gophercloud.EndpointOpts{}) + th.AssertNoErr(t, err) + return c +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go new file mode 100644 index 000000000..5ec3cc8e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go @@ -0,0 +1 @@ +package v2 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go new file mode 100644 index 000000000..24512b99a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go @@ -0,0 +1,73 @@ +// +build acceptance db rackspace + +package v1 + +import ( + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/acceptance/tools" + "github.com/rackspace/gophercloud/rackspace" + "github.com/rackspace/gophercloud/rackspace/db/v1/instances" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + opts, err := rackspace.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + opts = tools.OnlyRS(opts) + + client, err := rackspace.AuthenticatedClient(opts) + th.AssertNoErr(t, err) + + c, err := rackspace.NewDBV1(client, gophercloud.EndpointOpts{ + Region: "IAD", + }) + th.AssertNoErr(t, err) + + return c +} + +type context struct { + test *testing.T + client *gophercloud.ServiceClient + instanceID string + DBIDs []string + replicaID string + backupID string + configGroupID string + users []string +} + +func newContext(t *testing.T) context { + return context{ + test: t, + client: newClient(t), + } +} + +func (c context) Logf(msg string, args ...interface{}) { + if len(args) > 0 { + c.test.Logf(msg, args...) + } else { + c.test.Log(msg) + } +} + +func (c context) AssertNoErr(err error) { + th.AssertNoErr(c.test, err) +} + +func (c context) WaitUntilActive(id string) { + err := gophercloud.WaitFor(60, func() (bool, error) { + inst, err := instances.Get(c.client, id).Extract() + if err != nil { + return false, err + } + if inst.Status == "ACTIVE" { + return true, nil + } + return false, nil + }) + c.AssertNoErr(err) +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go new file mode 100644 index 000000000..b7b1f993d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go @@ -0,0 +1 @@ +package v1 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go new file mode 100644 index 000000000..5ec3cc8e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go @@ -0,0 +1 @@ +package v2 diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go new file mode 100644 index 000000000..4ce05e69c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go @@ -0,0 +1,62 @@ +// +build acceptance lbs + +package v1 + +import ( + "os" + "strconv" + "strings" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/acceptance/tools" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newProvider() (*gophercloud.ProviderClient, error) { + opts, err := rackspace.AuthOptionsFromEnv() + if err != nil { + return nil, err + } + opts = tools.OnlyRS(opts) + + return rackspace.AuthenticatedClient(opts) +} + +func newClient() (*gophercloud.ServiceClient, error) { + provider, err := newProvider() + if err != nil { + return nil, err + } + + return rackspace.NewLBV1(provider, gophercloud.EndpointOpts{ + Region: os.Getenv("RS_REGION"), + }) +} + +func newComputeClient() (*gophercloud.ServiceClient, error) { + provider, err := newProvider() + if err != nil { + return nil, err + } + + return rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{ + Region: os.Getenv("RS_REGION"), + }) +} + +func setup(t *testing.T) *gophercloud.ServiceClient { + client, err := newClient() + th.AssertNoErr(t, err) + + return client +} + +func intsToStr(ids []int) string { + strIDs := []string{} + for _, id := range ids { + strIDs = append(strIDs, strconv.Itoa(id)) + } + return strings.Join(strIDs, ", ") +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go new file mode 100644 index 000000000..81704187f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go @@ -0,0 +1,39 @@ +package v2 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +var Client *gophercloud.ServiceClient + +func NewClient() (*gophercloud.ServiceClient, error) { + opts, err := rackspace.AuthOptionsFromEnv() + if err != nil { + return nil, err + } + + provider, err := rackspace.AuthenticatedClient(opts) + if err != nil { + return nil, err + } + + return rackspace.NewNetworkV2(provider, gophercloud.EndpointOpts{ + Name: "cloudNetworks", + Region: os.Getenv("RS_REGION"), + }) +} + +func Setup(t *testing.T) { + client, err := NewClient() + th.AssertNoErr(t, err) + Client = client +} + +func Teardown() { + Client = nil +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go new file mode 100644 index 000000000..1ae07278c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go @@ -0,0 +1,54 @@ +// +build acceptance rackspace objectstorage v1 + +package v1 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/acceptance/tools" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +func rackspaceAuthOptions(t *testing.T) gophercloud.AuthOptions { + // Obtain credentials from the environment. + options, err := rackspace.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + options = tools.OnlyRS(options) + + if options.Username == "" { + t.Fatal("Please provide a Rackspace username as RS_USERNAME.") + } + if options.APIKey == "" { + t.Fatal("Please provide a Rackspace API key as RS_API_KEY.") + } + + return options +} + +func createClient(t *testing.T, cdn bool) (*gophercloud.ServiceClient, error) { + region := os.Getenv("RS_REGION") + if region == "" { + t.Fatal("Please provide a Rackspace region as RS_REGION") + } + + ao := rackspaceAuthOptions(t) + + provider, err := rackspace.NewClient(ao.IdentityEndpoint) + th.AssertNoErr(t, err) + + err = rackspace.Authenticate(provider, ao) + th.AssertNoErr(t, err) + + if cdn { + return rackspace.NewObjectCDNV1(provider, gophercloud.EndpointOpts{ + Region: region, + }) + } + + return rackspace.NewObjectStorageV1(provider, gophercloud.EndpointOpts{ + Region: region, + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go new file mode 100644 index 000000000..b9d51979d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go @@ -0,0 +1,45 @@ +// +build acceptance + +package v1 + +import ( + "fmt" + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +var template = fmt.Sprintf(` +{ + "heat_template_version": "2013-05-23", + "description": "Simple template to test heat commands", + "parameters": {}, + "resources": { + "hello_world": { + "type":"OS::Nova::Server", + "properties": { + "flavor": "%s", + "image": "%s", + "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n" + } + } + } +} +`, os.Getenv("RS_FLAVOR_ID"), os.Getenv("RS_IMAGE_ID")) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := rackspace.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := rackspace.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := rackspace.NewOrchestrationV1(client, gophercloud.EndpointOpts{ + Region: os.Getenv("RS_REGION_NAME"), + }) + th.AssertNoErr(t, err) + return c +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go new file mode 100644 index 000000000..5d17b32ca --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go @@ -0,0 +1 @@ +package rackspace diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go new file mode 100644 index 000000000..8c7531417 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go @@ -0,0 +1,26 @@ +// +build acceptance + +package v3 + +import ( + "os" + "testing" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/rackspace" + th "github.com/rackspace/gophercloud/testhelper" +) + +func newClient(t *testing.T) *gophercloud.ServiceClient { + ao, err := rackspace.AuthOptionsFromEnv() + th.AssertNoErr(t, err) + + client, err := rackspace.AuthenticatedClient(ao) + th.AssertNoErr(t, err) + + c, err := rackspace.NewRackConnectV3(client, gophercloud.EndpointOpts{ + Region: os.Getenv("RS_REGION_NAME"), + }) + th.AssertNoErr(t, err) + return c +} diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go b/vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go new file mode 100644 index 000000000..f7eca1298 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go @@ -0,0 +1 @@ +package tools diff --git a/vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go b/vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go new file mode 100644 index 000000000..35679b728 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go @@ -0,0 +1,89 @@ +// +build acceptance common + +package tools + +import ( + "crypto/rand" + "errors" + mrand "math/rand" + "os" + "time" + + "github.com/rackspace/gophercloud" +) + +// ErrTimeout is returned if WaitFor takes longer than 300 second to happen. +var ErrTimeout = errors.New("Timed out") + +// OnlyRS overrides the default Gophercloud behavior of using OS_-prefixed environment variables +// if RS_ variables aren't present. Otherwise, they'll stomp over each other here in the acceptance +// tests, where you need to have both defined. +func OnlyRS(original gophercloud.AuthOptions) gophercloud.AuthOptions { + if os.Getenv("RS_AUTH_URL") == "" { + original.IdentityEndpoint = "" + } + if os.Getenv("RS_USERNAME") == "" { + original.Username = "" + } + if os.Getenv("RS_PASSWORD") == "" { + original.Password = "" + } + if os.Getenv("RS_API_KEY") == "" { + original.APIKey = "" + } + return original +} + +// WaitFor polls a predicate function once per second to wait for a certain state to arrive. +func WaitFor(predicate func() (bool, error)) error { + for i := 0; i < 300; i++ { + time.Sleep(1 * time.Second) + + satisfied, err := predicate() + if err != nil { + return err + } + if satisfied { + return nil + } + } + return ErrTimeout +} + +// MakeNewPassword generates a new string that's guaranteed to be different than the given one. +func MakeNewPassword(oldPass string) string { + randomPassword := RandomString("", 16) + for randomPassword == oldPass { + randomPassword = RandomString("", 16) + } + return randomPassword +} + +// RandomString generates a string of given length, but random content. +// All content will be within the ASCII graphic character set. +// (Implementation from Even Shaw's contribution on +// http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go). +func RandomString(prefix string, n int) string { + const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + var bytes = make([]byte, n) + rand.Read(bytes) + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + return prefix + string(bytes) +} + +// RandomInt will return a random integer between a specified range. +func RandomInt(min, max int) int { + mrand.Seed(time.Now().Unix()) + return mrand.Intn(max-min) + min +} + +// Elide returns the first bit of its input string with a suffix of "..." if it's longer than +// a comfortable 40 characters. +func Elide(value string) string { + if len(value) > 40 { + return value[0:37] + "..." + } + return value +} diff --git a/vendor/github.com/rackspace/gophercloud/auth_options.go b/vendor/github.com/rackspace/gophercloud/auth_options.go new file mode 100644 index 000000000..d26e16ac1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/auth_options.go @@ -0,0 +1,50 @@ +package gophercloud + +/* +AuthOptions stores information needed to authenticate to an OpenStack cluster. +You can populate one manually, or use a provider's AuthOptionsFromEnv() function +to read relevant information from the standard environment variables. Pass one +to a provider's AuthenticatedClient function to authenticate and obtain a +ProviderClient representing an active session on that provider. + +Its fields are the union of those recognized by each identity implementation and +provider. +*/ +type AuthOptions struct { + // IdentityEndpoint specifies the HTTP endpoint that is required to work with + // the Identity API of the appropriate version. While it's ultimately needed by + // all of the identity services, it will often be populated by a provider-level + // function. + IdentityEndpoint string + + // Username is required if using Identity V2 API. Consult with your provider's + // control panel to discover your account's username. In Identity V3, either + // UserID or a combination of Username and DomainID or DomainName are needed. + Username, UserID string + + // Exactly one of Password or APIKey is required for the Identity V2 and V3 + // APIs. Consult with your provider's control panel to discover your account's + // preferred method of authentication. + Password, APIKey string + + // At most one of DomainID and DomainName must be provided if using Username + // with Identity V3. Otherwise, either are optional. + DomainID, DomainName string + + // The TenantID and TenantName fields are optional for the Identity V2 API. + // Some providers allow you to specify a TenantName instead of the TenantId. + // Some require both. Your provider's authentication policies will determine + // how these fields influence authentication. + TenantID, TenantName string + + // AllowReauth should be set to true if you grant permission for Gophercloud to + // cache your credentials in memory, and to allow Gophercloud to attempt to + // re-authenticate automatically if/when your token expires. If you set it to + // false, it will not cache these settings, but re-authentication will not be + // possible. This setting defaults to false. + AllowReauth bool + + // TokenID allows users to authenticate (possibly as another user) with an + // authentication token ID. + TokenID string +} diff --git a/vendor/github.com/rackspace/gophercloud/auth_results.go b/vendor/github.com/rackspace/gophercloud/auth_results.go new file mode 100644 index 000000000..856a23382 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/auth_results.go @@ -0,0 +1,14 @@ +package gophercloud + +import "time" + +// AuthResults [deprecated] is a leftover type from the v0.x days. It was +// intended to describe common functionality among identity service results, but +// is not actually used anywhere. +type AuthResults interface { + // TokenID returns the token's ID value from the authentication response. + TokenID() (string, error) + + // ExpiresAt retrieves the token's expiration time. + ExpiresAt() (time.Time, error) +} diff --git a/vendor/github.com/rackspace/gophercloud/doc.go b/vendor/github.com/rackspace/gophercloud/doc.go new file mode 100644 index 000000000..fb81a9d8f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/doc.go @@ -0,0 +1,67 @@ +/* +Package gophercloud provides a multi-vendor interface to OpenStack-compatible +clouds. The library has a three-level hierarchy: providers, services, and +resources. + +Provider structs represent the service providers that offer and manage a +collection of services. Examples of providers include: OpenStack, Rackspace, +HP. These are defined like so: + + opts := gophercloud.AuthOptions{ + IdentityEndpoint: "https://my-openstack.com:5000/v2.0", + Username: "{username}", + Password: "{password}", + TenantID: "{tenant_id}", + } + + provider, err := openstack.AuthenticatedClient(opts) + +Service structs are specific to a provider and handle all of the logic and +operations for a particular OpenStack service. Examples of services include: +Compute, Object Storage, Block Storage. In order to define one, you need to +pass in the parent provider, like so: + + opts := gophercloud.EndpointOpts{Region: "RegionOne"} + + client := openstack.NewComputeV2(provider, opts) + +Resource structs are the domain models that services make use of in order +to work with and represent the state of API resources: + + server, err := servers.Get(client, "{serverId}").Extract() + +Intermediate Result structs are returned for API operations, which allow +generic access to the HTTP headers, response body, and any errors associated +with the network transaction. To turn a result into a usable resource struct, +you must call the Extract method which is chained to the response, or an +Extract function from an applicable extension: + + result := servers.Get(client, "{serverId}") + + // Attempt to extract the disk configuration from the OS-DCF disk config + // extension: + config, err := diskconfig.ExtractGet(result) + +All requests that enumerate a collection return a Pager struct that is used to +iterate through the results one page at a time. Use the EachPage method on that +Pager to handle each successive Page in a closure, then use the appropriate +extraction method from that request's package to interpret that Page as a slice +of results: + + err := servers.List(client, nil).EachPage(func (page pagination.Page) (bool, error) { + s, err := servers.ExtractServers(page) + if err != nil { + return false, err + } + + // Handle the []servers.Server slice. + + // Return "false" or an error to prematurely stop fetching new pages. + return true, nil + }) + +This top-level package contains utility functions and data types that are used +throughout the provider and service packages. Of particular note for end users +are the AuthOptions and EndpointOpts structs. +*/ +package gophercloud diff --git a/vendor/github.com/rackspace/gophercloud/endpoint_search.go b/vendor/github.com/rackspace/gophercloud/endpoint_search.go new file mode 100644 index 000000000..518943121 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/endpoint_search.go @@ -0,0 +1,92 @@ +package gophercloud + +import "errors" + +var ( + // ErrServiceNotFound is returned when no service in a service catalog matches + // the provided EndpointOpts. This is generally returned by provider service + // factory methods like "NewComputeV2()" and can mean that a service is not + // enabled for your account. + ErrServiceNotFound = errors.New("No suitable service could be found in the service catalog.") + + // ErrEndpointNotFound is returned when no available endpoints match the + // provided EndpointOpts. This is also generally returned by provider service + // factory methods, and usually indicates that a region was specified + // incorrectly. + ErrEndpointNotFound = errors.New("No suitable endpoint could be found in the service catalog.") +) + +// Availability indicates to whom a specific service endpoint is accessible: +// the internet at large, internal networks only, or only to administrators. +// Different identity services use different terminology for these. Identity v2 +// lists them as different kinds of URLs within the service catalog ("adminURL", +// "internalURL", and "publicURL"), while v3 lists them as "Interfaces" in an +// endpoint's response. +type Availability string + +const ( + // AvailabilityAdmin indicates that an endpoint is only available to + // administrators. + AvailabilityAdmin Availability = "admin" + + // AvailabilityPublic indicates that an endpoint is available to everyone on + // the internet. + AvailabilityPublic Availability = "public" + + // AvailabilityInternal indicates that an endpoint is only available within + // the cluster's internal network. + AvailabilityInternal Availability = "internal" +) + +// EndpointOpts specifies search criteria used by queries against an +// OpenStack service catalog. The options must contain enough information to +// unambiguously identify one, and only one, endpoint within the catalog. +// +// Usually, these are passed to service client factory functions in a provider +// package, like "rackspace.NewComputeV2()". +type EndpointOpts struct { + // Type [required] is the service type for the client (e.g., "compute", + // "object-store"). Generally, this will be supplied by the service client + // function, but a user-given value will be honored if provided. + Type string + + // Name [optional] is the service name for the client (e.g., "nova") as it + // appears in the service catalog. Services can have the same Type but a + // different Name, which is why both Type and Name are sometimes needed. + Name string + + // Region [required] is the geographic region in which the endpoint resides, + // generally specifying which datacenter should house your resources. + // Required only for services that span multiple regions. + Region string + + // Availability [optional] is the visibility of the endpoint to be returned. + // Valid types include the constants AvailabilityPublic, AvailabilityInternal, + // or AvailabilityAdmin from this package. + // + // Availability is not required, and defaults to AvailabilityPublic. Not all + // providers or services offer all Availability options. + Availability Availability +} + +/* +EndpointLocator is an internal function to be used by provider implementations. + +It provides an implementation that locates a single endpoint from a service +catalog for a specific ProviderClient based on user-provided EndpointOpts. The +provider then uses it to discover related ServiceClients. +*/ +type EndpointLocator func(EndpointOpts) (string, error) + +// ApplyDefaults is an internal method to be used by provider implementations. +// +// It sets EndpointOpts fields if not already set, including a default type. +// Currently, EndpointOpts.Availability defaults to the public endpoint. +func (eo *EndpointOpts) ApplyDefaults(t string) { + if eo.Type == "" { + eo.Type = t + } + if eo.Availability == "" { + eo.Availability = AvailabilityPublic + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go b/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go new file mode 100644 index 000000000..a4402b6f0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go @@ -0,0 +1,58 @@ +package openstack + +import ( + "fmt" + "os" + + "github.com/rackspace/gophercloud" +) + +var nilOptions = gophercloud.AuthOptions{} + +// ErrNoAuthUrl, ErrNoUsername, and ErrNoPassword errors indicate of the required OS_AUTH_URL, OS_USERNAME, or OS_PASSWORD +// environment variables, respectively, remain undefined. See the AuthOptions() function for more details. +var ( + ErrNoAuthURL = fmt.Errorf("Environment variable OS_AUTH_URL needs to be set.") + ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME needs to be set.") + ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD needs to be set.") +) + +// AuthOptions fills out an identity.AuthOptions structure with the settings found on the various OpenStack +// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME, +// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must +// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional. +func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { + authURL := os.Getenv("OS_AUTH_URL") + username := os.Getenv("OS_USERNAME") + userID := os.Getenv("OS_USERID") + password := os.Getenv("OS_PASSWORD") + tenantID := os.Getenv("OS_TENANT_ID") + tenantName := os.Getenv("OS_TENANT_NAME") + domainID := os.Getenv("OS_DOMAIN_ID") + domainName := os.Getenv("OS_DOMAIN_NAME") + + if authURL == "" { + return nilOptions, ErrNoAuthURL + } + + if username == "" && userID == "" { + return nilOptions, ErrNoUsername + } + + if password == "" { + return nilOptions, ErrNoPassword + } + + ao := gophercloud.AuthOptions{ + IdentityEndpoint: authURL, + UserID: userID, + Username: username, + Password: password, + TenantID: tenantID, + TenantName: tenantName, + DomainID: domainID, + DomainName: domainName, + } + + return ao, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go new file mode 100644 index 000000000..e3af39f51 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go @@ -0,0 +1,3 @@ +// Package apiversions provides information and interaction with the different +// API versions for the OpenStack Block Storage service, code-named Cinder. +package apiversions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go new file mode 100644 index 000000000..bb2c25915 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go @@ -0,0 +1,21 @@ +package apiversions + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List lists all the Cinder API versions available to end-users. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page { + return APIVersionPage{pagination.SinglePageBase(r)} + }) +} + +// Get will retrieve the volume type with the provided ID. To extract the volume +// type from the result, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, v string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, v), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go new file mode 100644 index 000000000..7b0df115b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go @@ -0,0 +1,58 @@ +package apiversions + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// APIVersion represents an API version for Cinder. +type APIVersion struct { + ID string `json:"id" mapstructure:"id"` // unique identifier + Status string `json:"status" mapstructure:"status"` // current status + Updated string `json:"updated" mapstructure:"updated"` // date last updated +} + +// APIVersionPage is the page returned by a pager when traversing over a +// collection of API versions. +type APIVersionPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an APIVersionPage struct is empty. +func (r APIVersionPage) IsEmpty() (bool, error) { + is, err := ExtractAPIVersions(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractAPIVersions takes a collection page, extracts all of the elements, +// and returns them a slice of APIVersion structs. It is effectively a cast. +func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) { + var resp struct { + Versions []APIVersion `mapstructure:"versions"` + } + + err := mapstructure.Decode(page.(APIVersionPage).Body, &resp) + + return resp.Versions, err +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts an API version resource. +func (r GetResult) Extract() (*APIVersion, error) { + var resp struct { + Version *APIVersion `mapstructure:"version"` + } + + err := mapstructure.Decode(r.Body, &resp) + + return resp.Version, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go new file mode 100644 index 000000000..56f8260a2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go @@ -0,0 +1,15 @@ +package apiversions + +import ( + "strings" + + "github.com/rackspace/gophercloud" +) + +func getURL(c *gophercloud.ServiceClient, version string) string { + return c.ServiceURL(strings.TrimRight(version, "/") + "/") +} + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go new file mode 100644 index 000000000..198f83077 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go @@ -0,0 +1,5 @@ +// Package snapshots provides information and interaction with snapshots in the +// OpenStack Block Storage service. A snapshot is a point in time copy of the +// data contained in an external storage volume, and can be controlled +// programmatically. +package snapshots diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go new file mode 100644 index 000000000..d1461fb69 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go @@ -0,0 +1,114 @@ +package snapshots + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` + { + "snapshots": [ + { + "id": "289da7f8-6440-407c-9fb4-7db01ec49164", + "display_name": "snapshot-001" + }, + { + "id": "96c3bda7-c82a-4f50-be73-ca7621794835", + "display_name": "snapshot-002" + } + ] + } + `) + }) +} + +func MockGetResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` +{ + "snapshot": { + "display_name": "snapshot-001", + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" + } +} + `) + }) +} + +func MockCreateResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ` +{ + "snapshot": { + "volume_id": "1234", + "display_name": "snapshot-001" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + + fmt.Fprintf(w, ` +{ + "snapshot": { + "volume_id": "1234", + "display_name": "snapshot-001", + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" + } +} + `) + }) +} + +func MockUpdateMetadataResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/123/metadata", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, ` + { + "metadata": { + "key": "v1" + } + } + `) + + fmt.Fprintf(w, ` + { + "metadata": { + "key": "v1" + } + } + `) + }) +} + +func MockDeleteResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go new file mode 100644 index 000000000..71936e51b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go @@ -0,0 +1,206 @@ +package snapshots + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToSnapshotCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains options for creating a Snapshot. This object is passed to +// the snapshots.Create function. For more information about these parameters, +// see the Snapshot object. +type CreateOpts struct { + // OPTIONAL + Description string + // OPTIONAL + Force bool + // OPTIONAL + Metadata map[string]interface{} + // OPTIONAL + Name string + // REQUIRED + VolumeID string +} + +// ToSnapshotCreateMap assembles a request body based on the contents of a +// CreateOpts. +func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.VolumeID == "" { + return nil, fmt.Errorf("Required CreateOpts field 'VolumeID' not set.") + } + s["volume_id"] = opts.VolumeID + + if opts.Description != "" { + s["display_description"] = opts.Description + } + if opts.Force == true { + s["force"] = opts.Force + } + if opts.Metadata != nil { + s["metadata"] = opts.Metadata + } + if opts.Name != "" { + s["display_name"] = opts.Name + } + + return map[string]interface{}{"snapshot": s}, nil +} + +// Create will create a new Snapshot based on the values in CreateOpts. To +// extract the Snapshot object from the response, call the Extract method on the +// CreateResult. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToSnapshotCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + return res +} + +// Delete will delete the existing Snapshot with the provided ID. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} + +// Get retrieves the Snapshot with the provided ID. To extract the Snapshot +// object from the response, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToSnapshotListQuery() (string, error) +} + +// ListOpts hold options for listing Snapshots. It is passed to the +// snapshots.List function. +type ListOpts struct { + Name string `q:"display_name"` + Status string `q:"status"` + VolumeID string `q:"volume_id"` +} + +// ToSnapshotListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToSnapshotListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns Snapshots optionally limited by the conditions provided in +// ListOpts. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(client) + if opts != nil { + query, err := opts.ToSnapshotListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPage := func(r pagination.PageResult) pagination.Page { + return ListResult{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, url, createPage) +} + +// UpdateMetadataOptsBuilder allows extensions to add additional parameters to +// the Update request. +type UpdateMetadataOptsBuilder interface { + ToSnapshotUpdateMetadataMap() (map[string]interface{}, error) +} + +// UpdateMetadataOpts contain options for updating an existing Snapshot. This +// object is passed to the snapshots.Update function. For more information +// about the parameters, see the Snapshot object. +type UpdateMetadataOpts struct { + Metadata map[string]interface{} +} + +// ToSnapshotUpdateMetadataMap assembles a request body based on the contents of +// an UpdateMetadataOpts. +func (opts UpdateMetadataOpts) ToSnapshotUpdateMetadataMap() (map[string]interface{}, error) { + v := make(map[string]interface{}) + + if opts.Metadata != nil { + v["metadata"] = opts.Metadata + } + + return v, nil +} + +// UpdateMetadata will update the Snapshot with provided information. To +// extract the updated Snapshot from the response, call the ExtractMetadata +// method on the UpdateMetadataResult. +func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult { + var res UpdateMetadataResult + + reqBody, err := opts.ToSnapshotUpdateMetadataMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Put(updateMetadataURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// IDFromName is a convienience function that returns a snapshot's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + snapshotCount := 0 + snapshotID := "" + if name == "" { + return "", fmt.Errorf("A snapshot name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + snapshotList, err := ExtractSnapshots(page) + if err != nil { + return false, err + } + + for _, s := range snapshotList { + if s.Name == name { + snapshotCount++ + snapshotID = s.ID + } + } + return true, nil + }) + + switch snapshotCount { + case 0: + return "", fmt.Errorf("Unable to find snapshot: %s", name) + case 1: + return snapshotID, nil + default: + return "", fmt.Errorf("Found %d snapshots matching %s", snapshotCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go new file mode 100644 index 000000000..e595798e4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go @@ -0,0 +1,123 @@ +package snapshots + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Snapshot contains all the information associated with an OpenStack Snapshot. +type Snapshot struct { + // Currect status of the Snapshot. + Status string `mapstructure:"status"` + + // Display name. + Name string `mapstructure:"display_name"` + + // Instances onto which the Snapshot is attached. + Attachments []string `mapstructure:"attachments"` + + // Logical group. + AvailabilityZone string `mapstructure:"availability_zone"` + + // Is the Snapshot bootable? + Bootable string `mapstructure:"bootable"` + + // Date created. + CreatedAt string `mapstructure:"created_at"` + + // Display description. + Description string `mapstructure:"display_discription"` + + // See VolumeType object for more information. + VolumeType string `mapstructure:"volume_type"` + + // ID of the Snapshot from which this Snapshot was created. + SnapshotID string `mapstructure:"snapshot_id"` + + // ID of the Volume from which this Snapshot was created. + VolumeID string `mapstructure:"volume_id"` + + // User-defined key-value pairs. + Metadata map[string]string `mapstructure:"metadata"` + + // Unique identifier. + ID string `mapstructure:"id"` + + // Size of the Snapshot, in GB. + Size int `mapstructure:"size"` +} + +// CreateResult contains the response body and error from a Create request. +type CreateResult struct { + commonResult +} + +// GetResult contains the response body and error from a Get request. +type GetResult struct { + commonResult +} + +// DeleteResult contains the response body and error from a Delete request. +type DeleteResult struct { + gophercloud.ErrResult +} + +// ListResult is a pagination.Pager that is returned from a call to the List function. +type ListResult struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ListResult contains no Snapshots. +func (r ListResult) IsEmpty() (bool, error) { + volumes, err := ExtractSnapshots(r) + if err != nil { + return true, err + } + return len(volumes) == 0, nil +} + +// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call. +func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) { + var response struct { + Snapshots []Snapshot `json:"snapshots"` + } + + err := mapstructure.Decode(page.(ListResult).Body, &response) + return response.Snapshots, err +} + +// UpdateMetadataResult contains the response body and error from an UpdateMetadata request. +type UpdateMetadataResult struct { + commonResult +} + +// ExtractMetadata returns the metadata from a response from snapshots.UpdateMetadata. +func (r UpdateMetadataResult) ExtractMetadata() (map[string]interface{}, error) { + if r.Err != nil { + return nil, r.Err + } + + m := r.Body.(map[string]interface{})["metadata"] + return m.(map[string]interface{}), nil +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will get the Snapshot object out of the commonResult object. +func (r commonResult) Extract() (*Snapshot, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Snapshot *Snapshot `json:"snapshot"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Snapshot, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go new file mode 100644 index 000000000..4d635e8dd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go @@ -0,0 +1,27 @@ +package snapshots + +import "github.com/rackspace/gophercloud" + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("snapshots") +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return deleteURL(c, id) +} + +func listURL(c *gophercloud.ServiceClient) string { + return createURL(c) +} + +func metadataURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "metadata") +} + +func updateMetadataURL(c *gophercloud.ServiceClient, id string) string { + return metadataURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go new file mode 100644 index 000000000..64cdc607e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go @@ -0,0 +1,22 @@ +package snapshots + +import ( + "github.com/rackspace/gophercloud" +) + +// WaitForStatus will continually poll the resource, checking for a particular +// status. It will do this for the amount of seconds defined. +func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error { + return gophercloud.WaitFor(secs, func() (bool, error) { + current, err := Get(c, id).Extract() + if err != nil { + return false, err + } + + if current.Status == status { + return true, nil + } + + return false, nil + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go new file mode 100644 index 000000000..307b8b12d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go @@ -0,0 +1,5 @@ +// Package volumes provides information and interaction with volumes in the +// OpenStack Block Storage service. A volume is a detachable block storage +// device, akin to a USB hard drive. It can only be attached to one instance at +// a time. +package volumes diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go new file mode 100644 index 000000000..3e9243ac4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go @@ -0,0 +1,236 @@ +package volumes + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToVolumeCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains options for creating a Volume. This object is passed to +// the volumes.Create function. For more information about these parameters, +// see the Volume object. +type CreateOpts struct { + // OPTIONAL + Availability string + // OPTIONAL + Description string + // OPTIONAL + Metadata map[string]string + // OPTIONAL + Name string + // REQUIRED + Size int + // OPTIONAL + SnapshotID, SourceVolID, ImageID string + // OPTIONAL + VolumeType string +} + +// ToVolumeCreateMap assembles a request body based on the contents of a +// CreateOpts. +func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) { + v := make(map[string]interface{}) + + if opts.Size == 0 { + return nil, fmt.Errorf("Required CreateOpts field 'Size' not set.") + } + v["size"] = opts.Size + + if opts.Availability != "" { + v["availability_zone"] = opts.Availability + } + if opts.Description != "" { + v["display_description"] = opts.Description + } + if opts.ImageID != "" { + v["imageRef"] = opts.ImageID + } + if opts.Metadata != nil { + v["metadata"] = opts.Metadata + } + if opts.Name != "" { + v["display_name"] = opts.Name + } + if opts.SourceVolID != "" { + v["source_volid"] = opts.SourceVolID + } + if opts.SnapshotID != "" { + v["snapshot_id"] = opts.SnapshotID + } + if opts.VolumeType != "" { + v["volume_type"] = opts.VolumeType + } + + return map[string]interface{}{"volume": v}, nil +} + +// Create will create a new Volume based on the values in CreateOpts. To extract +// the Volume object from the response, call the Extract method on the +// CreateResult. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToVolumeCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + return res +} + +// Delete will delete the existing Volume with the provided ID. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} + +// Get retrieves the Volume with the provided ID. To extract the Volume object +// from the response, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToVolumeListQuery() (string, error) +} + +// ListOpts holds options for listing Volumes. It is passed to the volumes.List +// function. +type ListOpts struct { + // admin-only option. Set it to true to see all tenant volumes. + AllTenants bool `q:"all_tenants"` + // List only volumes that contain Metadata. + Metadata map[string]string `q:"metadata"` + // List only volumes that have Name as the display name. + Name string `q:"name"` + // List only volumes that have a status of Status. + Status string `q:"status"` +} + +// ToVolumeListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToVolumeListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns Volumes optionally limited by the conditions provided in ListOpts. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(client) + if opts != nil { + query, err := opts.ToVolumeListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + createPage := func(r pagination.PageResult) pagination.Page { + return ListResult{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, url, createPage) +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToVolumeUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts contain options for updating an existing Volume. This object is passed +// to the volumes.Update function. For more information about the parameters, see +// the Volume object. +type UpdateOpts struct { + // OPTIONAL + Name string + // OPTIONAL + Description string + // OPTIONAL + Metadata map[string]string +} + +// ToVolumeUpdateMap assembles a request body based on the contents of an +// UpdateOpts. +func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) { + v := make(map[string]interface{}) + + if opts.Description != "" { + v["display_description"] = opts.Description + } + if opts.Metadata != nil { + v["metadata"] = opts.Metadata + } + if opts.Name != "" { + v["display_name"] = opts.Name + } + + return map[string]interface{}{"volume": v}, nil +} + +// Update will update the Volume with provided information. To extract the updated +// Volume from the response, call the Extract method on the UpdateResult. +func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToVolumeUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Put(updateURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// IDFromName is a convienience function that returns a server's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + volumeCount := 0 + volumeID := "" + if name == "" { + return "", fmt.Errorf("A volume name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + volumeList, err := ExtractVolumes(page) + if err != nil { + return false, err + } + + for _, s := range volumeList { + if s.Name == name { + volumeCount++ + volumeID = s.ID + } + } + return true, nil + }) + + switch volumeCount { + case 0: + return "", fmt.Errorf("Unable to find volume: %s", name) + case 1: + return volumeID, nil + default: + return "", fmt.Errorf("Found %d volumes matching %s", volumeCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go new file mode 100644 index 000000000..2fd4ef14e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go @@ -0,0 +1,113 @@ +package volumes + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Volume contains all the information associated with an OpenStack Volume. +type Volume struct { + // Current status of the volume. + Status string `mapstructure:"status"` + + // Human-readable display name for the volume. + Name string `mapstructure:"display_name"` + + // Instances onto which the volume is attached. + Attachments []map[string]interface{} `mapstructure:"attachments"` + + // This parameter is no longer used. + AvailabilityZone string `mapstructure:"availability_zone"` + + // Indicates whether this is a bootable volume. + Bootable string `mapstructure:"bootable"` + + // The date when this volume was created. + CreatedAt string `mapstructure:"created_at"` + + // Human-readable description for the volume. + Description string `mapstructure:"display_description"` + + // The type of volume to create, either SATA or SSD. + VolumeType string `mapstructure:"volume_type"` + + // The ID of the snapshot from which the volume was created + SnapshotID string `mapstructure:"snapshot_id"` + + // The ID of another block storage volume from which the current volume was created + SourceVolID string `mapstructure:"source_volid"` + + // Arbitrary key-value pairs defined by the user. + Metadata map[string]string `mapstructure:"metadata"` + + // Unique identifier for the volume. + ID string `mapstructure:"id"` + + // Size of the volume in GB. + Size int `mapstructure:"size"` +} + +// CreateResult contains the response body and error from a Create request. +type CreateResult struct { + commonResult +} + +// GetResult contains the response body and error from a Get request. +type GetResult struct { + commonResult +} + +// DeleteResult contains the response body and error from a Delete request. +type DeleteResult struct { + gophercloud.ErrResult +} + +// ListResult is a pagination.pager that is returned from a call to the List function. +type ListResult struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ListResult contains no Volumes. +func (r ListResult) IsEmpty() (bool, error) { + volumes, err := ExtractVolumes(r) + if err != nil { + return true, err + } + return len(volumes) == 0, nil +} + +// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call. +func ExtractVolumes(page pagination.Page) ([]Volume, error) { + var response struct { + Volumes []Volume `json:"volumes"` + } + + err := mapstructure.Decode(page.(ListResult).Body, &response) + return response.Volumes, err +} + +// UpdateResult contains the response body and error from an Update request. +type UpdateResult struct { + commonResult +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will get the Volume object out of the commonResult object. +func (r commonResult) Extract() (*Volume, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Volume *Volume `json:"volume"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Volume, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go new file mode 100644 index 000000000..2f66ba5e4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go @@ -0,0 +1,7 @@ +/* +This is package created is to hold fixtures (which imports testing), +so that importing volumes package does not inadvertently import testing into production code +More information here: +https://github.com/rackspace/gophercloud/issues/473 +*/ +package testing diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go new file mode 100644 index 000000000..3df7653f7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go @@ -0,0 +1,113 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` + { + "volumes": [ + { + "id": "289da7f8-6440-407c-9fb4-7db01ec49164", + "display_name": "vol-001" + }, + { + "id": "96c3bda7-c82a-4f50-be73-ca7621794835", + "display_name": "vol-002" + } + ] + } + `) + }) +} + +func MockGetResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` +{ + "volume": { + "display_name": "vol-001", + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "attachments": [ + { + "device": "/dev/vde", + "server_id": "a740d24b-dc5b-4d59-ac75-53971c2920ba", + "id": "d6da11e5-2ed3-413e-88d8-b772ba62193d", + "volume_id": "d6da11e5-2ed3-413e-88d8-b772ba62193d" + } + ] + } +} + `) + }) +} + +func MockCreateResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ` +{ + "volume": { + "size": 75 + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + + fmt.Fprintf(w, ` +{ + "volume": { + "size": 4, + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" + } +} + `) + }) +} + +func MockDeleteResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} + +func MockUpdateResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` + { + "volume": { + "display_name": "vol-002", + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" + } + } + `) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go new file mode 100644 index 000000000..29629a1af --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go @@ -0,0 +1,23 @@ +package volumes + +import "github.com/rackspace/gophercloud" + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("volumes") +} + +func listURL(c *gophercloud.ServiceClient) string { + return createURL(c) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("volumes", id) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return deleteURL(c, id) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return deleteURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go new file mode 100644 index 000000000..1dda695ea --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go @@ -0,0 +1,22 @@ +package volumes + +import ( + "github.com/rackspace/gophercloud" +) + +// WaitForStatus will continually poll the resource, checking for a particular +// status. It will do this for the amount of seconds defined. +func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error { + return gophercloud.WaitFor(secs, func() (bool, error) { + current, err := Get(c, id).Extract() + if err != nil { + return false, err + } + + if current.Status == status { + return true, nil + } + + return false, nil + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go new file mode 100644 index 000000000..793084f89 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go @@ -0,0 +1,9 @@ +// Package volumetypes provides information and interaction with volume types +// in the OpenStack Block Storage service. A volume type indicates the type of +// a block storage volume, such as SATA, SCSCI, SSD, etc. These can be +// customized or defined by the OpenStack admin. +// +// You can also define extra_specs associated with your volume types. For +// instance, you could have a VolumeType=SATA, with extra_specs (RPM=10000, +// RAID-Level=5) . Extra_specs are defined and customized by the admin. +package volumetypes diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go new file mode 100644 index 000000000..e3326eae1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go @@ -0,0 +1,60 @@ +package volumetypes + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListResponse(t *testing.T) { + th.Mux.HandleFunc("/types", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` + { + "volume_types": [ + { + "id": "289da7f8-6440-407c-9fb4-7db01ec49164", + "name": "vol-type-001", + "extra_specs": { + "capabilities": "gpu" + } + }, + { + "id": "96c3bda7-c82a-4f50-be73-ca7621794835", + "name": "vol-type-002", + "extra_specs": {} + } + ] + } + `) + }) +} + +func MockGetResponse(t *testing.T) { + th.Mux.HandleFunc("/types/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` +{ + "volume_type": { + "name": "vol-type-001", + "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "extra_specs": { + "serverNumber": "2" + } + } +} + `) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go new file mode 100644 index 000000000..1673d13aa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go @@ -0,0 +1,76 @@ +package volumetypes + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToVolumeTypeCreateMap() (map[string]interface{}, error) +} + +// CreateOpts are options for creating a volume type. +type CreateOpts struct { + // OPTIONAL. See VolumeType. + ExtraSpecs map[string]interface{} + // OPTIONAL. See VolumeType. + Name string +} + +// ToVolumeTypeCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToVolumeTypeCreateMap() (map[string]interface{}, error) { + vt := make(map[string]interface{}) + + if opts.ExtraSpecs != nil { + vt["extra_specs"] = opts.ExtraSpecs + } + if opts.Name != "" { + vt["name"] = opts.Name + } + + return map[string]interface{}{"volume_type": vt}, nil +} + +// Create will create a new volume. To extract the created volume type object, +// call the Extract method on the CreateResult. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToVolumeTypeCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + return res +} + +// Delete will delete the volume type with the provided ID. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} + +// Get will retrieve the volume type with the provided ID. To extract the volume +// type from the result, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, err := client.Get(getURL(client, id), &res.Body, nil) + res.Err = err + return res +} + +// List returns all volume types. +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return ListResult{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, listURL(client), createPage) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go new file mode 100644 index 000000000..c049a045d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go @@ -0,0 +1,72 @@ +package volumetypes + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// VolumeType contains all information associated with an OpenStack Volume Type. +type VolumeType struct { + ExtraSpecs map[string]interface{} `json:"extra_specs" mapstructure:"extra_specs"` // user-defined metadata + ID string `json:"id" mapstructure:"id"` // unique identifier + Name string `json:"name" mapstructure:"name"` // display name +} + +// CreateResult contains the response body and error from a Create request. +type CreateResult struct { + commonResult +} + +// GetResult contains the response body and error from a Get request. +type GetResult struct { + commonResult +} + +// DeleteResult contains the response error from a Delete request. +type DeleteResult struct { + gophercloud.ErrResult +} + +// ListResult is a pagination.Pager that is returned from a call to the List function. +type ListResult struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ListResult contains no Volume Types. +func (r ListResult) IsEmpty() (bool, error) { + volumeTypes, err := ExtractVolumeTypes(r) + if err != nil { + return true, err + } + return len(volumeTypes) == 0, nil +} + +// ExtractVolumeTypes extracts and returns Volume Types. +func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) { + var response struct { + VolumeTypes []VolumeType `mapstructure:"volume_types"` + } + + err := mapstructure.Decode(page.(ListResult).Body, &response) + return response.VolumeTypes, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will get the Volume Type object out of the commonResult object. +func (r commonResult) Extract() (*VolumeType, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.VolumeType, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go new file mode 100644 index 000000000..cf8367bfa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go @@ -0,0 +1,19 @@ +package volumetypes + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("types") +} + +func createURL(c *gophercloud.ServiceClient) string { + return listURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("types", id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go new file mode 100644 index 000000000..f78d4f735 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go @@ -0,0 +1,4 @@ +// Package base provides information and interaction with the base API +// resource in the OpenStack CDN service. This API resource allows for +// retrieving the Home Document and pinging the root URL. +package base diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go new file mode 100644 index 000000000..19b5ece46 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go @@ -0,0 +1,53 @@ +package base + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleGetSuccessfully creates an HTTP handler at `/` on the test handler mux +// that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` + { + "resources": { + "rel/cdn": { + "href-template": "services{?marker,limit}", + "href-vars": { + "marker": "param/marker", + "limit": "param/limit" + }, + "hints": { + "allow": [ + "GET" + ], + "formats": { + "application/json": {} + } + } + } + } + } + `) + + }) +} + +// HandlePingSuccessfully creates an HTTP handler at `/ping` on the test handler +// mux that responds with a `Ping` response. +func HandlePingSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go new file mode 100644 index 000000000..dd221bc98 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go @@ -0,0 +1,21 @@ +package base + +import "github.com/rackspace/gophercloud" + +// Get retrieves the home document, allowing the user to discover the +// entire API. +func Get(c *gophercloud.ServiceClient) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c), &res.Body, nil) + return res +} + +// Ping retrieves a ping to the server. +func Ping(c *gophercloud.ServiceClient) PingResult { + var res PingResult + _, res.Err = c.Get(pingURL(c), nil, &gophercloud.RequestOpts{ + OkCodes: []int{204}, + MoreHeaders: map[string]string{"Accept": ""}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go new file mode 100644 index 000000000..bef1da8a1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go @@ -0,0 +1,35 @@ +package base + +import ( + "errors" + + "github.com/rackspace/gophercloud" +) + +// HomeDocument is a resource that contains all the resources for the CDN API. +type HomeDocument map[string]interface{} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a home document resource. +func (r GetResult) Extract() (*HomeDocument, error) { + if r.Err != nil { + return nil, r.Err + } + + submap, ok := r.Body.(map[string]interface{})["resources"] + if !ok { + return nil, errors.New("Unexpected HomeDocument structure") + } + casted := HomeDocument(submap.(map[string]interface{})) + + return &casted, nil +} + +// PingResult represents the result of a Ping operation. +type PingResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go new file mode 100644 index 000000000..a95e18bca --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go @@ -0,0 +1,11 @@ +package base + +import "github.com/rackspace/gophercloud" + +func getURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL() +} + +func pingURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("ping") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go new file mode 100644 index 000000000..d4066985c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go @@ -0,0 +1,6 @@ +// Package flavors provides information and interaction with the flavors API +// resource in the OpenStack CDN service. This API resource allows for +// listing flavors and retrieving a specific flavor. +// +// A flavor is a mapping configuration to a CDN provider. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go new file mode 100644 index 000000000..d7ec1a00d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go @@ -0,0 +1,82 @@ +package flavors + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleListCDNFlavorsSuccessfully creates an HTTP handler at `/flavors` on the test handler mux +// that responds with a `List` response. +func HandleListCDNFlavorsSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/flavors", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` + { + "flavors": [ + { + "id": "europe", + "providers": [ + { + "provider": "Fastly", + "links": [ + { + "href": "http://www.fastly.com", + "rel": "provider_url" + } + ] + } + ], + "links": [ + { + "href": "https://www.poppycdn.io/v1.0/flavors/europe", + "rel": "self" + } + ] + } + ] + } + `) + }) +} + +// HandleGetCDNFlavorSuccessfully creates an HTTP handler at `/flavors/{id}` on the test handler mux +// that responds with a `Get` response. +func HandleGetCDNFlavorSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/flavors/asia", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` + { + "id" : "asia", + "providers" : [ + { + "provider" : "ChinaCache", + "links": [ + { + "href": "http://www.chinacache.com", + "rel": "provider_url" + } + ] + } + ], + "links": [ + { + "href": "https://www.poppycdn.io/v1.0/flavors/asia", + "rel": "self" + } + ] + } + `) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go new file mode 100644 index 000000000..8755a95b8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go @@ -0,0 +1,22 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a single page of CDN flavors. +func List(c *gophercloud.ServiceClient) pagination.Pager { + url := listURL(c) + createPage := func(r pagination.PageResult) pagination.Page { + return FlavorPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Get retrieves a specific flavor based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go new file mode 100644 index 000000000..8cab48b53 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go @@ -0,0 +1,71 @@ +package flavors + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Provider represents a provider for a particular flavor. +type Provider struct { + // Specifies the name of the provider. The name must not exceed 64 bytes in + // length and is limited to unicode, digits, underscores, and hyphens. + Provider string `mapstructure:"provider"` + // Specifies a list with an href where rel is provider_url. + Links []gophercloud.Link `mapstructure:"links"` +} + +// Flavor represents a mapping configuration to a CDN provider. +type Flavor struct { + // Specifies the name of the flavor. The name must not exceed 64 bytes in + // length and is limited to unicode, digits, underscores, and hyphens. + ID string `mapstructure:"id"` + // Specifies the list of providers mapped to this flavor. + Providers []Provider `mapstructure:"providers"` + // Specifies the self-navigating JSON document paths. + Links []gophercloud.Link `mapstructure:"links"` +} + +// FlavorPage is the page returned by a pager when traversing over a +// collection of CDN flavors. +type FlavorPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a FlavorPage contains no Flavors. +func (r FlavorPage) IsEmpty() (bool, error) { + flavors, err := ExtractFlavors(r) + if err != nil { + return true, err + } + return len(flavors) == 0, nil +} + +// ExtractFlavors extracts and returns Flavors. It is used while iterating over +// a flavors.List call. +func ExtractFlavors(page pagination.Page) ([]Flavor, error) { + var response struct { + Flavors []Flavor `json:"flavors"` + } + + err := mapstructure.Decode(page.(FlavorPage).Body, &response) + return response.Flavors, err +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that extracts a flavor from a GetResult. +func (r GetResult) Extract() (*Flavor, error) { + if r.Err != nil { + return nil, r.Err + } + + var res Flavor + + err := mapstructure.Decode(r.Body, &res) + + return &res, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go new file mode 100644 index 000000000..6eb38d293 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go @@ -0,0 +1,11 @@ +package flavors + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("flavors") +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("flavors", id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go new file mode 100644 index 000000000..ceecaa5a5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go @@ -0,0 +1,7 @@ +// Package serviceassets provides information and interaction with the +// serviceassets API resource in the OpenStack CDN service. This API resource +// allows for deleting cached assets. +// +// A service distributes assets across the network. Service assets let you +// interrogate properties about these assets and perform certain actions on them. +package serviceassets diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go new file mode 100644 index 000000000..5c6b5d00e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go @@ -0,0 +1,19 @@ +package serviceassets + +import ( + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleDeleteCDNAssetSuccessfully creates an HTTP handler at `/services/{id}/assets` on the test handler mux +// that responds with a `Delete` response. +func HandleDeleteCDNAssetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0/assets", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go new file mode 100644 index 000000000..1ddc65faf --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go @@ -0,0 +1,48 @@ +package serviceassets + +import ( + "strings" + + "github.com/rackspace/gophercloud" +) + +// DeleteOptsBuilder allows extensions to add additional parameters to the Delete +// request. +type DeleteOptsBuilder interface { + ToCDNAssetDeleteParams() (string, error) +} + +// DeleteOpts is a structure that holds options for deleting CDN service assets. +type DeleteOpts struct { + // If all is set to true, specifies that the delete occurs against all of the + // assets for the service. + All bool `q:"all"` + // Specifies the relative URL of the asset to be deleted. + URL string `q:"url"` +} + +// ToCDNAssetDeleteParams formats a DeleteOpts into a query string. +func (opts DeleteOpts) ToCDNAssetDeleteParams() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// Delete accepts a unique service ID or URL and deletes the CDN service asset associated with +// it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and +// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" +// are valid options for idOrURL. +func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder) DeleteResult { + var url string + if strings.Contains(idOrURL, "/") { + url = idOrURL + } else { + url = deleteURL(c, idOrURL) + } + + var res DeleteResult + _, res.Err = c.Delete(url, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go new file mode 100644 index 000000000..1d8734b7c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go @@ -0,0 +1,8 @@ +package serviceassets + +import "github.com/rackspace/gophercloud" + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go new file mode 100644 index 000000000..cb0aea8fc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go @@ -0,0 +1,7 @@ +package serviceassets + +import "github.com/rackspace/gophercloud" + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("services", id, "assets") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go new file mode 100644 index 000000000..41f7c60da --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go @@ -0,0 +1,7 @@ +// Package services provides information and interaction with the services API +// resource in the OpenStack CDN service. This API resource allows for +// listing, creating, updating, retrieving, and deleting services. +// +// A service represents an application that has its content cached to the edge +// nodes. +package services diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go new file mode 100644 index 000000000..359584c2a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go @@ -0,0 +1,7 @@ +package services + +import "fmt" + +func no(str string) error { + return fmt.Errorf("Required parameter %s not provided", str) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go new file mode 100644 index 000000000..d9bc9f20b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go @@ -0,0 +1,372 @@ +package services + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleListCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux +// that responds with a `List` response. +func HandleListCDNServiceSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, ` + { + "links": [ + { + "rel": "next", + "href": "https://www.poppycdn.io/v1.0/services?marker=96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0&limit=20" + } + ], + "services": [ + { + "id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", + "name": "mywebsite.com", + "domains": [ + { + "domain": "www.mywebsite.com" + } + ], + "origins": [ + { + "origin": "mywebsite.com", + "port": 80, + "ssl": false + } + ], + "caching": [ + { + "name": "default", + "ttl": 3600 + }, + { + "name": "home", + "ttl": 17200, + "rules": [ + { + "name": "index", + "request_url": "/index.htm" + } + ] + }, + { + "name": "images", + "ttl": 12800, + "rules": [ + { + "name": "images", + "request_url": "*.png" + } + ] + } + ], + "restrictions": [ + { + "name": "website only", + "rules": [ + { + "name": "mywebsite.com", + "referrer": "www.mywebsite.com" + } + ] + } + ], + "flavor_id": "asia", + "status": "deployed", + "errors" : [], + "links": [ + { + "href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", + "rel": "self" + }, + { + "href": "mywebsite.com.cdn123.poppycdn.net", + "rel": "access_url" + }, + { + "href": "https://www.poppycdn.io/v1.0/flavors/asia", + "rel": "flavor" + } + ] + }, + { + "id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1", + "name": "myothersite.com", + "domains": [ + { + "domain": "www.myothersite.com" + } + ], + "origins": [ + { + "origin": "44.33.22.11", + "port": 80, + "ssl": false + }, + { + "origin": "77.66.55.44", + "port": 80, + "ssl": false, + "rules": [ + { + "name": "videos", + "request_url": "^/videos/*.m3u" + } + ] + } + ], + "caching": [ + { + "name": "default", + "ttl": 3600 + } + ], + "restrictions": [ + {} + ], + "flavor_id": "europe", + "status": "deployed", + "links": [ + { + "href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1", + "rel": "self" + }, + { + "href": "myothersite.com.poppycdn.net", + "rel": "access_url" + }, + { + "href": "https://www.poppycdn.io/v1.0/flavors/europe", + "rel": "flavor" + } + ] + } + ] + } + `) + case "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1": + fmt.Fprintf(w, `{ + "services": [] + }`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// HandleCreateCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux +// that responds with a `Create` response. +func HandleCreateCDNServiceSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestJSONRequest(t, r, ` + { + "name": "mywebsite.com", + "domains": [ + { + "domain": "www.mywebsite.com" + }, + { + "domain": "blog.mywebsite.com" + } + ], + "origins": [ + { + "origin": "mywebsite.com", + "port": 80, + "ssl": false + } + ], + "restrictions": [ + { + "name": "website only", + "rules": [ + { + "name": "mywebsite.com", + "referrer": "www.mywebsite.com" + } + ] + } + ], + "caching": [ + { + "name": "default", + "ttl": 3600 + } + ], + + "flavor_id": "cdn" + } + `) + w.Header().Add("Location", "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0") + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleGetCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux +// that responds with a `Get` response. +func HandleGetCDNServiceSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` + { + "id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", + "name": "mywebsite.com", + "domains": [ + { + "domain": "www.mywebsite.com", + "protocol": "http" + } + ], + "origins": [ + { + "origin": "mywebsite.com", + "port": 80, + "ssl": false + } + ], + "caching": [ + { + "name": "default", + "ttl": 3600 + }, + { + "name": "home", + "ttl": 17200, + "rules": [ + { + "name": "index", + "request_url": "/index.htm" + } + ] + }, + { + "name": "images", + "ttl": 12800, + "rules": [ + { + "name": "images", + "request_url": "*.png" + } + ] + } + ], + "restrictions": [ + { + "name": "website only", + "rules": [ + { + "name": "mywebsite.com", + "referrer": "www.mywebsite.com" + } + ] + } + ], + "flavor_id": "cdn", + "status": "deployed", + "errors" : [], + "links": [ + { + "href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", + "rel": "self" + }, + { + "href": "blog.mywebsite.com.cdn1.raxcdn.com", + "rel": "access_url" + }, + { + "href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/flavors/cdn", + "rel": "flavor" + } + ] + } + `) + }) +} + +// HandleUpdateCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux +// that responds with a `Update` response. +func HandleUpdateCDNServiceSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PATCH") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestJSONRequest(t, r, ` + [ + { + "op": "add", + "path": "/domains/-", + "value": {"domain": "appended.mocksite4.com"} + }, + { + "op": "add", + "path": "/domains/4", + "value": {"domain": "inserted.mocksite4.com"} + }, + { + "op": "add", + "path": "/domains", + "value": [ + {"domain": "bulkadded1.mocksite4.com"}, + {"domain": "bulkadded2.mocksite4.com"} + ] + }, + { + "op": "replace", + "path": "/origins/2", + "value": {"origin": "44.33.22.11", "port": 80, "ssl": false} + }, + { + "op": "replace", + "path": "/origins", + "value": [ + {"origin": "44.33.22.11", "port": 80, "ssl": false}, + {"origin": "55.44.33.22", "port": 443, "ssl": true} + ] + }, + { + "op": "remove", + "path": "/caching/8" + }, + { + "op": "remove", + "path": "/caching" + }, + { + "op": "replace", + "path": "/name", + "value": "differentServiceName" + } + ] + `) + w.Header().Add("Location", "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0") + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleDeleteCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux +// that responds with a `Delete` response. +func HandleDeleteCDNServiceSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go new file mode 100644 index 000000000..8b37928e2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go @@ -0,0 +1,378 @@ +package services + +import ( + "fmt" + "strings" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToCDNServiceListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Marker and Limit are used for pagination. +type ListOpts struct { + Marker string `q:"marker"` + Limit int `q:"limit"` +} + +// ToCDNServiceListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToCDNServiceListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// CDN services. It accepts a ListOpts struct, which allows for pagination via +// marker and limit. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToCDNServiceListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPage := func(r pagination.PageResult) pagination.Page { + p := ServicePage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + } + + pager := pagination.NewPager(c, url, createPage) + return pager +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToCDNServiceCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // REQUIRED. Specifies the name of the service. The minimum length for name is + // 3. The maximum length is 256. + Name string + // REQUIRED. Specifies a list of domains used by users to access their website. + Domains []Domain + // REQUIRED. Specifies a list of origin domains or IP addresses where the + // original assets are stored. + Origins []Origin + // REQUIRED. Specifies the CDN provider flavor ID to use. For a list of + // flavors, see the operation to list the available flavors. The minimum + // length for flavor_id is 1. The maximum length is 256. + FlavorID string + // OPTIONAL. Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control. + Caching []CacheRule + // OPTIONAL. Specifies the restrictions that define who can access assets (content from the CDN cache). + Restrictions []Restriction +} + +// ToCDNServiceCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToCDNServiceCreateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.Name == "" { + return nil, no("Name") + } + s["name"] = opts.Name + + if opts.Domains == nil { + return nil, no("Domains") + } + for _, domain := range opts.Domains { + if domain.Domain == "" { + return nil, no("Domains[].Domain") + } + } + s["domains"] = opts.Domains + + if opts.Origins == nil { + return nil, no("Origins") + } + for _, origin := range opts.Origins { + if origin.Origin == "" { + return nil, no("Origins[].Origin") + } + if origin.Rules == nil && len(opts.Origins) > 1 { + return nil, no("Origins[].Rules") + } + for _, rule := range origin.Rules { + if rule.Name == "" { + return nil, no("Origins[].Rules[].Name") + } + if rule.RequestURL == "" { + return nil, no("Origins[].Rules[].RequestURL") + } + } + } + s["origins"] = opts.Origins + + if opts.FlavorID == "" { + return nil, no("FlavorID") + } + s["flavor_id"] = opts.FlavorID + + if opts.Caching != nil { + for _, cache := range opts.Caching { + if cache.Name == "" { + return nil, no("Caching[].Name") + } + if cache.Rules != nil { + for _, rule := range cache.Rules { + if rule.Name == "" { + return nil, no("Caching[].Rules[].Name") + } + if rule.RequestURL == "" { + return nil, no("Caching[].Rules[].RequestURL") + } + } + } + } + s["caching"] = opts.Caching + } + + if opts.Restrictions != nil { + for _, restriction := range opts.Restrictions { + if restriction.Name == "" { + return nil, no("Restrictions[].Name") + } + if restriction.Rules != nil { + for _, rule := range restriction.Rules { + if rule.Name == "" { + return nil, no("Restrictions[].Rules[].Name") + } + } + } + } + s["restrictions"] = opts.Restrictions + } + + return s, nil +} + +// Create accepts a CreateOpts struct and creates a new CDN service using the +// values provided. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToCDNServiceCreateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + resp, err := c.Post(createURL(c), &reqBody, nil, nil) + res.Header = resp.Header + res.Err = err + return res +} + +// Get retrieves a specific service based on its URL or its unique ID. For +// example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and +// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" +// are valid options for idOrURL. +func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult { + var url string + if strings.Contains(idOrURL, "/") { + url = idOrURL + } else { + url = getURL(c, idOrURL) + } + + var res GetResult + _, res.Err = c.Get(url, &res.Body, nil) + return res +} + +// Path is a JSON pointer location that indicates which service parameter is being added, replaced, +// or removed. +type Path struct { + baseElement string +} + +func (p Path) renderRoot() string { + return "/" + p.baseElement +} + +func (p Path) renderDash() string { + return fmt.Sprintf("/%s/-", p.baseElement) +} + +func (p Path) renderIndex(index int64) string { + return fmt.Sprintf("/%s/%d", p.baseElement, index) +} + +var ( + // PathDomains indicates that an update operation is to be performed on a Domain. + PathDomains = Path{baseElement: "domains"} + + // PathOrigins indicates that an update operation is to be performed on an Origin. + PathOrigins = Path{baseElement: "origins"} + + // PathCaching indicates that an update operation is to be performed on a CacheRule. + PathCaching = Path{baseElement: "caching"} +) + +type value interface { + toPatchValue() interface{} + appropriatePath() Path + renderRootOr(func(p Path) string) string +} + +// Patch represents a single update to an existing Service. Multiple updates to a service can be +// submitted at the same time. +type Patch interface { + ToCDNServiceUpdateMap() map[string]interface{} +} + +// Insertion is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to +// a Service at a fixed index. Use an Append instead to append the new value to the end of its +// collection. Pass it to the Update function as part of the Patch slice. +type Insertion struct { + Index int64 + Value value +} + +// ToCDNServiceUpdateMap converts an Insertion into a request body fragment suitable for the +// Update call. +func (i Insertion) ToCDNServiceUpdateMap() map[string]interface{} { + return map[string]interface{}{ + "op": "add", + "path": i.Value.renderRootOr(func(p Path) string { return p.renderIndex(i.Index) }), + "value": i.Value.toPatchValue(), + } +} + +// Append is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to a +// Service at the end of its respective collection. Use an Insertion instead to insert the value +// at a fixed index within the collection. Pass this to the Update function as part of its +// Patch slice. +type Append struct { + Value value +} + +// ToCDNServiceUpdateMap converts an Append into a request body fragment suitable for the +// Update call. +func (a Append) ToCDNServiceUpdateMap() map[string]interface{} { + return map[string]interface{}{ + "op": "add", + "path": a.Value.renderRootOr(func(p Path) string { return p.renderDash() }), + "value": a.Value.toPatchValue(), + } +} + +// Replacement is a Patch that alters a specific service parameter (Domain, Origin, or CacheRule) +// in-place by index. Pass it to the Update function as part of the Patch slice. +type Replacement struct { + Value value + Index int64 +} + +// ToCDNServiceUpdateMap converts a Replacement into a request body fragment suitable for the +// Update call. +func (r Replacement) ToCDNServiceUpdateMap() map[string]interface{} { + return map[string]interface{}{ + "op": "replace", + "path": r.Value.renderRootOr(func(p Path) string { return p.renderIndex(r.Index) }), + "value": r.Value.toPatchValue(), + } +} + +// NameReplacement specifically updates the Service name. Pass it to the Update function as part +// of the Patch slice. +type NameReplacement struct { + NewName string +} + +// ToCDNServiceUpdateMap converts a NameReplacement into a request body fragment suitable for the +// Update call. +func (r NameReplacement) ToCDNServiceUpdateMap() map[string]interface{} { + return map[string]interface{}{ + "op": "replace", + "path": "/name", + "value": r.NewName, + } +} + +// Removal is a Patch that requests the removal of a service parameter (Domain, Origin, or +// CacheRule) by index. Pass it to the Update function as part of the Patch slice. +type Removal struct { + Path Path + Index int64 + All bool +} + +// ToCDNServiceUpdateMap converts a Removal into a request body fragment suitable for the +// Update call. +func (r Removal) ToCDNServiceUpdateMap() map[string]interface{} { + result := map[string]interface{}{"op": "remove"} + if r.All { + result["path"] = r.Path.renderRoot() + } else { + result["path"] = r.Path.renderIndex(r.Index) + } + return result +} + +type UpdateOpts []Patch + +// Update accepts a slice of Patch operations (Insertion, Append, Replacement or Removal) and +// updates an existing CDN service using the values provided. idOrURL can be either the service's +// URL or its ID. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and +// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" +// are valid options for idOrURL. +func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) UpdateResult { + var url string + if strings.Contains(idOrURL, "/") { + url = idOrURL + } else { + url = updateURL(c, idOrURL) + } + + reqBody := make([]map[string]interface{}, len(opts)) + for i, patch := range opts { + reqBody[i] = patch.ToCDNServiceUpdateMap() + } + + resp, err := c.Request("PATCH", url, gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + var result UpdateResult + result.Header = resp.Header + result.Err = err + return result +} + +// Delete accepts a service's ID or its URL and deletes the CDN service +// associated with it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and +// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" +// are valid options for idOrURL. +func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult { + var url string + if strings.Contains(idOrURL, "/") { + url = idOrURL + } else { + url = deleteURL(c, idOrURL) + } + + var res DeleteResult + _, res.Err = c.Delete(url, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go new file mode 100644 index 000000000..33406c482 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go @@ -0,0 +1,316 @@ +package services + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Domain represents a domain used by users to access their website. +type Domain struct { + // Specifies the domain used to access the assets on their website, for which + // a CNAME is given to the CDN provider. + Domain string `mapstructure:"domain" json:"domain"` + // Specifies the protocol used to access the assets on this domain. Only "http" + // or "https" are currently allowed. The default is "http". + Protocol string `mapstructure:"protocol" json:"protocol,omitempty"` +} + +func (d Domain) toPatchValue() interface{} { + r := make(map[string]interface{}) + r["domain"] = d.Domain + if d.Protocol != "" { + r["protocol"] = d.Protocol + } + return r +} + +func (d Domain) appropriatePath() Path { + return PathDomains +} + +func (d Domain) renderRootOr(render func(p Path) string) string { + return render(d.appropriatePath()) +} + +// DomainList provides a useful way to perform bulk operations in a single Patch. +type DomainList []Domain + +func (list DomainList) toPatchValue() interface{} { + r := make([]interface{}, len(list)) + for i, domain := range list { + r[i] = domain.toPatchValue() + } + return r +} + +func (list DomainList) appropriatePath() Path { + return PathDomains +} + +func (list DomainList) renderRootOr(_ func(p Path) string) string { + return list.appropriatePath().renderRoot() +} + +// OriginRule represents a rule that defines when an origin should be accessed. +type OriginRule struct { + // Specifies the name of this rule. + Name string `mapstructure:"name" json:"name"` + // Specifies the request URL this rule should match for this origin to be used. Regex is supported. + RequestURL string `mapstructure:"request_url" json:"request_url"` +} + +// Origin specifies a list of origin domains or IP addresses where the original assets are stored. +type Origin struct { + // Specifies the URL or IP address to pull origin content from. + Origin string `mapstructure:"origin" json:"origin"` + // Specifies the port used to access the origin. The default is port 80. + Port int `mapstructure:"port" json:"port,omitempty"` + // Specifies whether or not to use HTTPS to access the origin. The default + // is false. + SSL bool `mapstructure:"ssl" json:"ssl"` + // Specifies a collection of rules that define the conditions when this origin + // should be accessed. If there is more than one origin, the rules parameter is required. + Rules []OriginRule `mapstructure:"rules" json:"rules,omitempty"` +} + +func (o Origin) toPatchValue() interface{} { + r := make(map[string]interface{}) + r["origin"] = o.Origin + r["port"] = o.Port + r["ssl"] = o.SSL + if len(o.Rules) > 0 { + r["rules"] = make([]map[string]interface{}, len(o.Rules)) + for index, rule := range o.Rules { + submap := r["rules"].([]map[string]interface{})[index] + submap["name"] = rule.Name + submap["request_url"] = rule.RequestURL + } + } + return r +} + +func (o Origin) appropriatePath() Path { + return PathOrigins +} + +func (o Origin) renderRootOr(render func(p Path) string) string { + return render(o.appropriatePath()) +} + +// OriginList provides a useful way to perform bulk operations in a single Patch. +type OriginList []Origin + +func (list OriginList) toPatchValue() interface{} { + r := make([]interface{}, len(list)) + for i, origin := range list { + r[i] = origin.toPatchValue() + } + return r +} + +func (list OriginList) appropriatePath() Path { + return PathOrigins +} + +func (list OriginList) renderRootOr(_ func(p Path) string) string { + return list.appropriatePath().renderRoot() +} + +// TTLRule specifies a rule that determines if a TTL should be applied to an asset. +type TTLRule struct { + // Specifies the name of this rule. + Name string `mapstructure:"name" json:"name"` + // Specifies the request URL this rule should match for this TTL to be used. Regex is supported. + RequestURL string `mapstructure:"request_url" json:"request_url"` +} + +// CacheRule specifies the TTL rules for the assets under this service. +type CacheRule struct { + // Specifies the name of this caching rule. Note: 'default' is a reserved name used for the default TTL setting. + Name string `mapstructure:"name" json:"name"` + // Specifies the TTL to apply. + TTL int `mapstructure:"ttl" json:"ttl"` + // Specifies a collection of rules that determine if this TTL should be applied to an asset. + Rules []TTLRule `mapstructure:"rules" json:"rules,omitempty"` +} + +func (c CacheRule) toPatchValue() interface{} { + r := make(map[string]interface{}) + r["name"] = c.Name + r["ttl"] = c.TTL + r["rules"] = make([]map[string]interface{}, len(c.Rules)) + for index, rule := range c.Rules { + submap := r["rules"].([]map[string]interface{})[index] + submap["name"] = rule.Name + submap["request_url"] = rule.RequestURL + } + return r +} + +func (c CacheRule) appropriatePath() Path { + return PathCaching +} + +func (c CacheRule) renderRootOr(render func(p Path) string) string { + return render(c.appropriatePath()) +} + +// CacheRuleList provides a useful way to perform bulk operations in a single Patch. +type CacheRuleList []CacheRule + +func (list CacheRuleList) toPatchValue() interface{} { + r := make([]interface{}, len(list)) + for i, rule := range list { + r[i] = rule.toPatchValue() + } + return r +} + +func (list CacheRuleList) appropriatePath() Path { + return PathCaching +} + +func (list CacheRuleList) renderRootOr(_ func(p Path) string) string { + return list.appropriatePath().renderRoot() +} + +// RestrictionRule specifies a rule that determines if this restriction should be applied to an asset. +type RestrictionRule struct { + // Specifies the name of this rule. + Name string `mapstructure:"name" json:"name"` + // Specifies the http host that requests must come from. + Referrer string `mapstructure:"referrer" json:"referrer,omitempty"` +} + +// Restriction specifies a restriction that defines who can access assets (content from the CDN cache). +type Restriction struct { + // Specifies the name of this restriction. + Name string `mapstructure:"name" json:"name"` + // Specifies a collection of rules that determine if this TTL should be applied to an asset. + Rules []RestrictionRule `mapstructure:"rules" json:"rules"` +} + +// Error specifies an error that occurred during the previous service action. +type Error struct { + // Specifies an error message detailing why there is an error. + Message string `mapstructure:"message"` +} + +// Service represents a CDN service resource. +type Service struct { + // Specifies the service ID that represents distributed content. The value is + // a UUID, such as 96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0, that is generated by the server. + ID string `mapstructure:"id"` + // Specifies the name of the service. + Name string `mapstructure:"name"` + // Specifies a list of domains used by users to access their website. + Domains []Domain `mapstructure:"domains"` + // Specifies a list of origin domains or IP addresses where the original assets are stored. + Origins []Origin `mapstructure:"origins"` + // Specifies the TTL rules for the assets under this service. Supports wildcards for fine grained control. + Caching []CacheRule `mapstructure:"caching"` + // Specifies the restrictions that define who can access assets (content from the CDN cache). + Restrictions []Restriction `mapstructure:"restrictions" json:"restrictions,omitempty"` + // Specifies the CDN provider flavor ID to use. For a list of flavors, see the operation to list the available flavors. + FlavorID string `mapstructure:"flavor_id"` + // Specifies the current status of the service. + Status string `mapstructure:"status"` + // Specifies the list of errors that occurred during the previous service action. + Errors []Error `mapstructure:"errors"` + // Specifies the self-navigating JSON document paths. + Links []gophercloud.Link `mapstructure:"links"` +} + +// ServicePage is the page returned by a pager when traversing over a +// collection of CDN services. +type ServicePage struct { + pagination.MarkerPageBase +} + +// IsEmpty returns true if a ListResult contains no services. +func (r ServicePage) IsEmpty() (bool, error) { + services, err := ExtractServices(r) + if err != nil { + return true, err + } + return len(services) == 0, nil +} + +// LastMarker returns the last service in a ListResult. +func (r ServicePage) LastMarker() (string, error) { + services, err := ExtractServices(r) + if err != nil { + return "", err + } + if len(services) == 0 { + return "", nil + } + return (services[len(services)-1]).ID, nil +} + +// ExtractServices is a function that takes a ListResult and returns the services' information. +func ExtractServices(page pagination.Page) ([]Service, error) { + var response struct { + Services []Service `mapstructure:"services"` + } + + err := mapstructure.Decode(page.(ServicePage).Body, &response) + return response.Services, err +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + gophercloud.Result +} + +// Extract is a method that extracts the location of a newly created service. +func (r CreateResult) Extract() (string, error) { + if r.Err != nil { + return "", r.Err + } + if l, ok := r.Header["Location"]; ok && len(l) > 0 { + return l[0], nil + } + return "", nil +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that extracts a service from a GetResult. +func (r GetResult) Extract() (*Service, error) { + if r.Err != nil { + return nil, r.Err + } + + var res Service + + err := mapstructure.Decode(r.Body, &res) + + return &res, err +} + +// UpdateResult represents the result of a Update operation. +type UpdateResult struct { + gophercloud.Result +} + +// Extract is a method that extracts the location of an updated service. +func (r UpdateResult) Extract() (string, error) { + if r.Err != nil { + return "", r.Err + } + if l, ok := r.Header["Location"]; ok && len(l) > 0 { + return l[0], nil + } + return "", nil +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go new file mode 100644 index 000000000..d953d4c19 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go @@ -0,0 +1,23 @@ +package services + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("services") +} + +func createURL(c *gophercloud.ServiceClient) string { + return listURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("services", id) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/client.go b/vendor/github.com/rackspace/gophercloud/openstack/client.go new file mode 100644 index 000000000..33602a696 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/client.go @@ -0,0 +1,274 @@ +package openstack + +import ( + "fmt" + "net/url" + + "github.com/rackspace/gophercloud" + tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens" + tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens" + "github.com/rackspace/gophercloud/openstack/utils" +) + +const ( + v20 = "v2.0" + v30 = "v3.0" +) + +// NewClient prepares an unauthenticated ProviderClient instance. +// Most users will probably prefer using the AuthenticatedClient function instead. +// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly, +// for example. +func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { + u, err := url.Parse(endpoint) + if err != nil { + return nil, err + } + hadPath := u.Path != "" + u.Path, u.RawQuery, u.Fragment = "", "", "" + base := u.String() + + endpoint = gophercloud.NormalizeURL(endpoint) + base = gophercloud.NormalizeURL(base) + + if hadPath { + return &gophercloud.ProviderClient{ + IdentityBase: base, + IdentityEndpoint: endpoint, + }, nil + } + + return &gophercloud.ProviderClient{ + IdentityBase: base, + IdentityEndpoint: "", + }, nil +} + +// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by options, acquires a token, and +// returns a Client instance that's ready to operate. +// It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses +// the most recent identity service available to proceed. +func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { + client, err := NewClient(options.IdentityEndpoint) + if err != nil { + return nil, err + } + + err = Authenticate(client, options) + if err != nil { + return nil, err + } + return client, nil +} + +// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint. +func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + versions := []*utils.Version{ + &utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"}, + &utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"}, + } + + chosen, endpoint, err := utils.ChooseVersion(client, versions) + if err != nil { + return err + } + + switch chosen.ID { + case v20: + return v2auth(client, endpoint, options) + case v30: + return v3auth(client, endpoint, options) + default: + // The switch statement must be out of date from the versions list. + return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) + } +} + +// AuthenticateV2 explicitly authenticates against the identity v2 endpoint. +func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + return v2auth(client, "", options) +} + +func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error { + v2Client := NewIdentityV2(client) + if endpoint != "" { + v2Client.Endpoint = endpoint + } + + result := tokens2.Create(v2Client, tokens2.AuthOptions{AuthOptions: options}) + + token, err := result.ExtractToken() + if err != nil { + return err + } + + catalog, err := result.ExtractServiceCatalog() + if err != nil { + return err + } + + if options.AllowReauth { + client.ReauthFunc = func() error { + client.TokenID = "" + return AuthenticateV2(client, options) + } + } + client.TokenID = token.ID + client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { + return V2EndpointURL(catalog, opts) + } + + return nil +} + +// AuthenticateV3 explicitly authenticates against the identity v3 service. +func AuthenticateV3(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + return v3auth(client, "", options) +} + +func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error { + // Override the generated service endpoint with the one returned by the version endpoint. + v3Client := NewIdentityV3(client) + if endpoint != "" { + v3Client.Endpoint = endpoint + } + + var scope *tokens3.Scope + if options.TenantID != "" { + scope = &tokens3.Scope{ + ProjectID: options.TenantID, + } + options.TenantID = "" + options.TenantName = "" + } else { + if options.TenantName != "" { + scope = &tokens3.Scope{ + ProjectName: options.TenantName, + DomainID: options.DomainID, + DomainName: options.DomainName, + } + options.TenantName = "" + } + } + + result := tokens3.Create(v3Client, options, scope) + + token, err := result.ExtractToken() + if err != nil { + return err + } + + catalog, err := result.ExtractServiceCatalog() + if err != nil { + return err + } + + client.TokenID = token.ID + + if options.AllowReauth { + client.ReauthFunc = func() error { + client.TokenID = "" + return AuthenticateV3(client, options) + } + } + client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { + return V3EndpointURL(catalog, opts) + } + + return nil +} + +// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service. +func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient { + v2Endpoint := client.IdentityBase + "v2.0/" + + return &gophercloud.ServiceClient{ + ProviderClient: client, + Endpoint: v2Endpoint, + } +} + +// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service. +func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient { + v3Endpoint := client.IdentityBase + "v3/" + + return &gophercloud.ServiceClient{ + ProviderClient: client, + Endpoint: v3Endpoint, + } +} + +// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package. +func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("object-store") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package. +func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("compute") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package. +func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("network") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ + ProviderClient: client, + Endpoint: url, + ResourceBase: url + "v2.0/", + }, nil +} + +// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service. +func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("volume") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1 +// CDN service. +func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("cdn") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service. +func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("orchestration") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. +func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("database") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/README.md b/vendor/github.com/rackspace/gophercloud/openstack/common/README.md new file mode 100644 index 000000000..7b55795d0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/README.md @@ -0,0 +1,3 @@ +# Common Resources + +This directory is for resources that are shared by multiple services. diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go new file mode 100644 index 000000000..4a168f4b2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go @@ -0,0 +1,15 @@ +// Package extensions provides information and interaction with the different extensions available +// for an OpenStack service. +// +// The purpose of OpenStack API extensions is to: +// +// - Introduce new features in the API without requiring a version change. +// - Introduce vendor-specific niche functionality. +// - Act as a proving ground for experimental functionalities that might be included in a future +// version of the API. +// +// Extensions usually have tags that prevent conflicts with other extensions that define attributes +// or resources with the same names, and with core resources and attributes. +// Because an extension might not be supported by all plug-ins, its availability varies with deployments +// and the specific plug-in. +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go new file mode 100644 index 000000000..aeec0fa75 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go @@ -0,0 +1 @@ +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go new file mode 100644 index 000000000..0ed7de9f1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go @@ -0,0 +1,91 @@ +// +build fixtures + +package extensions + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput provides a single page of Extension results. +const ListOutput = ` +{ + "extensions": [ + { + "updated": "2013-01-20T00:00:00-00:00", + "name": "Neutron Service Type Management", + "links": [], + "namespace": "http://docs.openstack.org/ext/neutron/service-type/api/v1.0", + "alias": "service-type", + "description": "API for retrieving service providers for Neutron advanced services" + } + ] +}` + +// GetOutput provides a single Extension result. +const GetOutput = ` +{ + "extension": { + "updated": "2013-02-03T10:00:00-00:00", + "name": "agent", + "links": [], + "namespace": "http://docs.openstack.org/ext/agent/api/v2.0", + "alias": "agent", + "description": "The agent management extension." + } +} +` + +// ListedExtension is the Extension that should be parsed from ListOutput. +var ListedExtension = Extension{ + Updated: "2013-01-20T00:00:00-00:00", + Name: "Neutron Service Type Management", + Links: []interface{}{}, + Namespace: "http://docs.openstack.org/ext/neutron/service-type/api/v1.0", + Alias: "service-type", + Description: "API for retrieving service providers for Neutron advanced services", +} + +// ExpectedExtensions is a slice containing the Extension that should be parsed from ListOutput. +var ExpectedExtensions = []Extension{ListedExtension} + +// SingleExtension is the Extension that should be parsed from GetOutput. +var SingleExtension = &Extension{ + Updated: "2013-02-03T10:00:00-00:00", + Name: "agent", + Links: []interface{}{}, + Namespace: "http://docs.openstack.org/ext/agent/api/v2.0", + Alias: "agent", + Description: "The agent management extension.", +} + +// HandleListExtensionsSuccessfully creates an HTTP handler at `/extensions` on the test handler +// mux that response with a list containing a single tenant. +func HandleListExtensionsSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/extensions", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetExtensionSuccessfully creates an HTTP handler at `/extensions/agent` that responds with +// a JSON payload corresponding to SingleExtension. +func HandleGetExtensionSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/extensions/agent", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, GetOutput) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go new file mode 100644 index 000000000..0b7108501 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go @@ -0,0 +1,21 @@ +package extensions + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Get retrieves information for a specific extension using its alias. +func Get(c *gophercloud.ServiceClient, alias string) GetResult { + var res GetResult + _, res.Err = c.Get(ExtensionURL(c, alias), &res.Body, nil) + return res +} + +// List returns a Pager which allows you to iterate over the full collection of extensions. +// It does not accept query parameters. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(c, ListExtensionURL(c), func(r pagination.PageResult) pagination.Page { + return ExtensionPage{pagination.SinglePageBase(r)} + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go new file mode 100644 index 000000000..777d083fa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go @@ -0,0 +1,65 @@ +package extensions + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// GetResult temporarily stores the result of a Get call. +// Use its Extract() method to interpret it as an Extension. +type GetResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult as an Extension. +func (r GetResult) Extract() (*Extension, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Extension *Extension `json:"extension"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Extension, err +} + +// Extension is a struct that represents an OpenStack extension. +type Extension struct { + Updated string `json:"updated" mapstructure:"updated"` + Name string `json:"name" mapstructure:"name"` + Links []interface{} `json:"links" mapstructure:"links"` + Namespace string `json:"namespace" mapstructure:"namespace"` + Alias string `json:"alias" mapstructure:"alias"` + Description string `json:"description" mapstructure:"description"` +} + +// ExtensionPage is the page returned by a pager when traversing over a collection of extensions. +type ExtensionPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an ExtensionPage struct is empty. +func (r ExtensionPage) IsEmpty() (bool, error) { + is, err := ExtractExtensions(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the +// elements into a slice of Extension structs. +// In other words, a generic collection is mapped into a relevant slice. +func ExtractExtensions(page pagination.Page) ([]Extension, error) { + var resp struct { + Extensions []Extension `mapstructure:"extensions"` + } + + err := mapstructure.Decode(page.(ExtensionPage).Body, &resp) + + return resp.Extensions, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go new file mode 100644 index 000000000..6460c66bc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go @@ -0,0 +1,13 @@ +package extensions + +import "github.com/rackspace/gophercloud" + +// ExtensionURL generates the URL for an extension resource by name. +func ExtensionURL(c *gophercloud.ServiceClient, name string) string { + return c.ServiceURL("extensions", name) +} + +// ListExtensionURL generates the URL for the extensions resource collection. +func ListExtensionURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("extensions") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go new file mode 100644 index 000000000..c8edee0e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go @@ -0,0 +1,111 @@ +package bootfromvolume + +import ( + "errors" + "strconv" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// SourceType represents the type of medium being used to create the volume. +type SourceType string + +const ( + Volume SourceType = "volume" + Snapshot SourceType = "snapshot" + Image SourceType = "image" +) + +// BlockDevice is a structure with options for booting a server instance +// from a volume. The volume may be created from an image, snapshot, or another +// volume. +type BlockDevice struct { + // BootIndex [optional] is the boot index. It defaults to 0. + BootIndex int `json:"boot_index"` + + // DeleteOnTermination [optional] specifies whether or not to delete the attached volume + // when the server is deleted. Defaults to `false`. + DeleteOnTermination bool `json:"delete_on_termination"` + + // DestinationType [optional] is the type that gets created. Possible values are "volume" + // and "local". + DestinationType string `json:"destination_type"` + + // SourceType [required] must be one of: "volume", "snapshot", "image". + SourceType SourceType `json:"source_type"` + + // UUID [required] is the unique identifier for the volume, snapshot, or image (see above) + UUID string `json:"uuid"` + + // VolumeSize [optional] is the size of the volume to create (in gigabytes). + VolumeSize int `json:"volume_size"` +} + +// CreateOptsExt is a structure that extends the server `CreateOpts` structure +// by allowing for a block device mapping. +type CreateOptsExt struct { + servers.CreateOptsBuilder + BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"` +} + +// ToServerCreateMap adds the block device mapping option to the base server +// creation options. +func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToServerCreateMap() + if err != nil { + return nil, err + } + + if len(opts.BlockDevice) == 0 { + return nil, errors.New("Required fields UUID and SourceType not set.") + } + + serverMap := base["server"].(map[string]interface{}) + + blockDevice := make([]map[string]interface{}, len(opts.BlockDevice)) + + for i, bd := range opts.BlockDevice { + if string(bd.SourceType) == "" { + return nil, errors.New("SourceType must be one of: volume, image, snapshot.") + } + + blockDevice[i] = make(map[string]interface{}) + + blockDevice[i]["source_type"] = bd.SourceType + blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex) + blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination) + blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize) + if bd.UUID != "" { + blockDevice[i]["uuid"] = bd.UUID + } + if bd.DestinationType != "" { + blockDevice[i]["destination_type"] = bd.DestinationType + } + + } + serverMap["block_device_mapping_v2"] = blockDevice + + return base, nil +} + +// Create requests the creation of a server from the given block device mapping. +func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult { + var res servers.CreateResult + + reqBody, err := opts.ToServerCreateMap() + if err != nil { + res.Err = err + return res + } + + // Delete imageName and flavorName that come from ToServerCreateMap(). + // As of Liberty, Boot From Volume is failing if they are passed. + delete(reqBody["server"].(map[string]interface{}), "imageName") + delete(reqBody["server"].(map[string]interface{}), "flavorName") + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go new file mode 100644 index 000000000..f60329f0f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go @@ -0,0 +1,10 @@ +package bootfromvolume + +import ( + os "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// CreateResult temporarily contains the response from a Create call. +type CreateResult struct { + os.CreateResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go new file mode 100644 index 000000000..0cffe25ff --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go @@ -0,0 +1,7 @@ +package bootfromvolume + +import "github.com/rackspace/gophercloud" + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("os-volumes_boot") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go new file mode 100644 index 000000000..2571a1a5a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go @@ -0,0 +1 @@ +package defsecrules diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go new file mode 100644 index 000000000..c28e492d3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go @@ -0,0 +1,108 @@ +package defsecrules + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +const rootPath = "/os-security-group-default-rules" + +func mockListRulesResponse(t *testing.T) { + th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group_default_rules": [ + { + "from_port": 80, + "id": "{ruleID}", + "ip_protocol": "TCP", + "ip_range": { + "cidr": "10.10.10.0/24" + }, + "to_port": 80 + } + ] +} + `) + }) +} + +func mockCreateRuleResponse(t *testing.T) { + th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "security_group_default_rule": { + "ip_protocol": "TCP", + "from_port": 80, + "to_port": 80, + "cidr": "10.10.12.0/24" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group_default_rule": { + "from_port": 80, + "id": "{ruleID}", + "ip_protocol": "TCP", + "ip_range": { + "cidr": "10.10.12.0/24" + }, + "to_port": 80 + } +} +`) + }) +} + +func mockGetRuleResponse(t *testing.T, ruleID string) { + url := rootPath + "/" + ruleID + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group_default_rule": { + "id": "{ruleID}", + "from_port": 80, + "to_port": 80, + "ip_protocol": "TCP", + "ip_range": { + "cidr": "10.10.12.0/24" + } + } +} + `) + }) +} + +func mockDeleteRuleResponse(t *testing.T, ruleID string) { + url := rootPath + "/" + ruleID + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go new file mode 100644 index 000000000..9f27ef172 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go @@ -0,0 +1,95 @@ +package defsecrules + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List will return a collection of default rules. +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return DefaultRulePage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, rootURL(client), createPage) +} + +// CreateOpts represents the configuration for adding a new default rule. +type CreateOpts struct { + // Required - the lower bound of the port range that will be opened. + FromPort int `json:"from_port"` + + // Required - the upper bound of the port range that will be opened. + ToPort int `json:"to_port"` + + // Required - the protocol type that will be allowed, e.g. TCP. + IPProtocol string `json:"ip_protocol"` + + // ONLY required if FromGroupID is blank. This represents the IP range that + // will be the source of network traffic to your security group. Use + // 0.0.0.0/0 to allow all IP addresses. + CIDR string `json:"cidr,omitempty"` +} + +// CreateOptsBuilder builds the create rule options into a serializable format. +type CreateOptsBuilder interface { + ToRuleCreateMap() (map[string]interface{}, error) +} + +// ToRuleCreateMap builds the create rule options into a serializable format. +func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) { + rule := make(map[string]interface{}) + + if opts.FromPort == 0 { + return rule, errors.New("A FromPort must be set") + } + if opts.ToPort == 0 { + return rule, errors.New("A ToPort must be set") + } + if opts.IPProtocol == "" { + return rule, errors.New("A IPProtocol must be set") + } + if opts.CIDR == "" { + return rule, errors.New("A CIDR must be set") + } + + rule["from_port"] = opts.FromPort + rule["to_port"] = opts.ToPort + rule["ip_protocol"] = opts.IPProtocol + rule["cidr"] = opts.CIDR + + return map[string]interface{}{"security_group_default_rule": rule}, nil +} + +// Create is the operation responsible for creating a new default rule. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var result CreateResult + + reqBody, err := opts.ToRuleCreateMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return result +} + +// Get will return details for a particular default rule. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var result GetResult + _, result.Err = client.Get(resourceURL(client, id), &result.Body, nil) + return result +} + +// Delete will permanently delete a default rule from the project. +func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { + var result gophercloud.ErrResult + _, result.Err = client.Delete(resourceURL(client, id), nil) + return result +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go new file mode 100644 index 000000000..e588d3e32 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go @@ -0,0 +1,69 @@ +package defsecrules + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups" + "github.com/rackspace/gophercloud/pagination" +) + +// DefaultRule represents a default rule - which is identical to a +// normal security rule. +type DefaultRule secgroups.Rule + +// DefaultRulePage is a single page of a DefaultRule collection. +type DefaultRulePage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a page of default rules contains any results. +func (page DefaultRulePage) IsEmpty() (bool, error) { + users, err := ExtractDefaultRules(page) + if err != nil { + return false, err + } + return len(users) == 0, nil +} + +// ExtractDefaultRules returns a slice of DefaultRules contained in a single +// page of results. +func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) { + casted := page.(DefaultRulePage).Body + var response struct { + Rules []DefaultRule `mapstructure:"security_group_default_rules"` + } + + err := mapstructure.WeakDecode(casted, &response) + + return response.Rules, err +} + +type commonResult struct { + gophercloud.Result +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// Extract will extract a DefaultRule struct from most responses. +func (r commonResult) Extract() (*DefaultRule, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Rule DefaultRule `mapstructure:"security_group_default_rule"` + } + + err := mapstructure.WeakDecode(r.Body, &response) + + return &response.Rule, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go new file mode 100644 index 000000000..cc928ab89 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go @@ -0,0 +1,13 @@ +package defsecrules + +import "github.com/rackspace/gophercloud" + +const rulepath = "os-security-group-default-rules" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rulepath, id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rulepath) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go new file mode 100644 index 000000000..10079097b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go @@ -0,0 +1,23 @@ +package extensions + +import ( + "github.com/rackspace/gophercloud" + common "github.com/rackspace/gophercloud/openstack/common/extensions" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractExtensions interprets a Page as a slice of Extensions. +func ExtractExtensions(page pagination.Page) ([]common.Extension, error) { + return common.ExtractExtensions(page) +} + +// Get retrieves information for a specific extension using its alias. +func Get(c *gophercloud.ServiceClient, alias string) common.GetResult { + return common.Get(c, alias) +} + +// List returns a Pager which allows you to iterate over the full collection of extensions. +// It does not accept query parameters. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return common.List(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go new file mode 100644 index 000000000..80785faca --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go @@ -0,0 +1,3 @@ +// Package diskconfig provides information and interaction with the Disk +// Config extension that works with the OpenStack Compute service. +package diskconfig diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go new file mode 100644 index 000000000..7407e0d17 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go @@ -0,0 +1,114 @@ +package diskconfig + +import ( + "errors" + + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// DiskConfig represents one of the two possible settings for the DiskConfig option when creating, +// rebuilding, or resizing servers: Auto or Manual. +type DiskConfig string + +const ( + // Auto builds a server with a single partition the size of the target flavor disk and + // automatically adjusts the filesystem to fit the entire partition. Auto may only be used with + // images and servers that use a single EXT3 partition. + Auto DiskConfig = "AUTO" + + // Manual builds a server using whatever partition scheme and filesystem are present in the source + // image. If the target flavor disk is larger, the remaining space is left unpartitioned. This + // enables images to have non-EXT3 filesystems, multiple partitions, and so on, and enables you + // to manage the disk configuration. It also results in slightly shorter boot times. + Manual DiskConfig = "MANUAL" +) + +// ErrInvalidDiskConfig is returned if an invalid string is specified for a DiskConfig option. +var ErrInvalidDiskConfig = errors.New("DiskConfig must be either diskconfig.Auto or diskconfig.Manual.") + +// Validate ensures that a DiskConfig contains an appropriate value. +func (config DiskConfig) validate() error { + switch config { + case Auto, Manual: + return nil + default: + return ErrInvalidDiskConfig + } +} + +// CreateOptsExt adds a DiskConfig option to the base CreateOpts. +type CreateOptsExt struct { + servers.CreateOptsBuilder + + // DiskConfig [optional] controls how the created server's disk is partitioned. + DiskConfig DiskConfig `json:"OS-DCF:diskConfig,omitempty"` +} + +// ToServerCreateMap adds the diskconfig option to the base server creation options. +func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToServerCreateMap() + if err != nil { + return nil, err + } + + if string(opts.DiskConfig) == "" { + return base, nil + } + + serverMap := base["server"].(map[string]interface{}) + serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig) + + return base, nil +} + +// RebuildOptsExt adds a DiskConfig option to the base RebuildOpts. +type RebuildOptsExt struct { + servers.RebuildOptsBuilder + + // DiskConfig [optional] controls how the rebuilt server's disk is partitioned. + DiskConfig DiskConfig +} + +// ToServerRebuildMap adds the diskconfig option to the base server rebuild options. +func (opts RebuildOptsExt) ToServerRebuildMap() (map[string]interface{}, error) { + err := opts.DiskConfig.validate() + if err != nil { + return nil, err + } + + base, err := opts.RebuildOptsBuilder.ToServerRebuildMap() + if err != nil { + return nil, err + } + + serverMap := base["rebuild"].(map[string]interface{}) + serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig) + + return base, nil +} + +// ResizeOptsExt adds a DiskConfig option to the base server resize options. +type ResizeOptsExt struct { + servers.ResizeOptsBuilder + + // DiskConfig [optional] controls how the resized server's disk is partitioned. + DiskConfig DiskConfig +} + +// ToServerResizeMap adds the diskconfig option to the base server creation options. +func (opts ResizeOptsExt) ToServerResizeMap() (map[string]interface{}, error) { + err := opts.DiskConfig.validate() + if err != nil { + return nil, err + } + + base, err := opts.ResizeOptsBuilder.ToServerResizeMap() + if err != nil { + return nil, err + } + + serverMap := base["resize"].(map[string]interface{}) + serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig) + + return base, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go new file mode 100644 index 000000000..10ec2dafc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go @@ -0,0 +1,60 @@ +package diskconfig + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + "github.com/rackspace/gophercloud/pagination" +) + +func commonExtract(result gophercloud.Result) (*DiskConfig, error) { + var resp struct { + Server struct { + DiskConfig string `mapstructure:"OS-DCF:diskConfig"` + } `mapstructure:"server"` + } + + err := mapstructure.Decode(result.Body, &resp) + if err != nil { + return nil, err + } + + config := DiskConfig(resp.Server.DiskConfig) + return &config, nil +} + +// ExtractGet returns the disk configuration from a servers.Get call. +func ExtractGet(result servers.GetResult) (*DiskConfig, error) { + return commonExtract(result.Result) +} + +// ExtractUpdate returns the disk configuration from a servers.Update call. +func ExtractUpdate(result servers.UpdateResult) (*DiskConfig, error) { + return commonExtract(result.Result) +} + +// ExtractRebuild returns the disk configuration from a servers.Rebuild call. +func ExtractRebuild(result servers.RebuildResult) (*DiskConfig, error) { + return commonExtract(result.Result) +} + +// ExtractDiskConfig returns the DiskConfig setting for a specific server acquired from an +// servers.ExtractServers call, while iterating through a Pager. +func ExtractDiskConfig(page pagination.Page, index int) (*DiskConfig, error) { + casted := page.(servers.ServerPage).Body + + type server struct { + DiskConfig string `mapstructure:"OS-DCF:diskConfig"` + } + var response struct { + Servers []server `mapstructure:"servers"` + } + + err := mapstructure.Decode(casted, &response) + if err != nil { + return nil, err + } + + config := DiskConfig(response.Servers[index].DiskConfig) + return &config, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go new file mode 100644 index 000000000..2b447da1d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go @@ -0,0 +1,3 @@ +// Package extensions provides information and interaction with the +// different extensions available for the OpenStack Compute service. +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go new file mode 100644 index 000000000..f74f58ce8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go @@ -0,0 +1,3 @@ +// Package floatingip provides the ability to manage floating ips through +// nova-network +package floatingip diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go new file mode 100644 index 000000000..e47fa4ccd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go @@ -0,0 +1,193 @@ +// +build fixtures + +package floatingip + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "floating_ips": [ + { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + }, + { + "fixed_ip": "166.78.185.201", + "id": 2, + "instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "ip": "10.10.10.2", + "pool": "nova" + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "floating_ip": { + "fixed_ip": "166.78.185.201", + "id": 2, + "instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "ip": "10.10.10.2", + "pool": "nova" + } +} +` + +// CreateOutput is a sample response to a Post call +const CreateOutput = ` +{ + "floating_ip": { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + } +} +` + +// FirstFloatingIP is the first result in ListOutput. +var FirstFloatingIP = FloatingIP{ + ID: "1", + IP: "10.10.10.1", + Pool: "nova", +} + +// SecondFloatingIP is the first result in ListOutput. +var SecondFloatingIP = FloatingIP{ + FixedIP: "166.78.185.201", + ID: "2", + InstanceID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + IP: "10.10.10.2", + Pool: "nova", +} + +// ExpectedFloatingIPsSlice is the slice of results that should be parsed +// from ListOutput, in the expected order. +var ExpectedFloatingIPsSlice = []FloatingIP{FirstFloatingIP, SecondFloatingIP} + +// CreatedFloatingIP is the parsed result from CreateOutput. +var CreatedFloatingIP = FloatingIP{ + ID: "1", + IP: "10.10.10.1", + Pool: "nova", +} + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request +// for an existing floating ip +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-floating-ips/2", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} + +// HandleCreateSuccessfully configures the test server to respond to a Create request +// for a new floating ip +func HandleCreateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "pool": "nova" +} +`) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, CreateOutput) + }) +} + +// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a +// an existing floating ip +func HandleDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-floating-ips/1", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleAssociateSuccessfully configures the test server to respond to a Post request +// to associate an allocated floating IP +func HandleAssociateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "addFloatingIp": { + "address": "10.10.10.2" + } +} +`) + + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleFixedAssociateSucessfully configures the test server to respond to a Post request +// to associate an allocated floating IP with a specific fixed IP address +func HandleAssociateFixedSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "addFloatingIp": { + "address": "10.10.10.2", + "fixed_address": "166.78.185.201" + } +} +`) + + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleDisassociateSuccessfully configures the test server to respond to a Post request +// to disassociate an allocated floating IP +func HandleDisassociateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "removeFloatingIp": { + "address": "10.10.10.2" + } +} +`) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go new file mode 100644 index 000000000..820646297 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go @@ -0,0 +1,171 @@ +package floatingip + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of FloatingIPs. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { + return FloatingIPsPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the +// CreateOpts struct in this package does. +type CreateOptsBuilder interface { + ToFloatingIPCreateMap() (map[string]interface{}, error) +} + +// CreateOpts specifies a Floating IP allocation request +type CreateOpts struct { + // Pool is the pool of floating IPs to allocate one from + Pool string +} + +// AssociateOpts specifies the required information to associate or disassociate a floating IP to an instance +type AssociateOpts struct { + // ServerID is the UUID of the server + ServerID string + + // FixedIP is an optional fixed IP address of the server + FixedIP string + + // FloatingIP is the floating IP to associate with an instance + FloatingIP string +} + +// ToFloatingIPCreateMap constructs a request body from CreateOpts. +func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) { + if opts.Pool == "" { + return nil, errors.New("Missing field required for floating IP creation: Pool") + } + + return map[string]interface{}{"pool": opts.Pool}, nil +} + +// ToAssociateMap constructs a request body from AssociateOpts. +func (opts AssociateOpts) ToAssociateMap() (map[string]interface{}, error) { + if opts.ServerID == "" { + return nil, errors.New("Required field missing for floating IP association: ServerID") + } + + if opts.FloatingIP == "" { + return nil, errors.New("Required field missing for floating IP association: FloatingIP") + } + + associateInfo := map[string]interface{}{ + "serverId": opts.ServerID, + "floatingIp": opts.FloatingIP, + "fixedIp": opts.FixedIP, + } + + return associateInfo, nil + +} + +// Create requests the creation of a new floating IP +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToFloatingIPCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Get returns data about a previously created FloatingIP. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} + +// Delete requests the deletion of a previous allocated FloatingIP. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} + +// association / disassociation + +// Associate pairs an allocated floating IP with an instance +// Deprecated. Use AssociateInstance. +func Associate(client *gophercloud.ServiceClient, serverId, fip string) AssociateResult { + var res AssociateResult + + addFloatingIp := make(map[string]interface{}) + addFloatingIp["address"] = fip + reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp} + + _, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil) + return res +} + +// AssociateInstance pairs an allocated floating IP with an instance. +func AssociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) AssociateResult { + var res AssociateResult + + associateInfo, err := opts.ToAssociateMap() + if err != nil { + res.Err = err + return res + } + + addFloatingIp := make(map[string]interface{}) + addFloatingIp["address"] = associateInfo["floatingIp"].(string) + + // fixedIp is not required + if associateInfo["fixedIp"] != "" { + addFloatingIp["fixed_address"] = associateInfo["fixedIp"].(string) + } + + serverId := associateInfo["serverId"].(string) + + reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp} + _, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil) + return res +} + +// Disassociate decouples an allocated floating IP from an instance +// Deprecated. Use DisassociateInstance. +func Disassociate(client *gophercloud.ServiceClient, serverId, fip string) DisassociateResult { + var res DisassociateResult + + removeFloatingIp := make(map[string]interface{}) + removeFloatingIp["address"] = fip + reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp} + + _, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil) + return res +} + +// DisassociateInstance decouples an allocated floating IP from an instance +func DisassociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) DisassociateResult { + var res DisassociateResult + + associateInfo, err := opts.ToAssociateMap() + if err != nil { + res.Err = err + return res + } + + removeFloatingIp := make(map[string]interface{}) + removeFloatingIp["address"] = associateInfo["floatingIp"].(string) + reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp} + + serverId := associateInfo["serverId"].(string) + + _, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go new file mode 100644 index 000000000..be77fa179 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go @@ -0,0 +1,99 @@ +package floatingip + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// A FloatingIP is an IP that can be associated with an instance +type FloatingIP struct { + // ID is a unique ID of the Floating IP + ID string `mapstructure:"id"` + + // FixedIP is the IP of the instance related to the Floating IP + FixedIP string `mapstructure:"fixed_ip,omitempty"` + + // InstanceID is the ID of the instance that is using the Floating IP + InstanceID string `mapstructure:"instance_id"` + + // IP is the actual Floating IP + IP string `mapstructure:"ip"` + + // Pool is the pool of floating IPs that this floating IP belongs to + Pool string `mapstructure:"pool"` +} + +// FloatingIPsPage stores a single, only page of FloatingIPs +// results from a List call. +type FloatingIPsPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a FloatingIPsPage is empty. +func (page FloatingIPsPage) IsEmpty() (bool, error) { + va, err := ExtractFloatingIPs(page) + return len(va) == 0, err +} + +// ExtractFloatingIPs interprets a page of results as a slice of +// FloatingIPs. +func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) { + casted := page.(FloatingIPsPage).Body + var response struct { + FloatingIPs []FloatingIP `mapstructure:"floating_ips"` + } + + err := mapstructure.WeakDecode(casted, &response) + + return response.FloatingIPs, err +} + +type FloatingIPResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any FloatingIP resource +// response as a FloatingIP struct. +func (r FloatingIPResult) Extract() (*FloatingIP, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + FloatingIP *FloatingIP `json:"floating_ip" mapstructure:"floating_ip"` + } + + err := mapstructure.WeakDecode(r.Body, &res) + return res.FloatingIP, err +} + +// CreateResult is the response from a Create operation. Call its Extract method to interpret it +// as a FloatingIP. +type CreateResult struct { + FloatingIPResult +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a FloatingIP. +type GetResult struct { + FloatingIPResult +} + +// DeleteResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} + +// AssociateResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type AssociateResult struct { + gophercloud.ErrResult +} + +// DisassociateResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type DisassociateResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go new file mode 100644 index 000000000..54198f852 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go @@ -0,0 +1,37 @@ +package floatingip + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-floating-ips" + +func resourceURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func listURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} + +func serverURL(c *gophercloud.ServiceClient, serverId string) string { + return c.ServiceURL("servers/" + serverId + "/action") +} + +func associateURL(c *gophercloud.ServiceClient, serverId string) string { + return serverURL(c, serverId) +} + +func disassociateURL(c *gophercloud.ServiceClient, serverId string) string { + return serverURL(c, serverId) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go new file mode 100644 index 000000000..856f41bac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go @@ -0,0 +1,3 @@ +// Package keypairs provides information and interaction with the Keypairs +// extension for the OpenStack Compute service. +package keypairs diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go new file mode 100644 index 000000000..d10af99d0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go @@ -0,0 +1,171 @@ +// +build fixtures + +package keypairs + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "keypairs": [ + { + "keypair": { + "fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a", + "name": "firstkey", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n" + } + }, + { + "keypair": { + "fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", + "name": "secondkey", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n" + } + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "keypair": { + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n", + "name": "firstkey", + "fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a" + } +} +` + +// CreateOutput is a sample response to a Create call. +const CreateOutput = ` +{ + "keypair": { + "fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", + "name": "createdkey", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", + "user_id": "fake" + } +} +` + +// ImportOutput is a sample response to a Create call that provides its own public key. +const ImportOutput = ` +{ + "keypair": { + "fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", + "name": "importedkey", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova", + "user_id": "fake" + } +} +` + +// FirstKeyPair is the first result in ListOutput. +var FirstKeyPair = KeyPair{ + Name: "firstkey", + Fingerprint: "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a", + PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n", +} + +// SecondKeyPair is the second result in ListOutput. +var SecondKeyPair = KeyPair{ + Name: "secondkey", + Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", + PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", +} + +// ExpectedKeyPairSlice is the slice of results that should be parsed from ListOutput, in the expected +// order. +var ExpectedKeyPairSlice = []KeyPair{FirstKeyPair, SecondKeyPair} + +// CreatedKeyPair is the parsed result from CreatedOutput. +var CreatedKeyPair = KeyPair{ + Name: "createdkey", + Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8", + PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n", + PrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n", + UserID: "fake", +} + +// ImportedKeyPair is the parsed result from ImportOutput. +var ImportedKeyPair = KeyPair{ + Name: "importedkey", + Fingerprint: "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c", + PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova", + UserID: "fake", +} + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request for "firstkey". +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-keypairs/firstkey", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} + +// HandleCreateSuccessfully configures the test server to respond to a Create request for a new +// keypair called "createdkey". +func HandleCreateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ "keypair": { "name": "createdkey" } }`) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, CreateOutput) + }) +} + +// HandleImportSuccessfully configures the test server to respond to an Import request for an +// existing keypair called "importedkey". +func HandleImportSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` + { + "keypair": { + "name": "importedkey", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova" + } + } + `) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ImportOutput) + }) +} + +// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a +// keypair called "deletedkey". +func HandleDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-keypairs/deletedkey", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go new file mode 100644 index 000000000..c56ee67ea --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go @@ -0,0 +1,102 @@ +package keypairs + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsExt adds a KeyPair option to the base CreateOpts. +type CreateOptsExt struct { + servers.CreateOptsBuilder + KeyName string `json:"key_name,omitempty"` +} + +// ToServerCreateMap adds the key_name and, optionally, key_data options to +// the base server creation options. +func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToServerCreateMap() + if err != nil { + return nil, err + } + + if opts.KeyName == "" { + return base, nil + } + + serverMap := base["server"].(map[string]interface{}) + serverMap["key_name"] = opts.KeyName + + return base, nil +} + +// List returns a Pager that allows you to iterate over a collection of KeyPairs. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { + return KeyPairPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the +// CreateOpts struct in this package does. +type CreateOptsBuilder interface { + ToKeyPairCreateMap() (map[string]interface{}, error) +} + +// CreateOpts specifies keypair creation or import parameters. +type CreateOpts struct { + // Name [required] is a friendly name to refer to this KeyPair in other services. + Name string + + // PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key + // will be imported and no new key will be created. + PublicKey string +} + +// ToKeyPairCreateMap constructs a request body from CreateOpts. +func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) { + if opts.Name == "" { + return nil, errors.New("Missing field required for keypair creation: Name") + } + + keypair := make(map[string]interface{}) + keypair["name"] = opts.Name + if opts.PublicKey != "" { + keypair["public_key"] = opts.PublicKey + } + + return map[string]interface{}{"keypair": keypair}, nil +} + +// Create requests the creation of a new keypair on the server, or to import a pre-existing +// keypair. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToKeyPairCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Get returns public data about a previously uploaded KeyPair. +func Get(client *gophercloud.ServiceClient, name string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, name), &res.Body, nil) + return res +} + +// Delete requests the deletion of a previous stored KeyPair from the server. +func Delete(client *gophercloud.ServiceClient, name string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, name), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go new file mode 100644 index 000000000..f1a0d8e11 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go @@ -0,0 +1,94 @@ +package keypairs + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// KeyPair is an SSH key known to the OpenStack cluster that is available to be injected into +// servers. +type KeyPair struct { + // Name is used to refer to this keypair from other services within this region. + Name string `mapstructure:"name"` + + // Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer + // public key. + Fingerprint string `mapstructure:"fingerprint"` + + // PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..." + PublicKey string `mapstructure:"public_key"` + + // PrivateKey is the private key from this pair, in PEM format. + // "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just + // returned from a Create call + PrivateKey string `mapstructure:"private_key"` + + // UserID is the user who owns this keypair. + UserID string `mapstructure:"user_id"` +} + +// KeyPairPage stores a single, only page of KeyPair results from a List call. +type KeyPairPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a KeyPairPage is empty. +func (page KeyPairPage) IsEmpty() (bool, error) { + ks, err := ExtractKeyPairs(page) + return len(ks) == 0, err +} + +// ExtractKeyPairs interprets a page of results as a slice of KeyPairs. +func ExtractKeyPairs(page pagination.Page) ([]KeyPair, error) { + type pair struct { + KeyPair KeyPair `mapstructure:"keypair"` + } + + var resp struct { + KeyPairs []pair `mapstructure:"keypairs"` + } + + err := mapstructure.Decode(page.(KeyPairPage).Body, &resp) + results := make([]KeyPair, len(resp.KeyPairs)) + for i, pair := range resp.KeyPairs { + results[i] = pair.KeyPair + } + return results, err +} + +type keyPairResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct. +func (r keyPairResult) Extract() (*KeyPair, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + KeyPair *KeyPair `json:"keypair" mapstructure:"keypair"` + } + + err := mapstructure.Decode(r.Body, &res) + return res.KeyPair, err +} + +// CreateResult is the response from a Create operation. Call its Extract method to interpret it +// as a KeyPair. +type CreateResult struct { + keyPairResult +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a KeyPair. +type GetResult struct { + keyPairResult +} + +// DeleteResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go new file mode 100644 index 000000000..702f5329e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go @@ -0,0 +1,25 @@ +package keypairs + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-keypairs" + +func resourceURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func listURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func getURL(c *gophercloud.ServiceClient, name string) string { + return c.ServiceURL(resourcePath, name) +} + +func deleteURL(c *gophercloud.ServiceClient, name string) string { + return getURL(c, name) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/doc.go new file mode 100644 index 000000000..fafe4a04d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/doc.go @@ -0,0 +1,2 @@ +// Package network provides the ability to manage nova-networks +package networks diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go new file mode 100644 index 000000000..12b94859b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/fixtures.go @@ -0,0 +1,209 @@ +// +build fixtures + +package networks + +import ( + "fmt" + "net/http" + "testing" + "time" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "networks": [ + { + "bridge": "br100", + "bridge_interface": "eth0", + "broadcast": "10.0.0.7", + "cidr": "10.0.0.0/29", + "cidr_v6": null, + "created_at": "2011-08-15 06:19:19.387525", + "deleted": false, + "deleted_at": null, + "dhcp_start": "10.0.0.3", + "dns1": null, + "dns2": null, + "gateway": "10.0.0.1", + "gateway_v6": null, + "host": "nsokolov-desktop", + "id": "20c8acc0-f747-4d71-a389-46d078ebf047", + "injected": false, + "label": "mynet_0", + "multi_host": false, + "netmask": "255.255.255.248", + "netmask_v6": null, + "priority": null, + "project_id": "1234", + "rxtx_base": null, + "updated_at": "2011-08-16 09:26:13.048257", + "vlan": 100, + "vpn_private_address": "10.0.0.2", + "vpn_public_address": "127.0.0.1", + "vpn_public_port": 1000 + }, + { + "bridge": "br101", + "bridge_interface": "eth0", + "broadcast": "10.0.0.15", + "cidr": "10.0.0.10/29", + "cidr_v6": null, + "created_at": "2011-08-15 06:19:19.885495", + "deleted": false, + "deleted_at": null, + "dhcp_start": "10.0.0.11", + "dns1": null, + "dns2": null, + "gateway": "10.0.0.9", + "gateway_v6": null, + "host": null, + "id": "20c8acc0-f747-4d71-a389-46d078ebf000", + "injected": false, + "label": "mynet_1", + "multi_host": false, + "netmask": "255.255.255.248", + "netmask_v6": null, + "priority": null, + "project_id": null, + "rxtx_base": null, + "updated_at": null, + "vlan": 101, + "vpn_private_address": "10.0.0.10", + "vpn_public_address": null, + "vpn_public_port": 1001 + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "network": { + "bridge": "br101", + "bridge_interface": "eth0", + "broadcast": "10.0.0.15", + "cidr": "10.0.0.10/29", + "cidr_v6": null, + "created_at": "2011-08-15 06:19:19.885495", + "deleted": false, + "deleted_at": null, + "dhcp_start": "10.0.0.11", + "dns1": null, + "dns2": null, + "gateway": "10.0.0.9", + "gateway_v6": null, + "host": null, + "id": "20c8acc0-f747-4d71-a389-46d078ebf000", + "injected": false, + "label": "mynet_1", + "multi_host": false, + "netmask": "255.255.255.248", + "netmask_v6": null, + "priority": null, + "project_id": null, + "rxtx_base": null, + "updated_at": null, + "vlan": 101, + "vpn_private_address": "10.0.0.10", + "vpn_public_address": null, + "vpn_public_port": 1001 + } +} +` + +// FirstNetwork is the first result in ListOutput. +var nilTime time.Time +var FirstNetwork = Network{ + Bridge: "br100", + BridgeInterface: "eth0", + Broadcast: "10.0.0.7", + CIDR: "10.0.0.0/29", + CIDRv6: "", + CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC), + Deleted: false, + DeletedAt: nilTime, + DHCPStart: "10.0.0.3", + DNS1: "", + DNS2: "", + Gateway: "10.0.0.1", + Gatewayv6: "", + Host: "nsokolov-desktop", + ID: "20c8acc0-f747-4d71-a389-46d078ebf047", + Injected: false, + Label: "mynet_0", + MultiHost: false, + Netmask: "255.255.255.248", + Netmaskv6: "", + Priority: 0, + ProjectID: "1234", + RXTXBase: 0, + UpdatedAt: time.Date(2011, 8, 16, 9, 26, 13, 48257000, time.UTC), + VLAN: 100, + VPNPrivateAddress: "10.0.0.2", + VPNPublicAddress: "127.0.0.1", + VPNPublicPort: 1000, +} + +// SecondNetwork is the second result in ListOutput. +var SecondNetwork = Network{ + Bridge: "br101", + BridgeInterface: "eth0", + Broadcast: "10.0.0.15", + CIDR: "10.0.0.10/29", + CIDRv6: "", + CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 885495000, time.UTC), + Deleted: false, + DeletedAt: nilTime, + DHCPStart: "10.0.0.11", + DNS1: "", + DNS2: "", + Gateway: "10.0.0.9", + Gatewayv6: "", + Host: "", + ID: "20c8acc0-f747-4d71-a389-46d078ebf000", + Injected: false, + Label: "mynet_1", + MultiHost: false, + Netmask: "255.255.255.248", + Netmaskv6: "", + Priority: 0, + ProjectID: "", + RXTXBase: 0, + UpdatedAt: nilTime, + VLAN: 101, + VPNPrivateAddress: "10.0.0.10", + VPNPublicAddress: "", + VPNPublicPort: 1001, +} + +// ExpectedNetworkSlice is the slice of results that should be parsed +// from ListOutput, in the expected order. +var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork} + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-networks", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request +// for an existing network. +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/requests.go new file mode 100644 index 000000000..eb203878b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/requests.go @@ -0,0 +1,22 @@ +package networks + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of Network. +func List(client *gophercloud.ServiceClient) pagination.Pager { + url := listURL(client) + createPage := func(r pagination.PageResult) pagination.Page { + return NetworkPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, url, createPage) +} + +// Get returns data about a previously created Network. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go new file mode 100644 index 000000000..55b361d7f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/results.go @@ -0,0 +1,222 @@ +package networks + +import ( + "fmt" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// A Network represents a nova-network that an instance communicates on +type Network struct { + // The Bridge that VIFs on this network are connected to + Bridge string `mapstructure:"bridge"` + + // BridgeInterface is what interface is connected to the Bridge + BridgeInterface string `mapstructure:"bridge_interface"` + + // The Broadcast address of the network. + Broadcast string `mapstructure:"broadcast"` + + // CIDR is the IPv4 subnet. + CIDR string `mapstructure:"cidr"` + + // CIDRv6 is the IPv6 subnet. + CIDRv6 string `mapstructure:"cidr_v6"` + + // CreatedAt is when the network was created.. + CreatedAt time.Time `mapstructure:"-"` + + // Deleted shows if the network has been deleted. + Deleted bool `mapstructure:"deleted"` + + // DeletedAt is the time when the network was deleted. + DeletedAt time.Time `mapstructure:"-"` + + // DHCPStart is the start of the DHCP address range. + DHCPStart string `mapstructure:"dhcp_start"` + + // DNS1 is the first DNS server to use through DHCP. + DNS1 string `mapstructure:"dns_1"` + + // DNS2 is the first DNS server to use through DHCP. + DNS2 string `mapstructure:"dns_2"` + + // Gateway is the network gateway. + Gateway string `mapstructure:"gateway"` + + // Gatewayv6 is the IPv6 network gateway. + Gatewayv6 string `mapstructure:"gateway_v6"` + + // Host is the host that the network service is running on. + Host string `mapstructure:"host"` + + // ID is the UUID of the network. + ID string `mapstructure:"id"` + + // Injected determines if network information is injected into the host. + Injected bool `mapstructure:"injected"` + + // Label is the common name that the network has.. + Label string `mapstructure:"label"` + + // MultiHost is if multi-host networking is enablec.. + MultiHost bool `mapstructure:"multi_host"` + + // Netmask is the network netmask. + Netmask string `mapstructure:"netmask"` + + // Netmaskv6 is the IPv6 netmask. + Netmaskv6 string `mapstructure:"netmask_v6"` + + // Priority is the network interface priority. + Priority int `mapstructure:"priority"` + + // ProjectID is the project associated with this network. + ProjectID string `mapstructure:"project_id"` + + // RXTXBase configures bandwidth entitlement. + RXTXBase int `mapstructure:"rxtx_base"` + + // UpdatedAt is the time when the network was last updated. + UpdatedAt time.Time `mapstructure:"-"` + + // VLAN is the vlan this network runs on. + VLAN int `mapstructure:"vlan"` + + // VPNPrivateAddress is the private address of the CloudPipe VPN. + VPNPrivateAddress string `mapstructure:"vpn_private_address"` + + // VPNPublicAddress is the public address of the CloudPipe VPN. + VPNPublicAddress string `mapstructure:"vpn_public_address"` + + // VPNPublicPort is the port of the CloudPipe VPN. + VPNPublicPort int `mapstructure:"vpn_public_port"` +} + +// NetworkPage stores a single, only page of Networks +// results from a List call. +type NetworkPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a NetworkPage is empty. +func (page NetworkPage) IsEmpty() (bool, error) { + va, err := ExtractNetworks(page) + return len(va) == 0, err +} + +// ExtractNetworks interprets a page of results as a slice of Networks +func ExtractNetworks(page pagination.Page) ([]Network, error) { + var res struct { + Networks []Network `mapstructure:"networks"` + } + + err := mapstructure.Decode(page.(NetworkPage).Body, &res) + + var rawNetworks []interface{} + body := page.(NetworkPage).Body + switch body.(type) { + case map[string]interface{}: + rawNetworks = body.(map[string]interface{})["networks"].([]interface{}) + case map[string][]interface{}: + rawNetworks = body.(map[string][]interface{})["networks"] + default: + return res.Networks, fmt.Errorf("Unknown type") + } + + for i := range rawNetworks { + thisNetwork := rawNetworks[i].(map[string]interface{}) + if t, ok := thisNetwork["created_at"].(string); ok && t != "" { + createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Networks, err + } + res.Networks[i].CreatedAt = createdAt + } + + if t, ok := thisNetwork["updated_at"].(string); ok && t != "" { + updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Networks, err + } + res.Networks[i].UpdatedAt = updatedAt + } + + if t, ok := thisNetwork["deleted_at"].(string); ok && t != "" { + deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Networks, err + } + res.Networks[i].DeletedAt = deletedAt + } + } + + return res.Networks, err +} + +type NetworkResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any Network resource +// response as a Network struct. +func (r NetworkResult) Extract() (*Network, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *Network `json:"network" mapstructure:"network"` + } + + config := &mapstructure.DecoderConfig{ + Result: &res, + WeaklyTypedInput: true, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + + if err := decoder.Decode(r.Body); err != nil { + return nil, err + } + + b := r.Body.(map[string]interface{})["network"].(map[string]interface{}) + + if t, ok := b["created_at"].(string); ok && t != "" { + createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Network, err + } + res.Network.CreatedAt = createdAt + } + + if t, ok := b["updated_at"].(string); ok && t != "" { + updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Network, err + } + res.Network.UpdatedAt = updatedAt + } + + if t, ok := b["deleted_at"].(string); ok && t != "" { + deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) + if err != nil { + return res.Network, err + } + res.Network.DeletedAt = deletedAt + } + + return res.Network, err + +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a Network. +type GetResult struct { + NetworkResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go new file mode 100644 index 000000000..69664620a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks/urls.go @@ -0,0 +1,17 @@ +package networks + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-networks" + +func resourceURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func listURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go new file mode 100644 index 000000000..0bd45661b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go @@ -0,0 +1,3 @@ +// Package schedulerhints enables instances to provide the OpenStack scheduler +// hints about where they should be placed in the cloud. +package schedulerhints diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go new file mode 100644 index 000000000..567eef41a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go @@ -0,0 +1,134 @@ +package schedulerhints + +import ( + "fmt" + "net" + "regexp" + "strings" + + "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// SchedulerHints represents a set of scheduling hints that are passed to the +// OpenStack scheduler +type SchedulerHints struct { + // Group specifies a Server Group to place the instance in. + Group string + + // DifferentHost will place the instance on a compute node that does not + // host the given instances. + DifferentHost []string + + // SameHost will place the instance on a compute node that hosts the given + // instances. + SameHost []string + + // Query is a conditional statement that results in compute nodes able to + // host the instance. + Query []interface{} + + // TargetCell specifies a cell name where the instance will be placed. + TargetCell string + + // BuildNearHostIP specifies a subnet of compute nodes to host the instance. + BuildNearHostIP string +} + +// SchedulerHintsBuilder builds the scheduler hints into a serializable format. +type SchedulerHintsBuilder interface { + ToServerSchedulerHintsMap() (map[string]interface{}, error) +} + +// ToServerSchedulerHintsMap builds the scheduler hints into a serializable format. +func (opts SchedulerHints) ToServerSchedulerHintsMap() (map[string]interface{}, error) { + sh := make(map[string]interface{}) + + uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$") + + if opts.Group != "" { + if !uuidRegex.MatchString(opts.Group) { + return nil, fmt.Errorf("Group must be a UUID") + } + sh["group"] = opts.Group + } + + if len(opts.DifferentHost) > 0 { + for _, diffHost := range opts.DifferentHost { + if !uuidRegex.MatchString(diffHost) { + return nil, fmt.Errorf("The hosts in DifferentHost must be in UUID format.") + } + } + sh["different_host"] = opts.DifferentHost + } + + if len(opts.SameHost) > 0 { + for _, sameHost := range opts.SameHost { + if !uuidRegex.MatchString(sameHost) { + return nil, fmt.Errorf("The hosts in SameHost must be in UUID format.") + } + } + sh["same_host"] = opts.SameHost + } + + /* Query can be something simple like: + [">=", "$free_ram_mb", 1024] + + Or more complex like: + ['and', + ['>=', '$free_ram_mb', 1024], + ['>=', '$free_disk_mb', 200 * 1024] + ] + + Because of the possible complexity, just make sure the length is a minimum of 3. + */ + if len(opts.Query) > 0 { + if len(opts.Query) < 3 { + return nil, fmt.Errorf("Query must be a conditional statement in the format of [op,variable,value]") + } + sh["query"] = opts.Query + } + + if opts.TargetCell != "" { + sh["target_cell"] = opts.TargetCell + } + + if opts.BuildNearHostIP != "" { + if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil { + return nil, fmt.Errorf("BuildNearHostIP must be a valid subnet in the form 192.168.1.1/24") + } + ipParts := strings.Split(opts.BuildNearHostIP, "/") + sh["build_near_host_ip"] = ipParts[0] + sh["cidr"] = "/" + ipParts[1] + } + + return sh, nil +} + +// CreateOptsExt adds a SchedulerHints option to the base CreateOpts. +type CreateOptsExt struct { + servers.CreateOptsBuilder + + // SchedulerHints provides a set of hints to the scheduler. + SchedulerHints SchedulerHintsBuilder +} + +// ToServerCreateMap adds the SchedulerHints option to the base server creation options. +func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToServerCreateMap() + if err != nil { + return nil, err + } + + schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsMap() + if err != nil { + return nil, err + } + + if len(schedulerHints) == 0 { + return base, nil + } + + base["os:scheduler_hints"] = schedulerHints + + return base, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go new file mode 100644 index 000000000..702f32c98 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go @@ -0,0 +1 @@ +package secgroups diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go new file mode 100644 index 000000000..8c42e48e4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go @@ -0,0 +1,267 @@ +package secgroups + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +const rootPath = "/os-security-groups" + +const listGroupsJSON = ` +{ + "security_groups": [ + { + "description": "default", + "id": "{groupID}", + "name": "default", + "rules": [], + "tenant_id": "openstack" + } + ] +} +` + +func mockListGroupsResponse(t *testing.T) { + th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, listGroupsJSON) + }) +} + +func mockListGroupsByServerResponse(t *testing.T, serverID string) { + url := fmt.Sprintf("/servers/%s%s", serverID, rootPath) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, listGroupsJSON) + }) +} + +func mockCreateGroupResponse(t *testing.T) { + th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "security_group": { + "name": "test", + "description": "something" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group": { + "description": "something", + "id": "{groupID}", + "name": "test", + "rules": [], + "tenant_id": "openstack" + } +} +`) + }) +} + +func mockUpdateGroupResponse(t *testing.T, groupID string) { + url := fmt.Sprintf("%s/%s", rootPath, groupID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "security_group": { + "name": "new_name", + "description": "new_desc" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group": { + "description": "something", + "id": "{groupID}", + "name": "new_name", + "rules": [], + "tenant_id": "openstack" + } +} +`) + }) +} + +func mockGetGroupsResponse(t *testing.T, groupID string) { + url := fmt.Sprintf("%s/%s", rootPath, groupID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group": { + "description": "default", + "id": "{groupID}", + "name": "default", + "rules": [ + { + "from_port": 80, + "group": { + "tenant_id": "openstack", + "name": "default" + }, + "ip_protocol": "TCP", + "to_port": 85, + "parent_group_id": "{groupID}", + "ip_range": { + "cidr": "0.0.0.0" + }, + "id": "{ruleID}" + } + ], + "tenant_id": "openstack" + } +} + `) + }) +} + +func mockGetNumericIDGroupResponse(t *testing.T, groupID int) { + url := fmt.Sprintf("%s/%d", rootPath, groupID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group": { + "id": 12345 + } +} + `) + }) +} + +func mockDeleteGroupResponse(t *testing.T, groupID string) { + url := fmt.Sprintf("%s/%s", rootPath, groupID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockAddRuleResponse(t *testing.T) { + th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "security_group_rule": { + "from_port": 22, + "ip_protocol": "TCP", + "to_port": 22, + "parent_group_id": "{groupID}", + "cidr": "0.0.0.0/0" + } +} `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "security_group_rule": { + "from_port": 22, + "group": {}, + "ip_protocol": "TCP", + "to_port": 22, + "parent_group_id": "{groupID}", + "ip_range": { + "cidr": "0.0.0.0/0" + }, + "id": "{ruleID}" + } +}`) + }) +} + +func mockDeleteRuleResponse(t *testing.T, ruleID string) { + url := fmt.Sprintf("/os-security-group-rules/%s", ruleID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockAddServerToGroupResponse(t *testing.T, serverID string) { + url := fmt.Sprintf("/servers/%s/action", serverID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "addSecurityGroup": { + "name": "test" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + fmt.Fprintf(w, `{}`) + }) +} + +func mockRemoveServerFromGroupResponse(t *testing.T, serverID string) { + url := fmt.Sprintf("/servers/%s/action", serverID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "removeSecurityGroup": { + "name": "test" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + fmt.Fprintf(w, `{}`) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go new file mode 100644 index 000000000..4cef48022 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go @@ -0,0 +1,257 @@ +package secgroups + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return SecurityGroupPage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, url, createPage) +} + +// List will return a collection of all the security groups for a particular +// tenant. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return commonList(client, rootURL(client)) +} + +// ListByServer will return a collection of all the security groups which are +// associated with a particular server. +func ListByServer(client *gophercloud.ServiceClient, serverID string) pagination.Pager { + return commonList(client, listByServerURL(client, serverID)) +} + +// GroupOpts is the underlying struct responsible for creating or updating +// security groups. It therefore represents the mutable attributes of a +// security group. +type GroupOpts struct { + // Required - the name of your security group. + Name string `json:"name"` + + // Required - the description of your security group. + Description string `json:"description"` +} + +// CreateOpts is the struct responsible for creating a security group. +type CreateOpts GroupOpts + +// CreateOptsBuilder builds the create options into a serializable format. +type CreateOptsBuilder interface { + ToSecGroupCreateMap() (map[string]interface{}, error) +} + +var ( + errName = errors.New("Name is a required field") + errDesc = errors.New("Description is a required field") +) + +// ToSecGroupCreateMap builds the create options into a serializable format. +func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) { + sg := make(map[string]interface{}) + + if opts.Name == "" { + return sg, errName + } + if opts.Description == "" { + return sg, errDesc + } + + sg["name"] = opts.Name + sg["description"] = opts.Description + + return map[string]interface{}{"security_group": sg}, nil +} + +// Create will create a new security group. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var result CreateResult + + reqBody, err := opts.ToSecGroupCreateMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return result +} + +// UpdateOpts is the struct responsible for updating an existing security group. +type UpdateOpts GroupOpts + +// UpdateOptsBuilder builds the update options into a serializable format. +type UpdateOptsBuilder interface { + ToSecGroupUpdateMap() (map[string]interface{}, error) +} + +// ToSecGroupUpdateMap builds the update options into a serializable format. +func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) { + sg := make(map[string]interface{}) + + if opts.Name == "" { + return sg, errName + } + if opts.Description == "" { + return sg, errDesc + } + + sg["name"] = opts.Name + sg["description"] = opts.Description + + return map[string]interface{}{"security_group": sg}, nil +} + +// Update will modify the mutable properties of a security group, notably its +// name and description. +func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var result UpdateResult + + reqBody, err := opts.ToSecGroupUpdateMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Put(resourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return result +} + +// Get will return details for a particular security group. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var result GetResult + _, result.Err = client.Get(resourceURL(client, id), &result.Body, nil) + return result +} + +// Delete will permanently delete a security group from the project. +func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { + var result gophercloud.ErrResult + _, result.Err = client.Delete(resourceURL(client, id), nil) + return result +} + +// CreateRuleOpts represents the configuration for adding a new rule to an +// existing security group. +type CreateRuleOpts struct { + // Required - the ID of the group that this rule will be added to. + ParentGroupID string `json:"parent_group_id"` + + // Required - the lower bound of the port range that will be opened. + FromPort int `json:"from_port"` + + // Required - the upper bound of the port range that will be opened. + ToPort int `json:"to_port"` + + // Required - the protocol type that will be allowed, e.g. TCP. + IPProtocol string `json:"ip_protocol"` + + // ONLY required if FromGroupID is blank. This represents the IP range that + // will be the source of network traffic to your security group. Use + // 0.0.0.0/0 to allow all IP addresses. + CIDR string `json:"cidr,omitempty"` + + // ONLY required if CIDR is blank. This value represents the ID of a group + // that forwards traffic to the parent group. So, instead of accepting + // network traffic from an entire IP range, you can instead refine the + // inbound source by an existing security group. + FromGroupID string `json:"group_id,omitempty"` +} + +// CreateRuleOptsBuilder builds the create rule options into a serializable format. +type CreateRuleOptsBuilder interface { + ToRuleCreateMap() (map[string]interface{}, error) +} + +// ToRuleCreateMap builds the create rule options into a serializable format. +func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) { + rule := make(map[string]interface{}) + + if opts.ParentGroupID == "" { + return rule, errors.New("A ParentGroupID must be set") + } + if opts.FromPort == 0 { + return rule, errors.New("A FromPort must be set") + } + if opts.ToPort == 0 { + return rule, errors.New("A ToPort must be set") + } + if opts.IPProtocol == "" { + return rule, errors.New("A IPProtocol must be set") + } + if opts.CIDR == "" && opts.FromGroupID == "" { + return rule, errors.New("A CIDR or FromGroupID must be set") + } + + rule["parent_group_id"] = opts.ParentGroupID + rule["from_port"] = opts.FromPort + rule["to_port"] = opts.ToPort + rule["ip_protocol"] = opts.IPProtocol + + if opts.CIDR != "" { + rule["cidr"] = opts.CIDR + } + if opts.FromGroupID != "" { + rule["group_id"] = opts.FromGroupID + } + + return map[string]interface{}{"security_group_rule": rule}, nil +} + +// CreateRule will add a new rule to an existing security group (whose ID is +// specified in CreateRuleOpts). You have the option of controlling inbound +// traffic from either an IP range (CIDR) or from another security group. +func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) CreateRuleResult { + var result CreateRuleResult + + reqBody, err := opts.ToRuleCreateMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Post(rootRuleURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return result +} + +// DeleteRule will permanently delete a rule from a security group. +func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { + var result gophercloud.ErrResult + _, result.Err = client.Delete(resourceRuleURL(client, id), nil) + return result +} + +func actionMap(prefix, groupName string) map[string]map[string]string { + return map[string]map[string]string{ + prefix + "SecurityGroup": map[string]string{"name": groupName}, + } +} + +// AddServerToGroup will associate a server and a security group, enforcing the +// rules of the group on the server. +func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { + var result gophercloud.ErrResult + _, result.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &result.Body, nil) + return result +} + +// RemoveServerFromGroup will disassociate a server from a security group. +func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { + var result gophercloud.ErrResult + _, result.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &result.Body, nil) + return result +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go new file mode 100644 index 000000000..478c5dc09 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go @@ -0,0 +1,147 @@ +package secgroups + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// SecurityGroup represents a security group. +type SecurityGroup struct { + // The unique ID of the group. If Neutron is installed, this ID will be + // represented as a string UUID; if Neutron is not installed, it will be a + // numeric ID. For the sake of consistency, we always cast it to a string. + ID string + + // The human-readable name of the group, which needs to be unique. + Name string + + // The human-readable description of the group. + Description string + + // The rules which determine how this security group operates. + Rules []Rule + + // The ID of the tenant to which this security group belongs. + TenantID string `mapstructure:"tenant_id"` +} + +// Rule represents a security group rule, a policy which determines how a +// security group operates and what inbound traffic it allows in. +type Rule struct { + // The unique ID. If Neutron is installed, this ID will be + // represented as a string UUID; if Neutron is not installed, it will be a + // numeric ID. For the sake of consistency, we always cast it to a string. + ID string + + // The lower bound of the port range which this security group should open up + FromPort int `mapstructure:"from_port"` + + // The upper bound of the port range which this security group should open up + ToPort int `mapstructure:"to_port"` + + // The IP protocol (e.g. TCP) which the security group accepts + IPProtocol string `mapstructure:"ip_protocol"` + + // The CIDR IP range whose traffic can be received + IPRange IPRange `mapstructure:"ip_range"` + + // The security group ID to which this rule belongs + ParentGroupID string `mapstructure:"parent_group_id"` + + // Not documented. + Group Group +} + +// IPRange represents the IP range whose traffic will be accepted by the +// security group. +type IPRange struct { + CIDR string +} + +// Group represents a group. +type Group struct { + TenantID string `mapstructure:"tenant_id"` + Name string +} + +// SecurityGroupPage is a single page of a SecurityGroup collection. +type SecurityGroupPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a page of Security Groups contains any results. +func (page SecurityGroupPage) IsEmpty() (bool, error) { + users, err := ExtractSecurityGroups(page) + if err != nil { + return false, err + } + return len(users) == 0, nil +} + +// ExtractSecurityGroups returns a slice of SecurityGroups contained in a single page of results. +func ExtractSecurityGroups(page pagination.Page) ([]SecurityGroup, error) { + casted := page.(SecurityGroupPage).Body + var response struct { + SecurityGroups []SecurityGroup `mapstructure:"security_groups"` + } + + err := mapstructure.WeakDecode(casted, &response) + + return response.SecurityGroups, err +} + +type commonResult struct { + gophercloud.Result +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// Extract will extract a SecurityGroup struct from most responses. +func (r commonResult) Extract() (*SecurityGroup, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + SecurityGroup SecurityGroup `mapstructure:"security_group"` + } + + err := mapstructure.WeakDecode(r.Body, &response) + + return &response.SecurityGroup, err +} + +// CreateRuleResult represents the result when adding rules to a security group. +type CreateRuleResult struct { + gophercloud.Result +} + +// Extract will extract a Rule struct from a CreateRuleResult. +func (r CreateRuleResult) Extract() (*Rule, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Rule Rule `mapstructure:"security_group_rule"` + } + + err := mapstructure.WeakDecode(r.Body, &response) + + return &response.Rule, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go new file mode 100644 index 000000000..dc53fbfac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go @@ -0,0 +1,32 @@ +package secgroups + +import "github.com/rackspace/gophercloud" + +const ( + secgrouppath = "os-security-groups" + rulepath = "os-security-group-rules" +) + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(secgrouppath, id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(secgrouppath) +} + +func listByServerURL(c *gophercloud.ServiceClient, serverID string) string { + return c.ServiceURL("servers", serverID, secgrouppath) +} + +func rootRuleURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rulepath) +} + +func resourceRuleURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rulepath, id) +} + +func serverActionURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("servers", id, "action") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/doc.go new file mode 100644 index 000000000..1e5ed568d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/doc.go @@ -0,0 +1,2 @@ +// Package servergroups provides the ability to manage server groups +package servergroups diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/fixtures.go new file mode 100644 index 000000000..133fd85ce --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/fixtures.go @@ -0,0 +1,161 @@ +// +build fixtures + +package servergroups + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "server_groups": [ + { + "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", + "name": "test", + "policies": [ + "anti-affinity" + ], + "members": [], + "metadata": {} + }, + { + "id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "name": "test2", + "policies": [ + "affinity" + ], + "members": [], + "metadata": {} + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "server_group": { + "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", + "name": "test", + "policies": [ + "anti-affinity" + ], + "members": [], + "metadata": {} + } +} +` + +// CreateOutput is a sample response to a Post call +const CreateOutput = ` +{ + "server_group": { + "id": "616fb98f-46ca-475e-917e-2563e5a8cd19", + "name": "test", + "policies": [ + "anti-affinity" + ], + "members": [], + "metadata": {} + } +} +` + +// FirstServerGroup is the first result in ListOutput. +var FirstServerGroup = ServerGroup{ + ID: "616fb98f-46ca-475e-917e-2563e5a8cd19", + Name: "test", + Policies: []string{ + "anti-affinity", + }, + Members: []string{}, + Metadata: map[string]interface{}{}, +} + +// SecondServerGroup is the second result in ListOutput. +var SecondServerGroup = ServerGroup{ + ID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + Name: "test2", + Policies: []string{ + "affinity", + }, + Members: []string{}, + Metadata: map[string]interface{}{}, +} + +// ExpectedServerGroupSlice is the slice of results that should be parsed +// from ListOutput, in the expected order. +var ExpectedServerGroupSlice = []ServerGroup{FirstServerGroup, SecondServerGroup} + +// CreatedServerGroup is the parsed result from CreateOutput. +var CreatedServerGroup = ServerGroup{ + ID: "616fb98f-46ca-475e-917e-2563e5a8cd19", + Name: "test", + Policies: []string{ + "anti-affinity", + }, + Members: []string{}, + Metadata: map[string]interface{}{}, +} + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request +// for an existing server group +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-server-groups/4d8c3732-a248-40ed-bebc-539a6ffd25c0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} + +// HandleCreateSuccessfully configures the test server to respond to a Create request +// for a new server group +func HandleCreateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-server-groups", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "server_group": { + "name": "test", + "policies": [ + "anti-affinity" + ] + } +} +`) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, CreateOutput) + }) +} + +// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a +// an existing server group +func HandleDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-server-groups/616fb98f-46ca-475e-917e-2563e5a8cd19", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/requests.go new file mode 100644 index 000000000..1597b43eb --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/requests.go @@ -0,0 +1,77 @@ +package servergroups + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of ServerGroups. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { + return ServerGroupsPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notably, the +// CreateOpts struct in this package does. +type CreateOptsBuilder interface { + ToServerGroupCreateMap() (map[string]interface{}, error) +} + +// CreateOpts specifies a Server Group allocation request +type CreateOpts struct { + // Name is the name of the server group + Name string + + // Policies are the server group policies + Policies []string +} + +// ToServerGroupCreateMap constructs a request body from CreateOpts. +func (opts CreateOpts) ToServerGroupCreateMap() (map[string]interface{}, error) { + if opts.Name == "" { + return nil, errors.New("Missing field required for server group creation: Name") + } + + if len(opts.Policies) < 1 { + return nil, errors.New("Missing field required for server group creation: Policies") + } + + serverGroup := make(map[string]interface{}) + serverGroup["name"] = opts.Name + serverGroup["policies"] = opts.Policies + + return map[string]interface{}{"server_group": serverGroup}, nil +} + +// Create requests the creation of a new Server Group +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToServerGroupCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Get returns data about a previously created ServerGroup. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} + +// Delete requests the deletion of a previously allocated ServerGroup. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/results.go new file mode 100644 index 000000000..d74ee5dbb --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/results.go @@ -0,0 +1,87 @@ +package servergroups + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// A ServerGroup creates a policy for instance placement in the cloud +type ServerGroup struct { + // ID is the unique ID of the Server Group. + ID string `mapstructure:"id"` + + // Name is the common name of the server group. + Name string `mapstructure:"name"` + + // Polices are the group policies. + Policies []string `mapstructure:"policies"` + + // Members are the members of the server group. + Members []string `mapstructure:"members"` + + // Metadata includes a list of all user-specified key-value pairs attached to the Server Group. + Metadata map[string]interface{} +} + +// ServerGroupsPage stores a single, only page of ServerGroups +// results from a List call. +type ServerGroupsPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a ServerGroupsPage is empty. +func (page ServerGroupsPage) IsEmpty() (bool, error) { + va, err := ExtractServerGroups(page) + return len(va) == 0, err +} + +// ExtractServerGroups interprets a page of results as a slice of +// ServerGroups. +func ExtractServerGroups(page pagination.Page) ([]ServerGroup, error) { + casted := page.(ServerGroupsPage).Body + var response struct { + ServerGroups []ServerGroup `mapstructure:"server_groups"` + } + + err := mapstructure.WeakDecode(casted, &response) + + return response.ServerGroups, err +} + +type ServerGroupResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any Server Group resource +// response as a ServerGroup struct. +func (r ServerGroupResult) Extract() (*ServerGroup, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + ServerGroup *ServerGroup `json:"server_group" mapstructure:"server_group"` + } + + err := mapstructure.WeakDecode(r.Body, &res) + return res.ServerGroup, err +} + +// CreateResult is the response from a Create operation. Call its Extract method to interpret it +// as a ServerGroup. +type CreateResult struct { + ServerGroupResult +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a ServerGroup. +type GetResult struct { + ServerGroupResult +} + +// DeleteResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/urls.go new file mode 100644 index 000000000..074a16c67 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups/urls.go @@ -0,0 +1,25 @@ +package servergroups + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-server-groups" + +func resourceURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func listURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go new file mode 100644 index 000000000..d2729f874 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go @@ -0,0 +1,5 @@ +/* +Package startstop provides functionality to start and stop servers that have +been provisioned by the OpenStack Compute service. +*/ +package startstop diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go new file mode 100644 index 000000000..670828a98 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go @@ -0,0 +1,27 @@ +package startstop + +import ( + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +func mockStartServerResponse(t *testing.T, id string) { + th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{"os-start": null}`) + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockStopServerResponse(t *testing.T, id string) { + th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{"os-stop": null}`) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go new file mode 100644 index 000000000..0e090e69f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go @@ -0,0 +1,23 @@ +package startstop + +import "github.com/rackspace/gophercloud" + +func actionURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("servers", id, "action") +} + +// Start is the operation responsible for starting a Compute server. +func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { + var res gophercloud.ErrResult + reqBody := map[string]interface{}{"os-start": nil} + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) + return res +} + +// Stop is the operation responsible for stopping a Compute server. +func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { + var res gophercloud.ErrResult + reqBody := map[string]interface{}{"os-stop": nil} + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go new file mode 100644 index 000000000..65c46ff50 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go @@ -0,0 +1,2 @@ +// Package tenantnetworks provides the ability for tenants to see information about the networks they have access to +package tenantnetworks diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go new file mode 100644 index 000000000..0cfa72ab0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go @@ -0,0 +1,84 @@ +// +build fixtures + +package tenantnetworks + +import ( + "fmt" + "net/http" + "testing" + "time" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "networks": [ + { + "cidr": "10.0.0.0/29", + "id": "20c8acc0-f747-4d71-a389-46d078ebf047", + "label": "mynet_0" + }, + { + "cidr": "10.0.0.10/29", + "id": "20c8acc0-f747-4d71-a389-46d078ebf000", + "label": "mynet_1" + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "network": { + "cidr": "10.0.0.10/29", + "id": "20c8acc0-f747-4d71-a389-46d078ebf000", + "label": "mynet_1" + } +} +` + +// FirstNetwork is the first result in ListOutput. +var nilTime time.Time +var FirstNetwork = Network{ + CIDR: "10.0.0.0/29", + ID: "20c8acc0-f747-4d71-a389-46d078ebf047", + Name: "mynet_0", +} + +// SecondNetwork is the second result in ListOutput. +var SecondNetwork = Network{ + CIDR: "10.0.0.10/29", + ID: "20c8acc0-f747-4d71-a389-46d078ebf000", + Name: "mynet_1", +} + +// ExpectedNetworkSlice is the slice of results that should be parsed +// from ListOutput, in the expected order. +var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork} + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-tenant-networks", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request +// for an existing network. +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/os-tenant-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go new file mode 100644 index 000000000..3ec13d384 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go @@ -0,0 +1,22 @@ +package tenantnetworks + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of Network. +func List(client *gophercloud.ServiceClient) pagination.Pager { + url := listURL(client) + createPage := func(r pagination.PageResult) pagination.Page { + return NetworkPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, url, createPage) +} + +// Get returns data about a previously created Network. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go new file mode 100644 index 000000000..805009247 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go @@ -0,0 +1,68 @@ +package tenantnetworks + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// A Network represents a nova-network that an instance communicates on +type Network struct { + // CIDR is the IPv4 subnet. + CIDR string `mapstructure:"cidr"` + + // ID is the UUID of the network. + ID string `mapstructure:"id"` + + // Name is the common name that the network has. + Name string `mapstructure:"label"` +} + +// NetworkPage stores a single, only page of Networks +// results from a List call. +type NetworkPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a NetworkPage is empty. +func (page NetworkPage) IsEmpty() (bool, error) { + va, err := ExtractNetworks(page) + return len(va) == 0, err +} + +// ExtractNetworks interprets a page of results as a slice of Networks +func ExtractNetworks(page pagination.Page) ([]Network, error) { + networks := page.(NetworkPage).Body + var res struct { + Networks []Network `mapstructure:"networks"` + } + + err := mapstructure.WeakDecode(networks, &res) + + return res.Networks, err +} + +type NetworkResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any Network resource +// response as a Network struct. +func (r NetworkResult) Extract() (*Network, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *Network `json:"network" mapstructure:"network"` + } + + err := mapstructure.Decode(r.Body, &res) + return res.Network, err +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a Network. +type GetResult struct { + NetworkResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go new file mode 100644 index 000000000..2401a5d03 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go @@ -0,0 +1,17 @@ +package tenantnetworks + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-tenant-networks" + +func resourceURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func listURL(c *gophercloud.ServiceClient) string { + return resourceURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go new file mode 100644 index 000000000..22f68d80e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go @@ -0,0 +1,3 @@ +// Package volumeattach provides the ability to attach and detach volumes +// to instances +package volumeattach diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go new file mode 100644 index 000000000..b4ebedea8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go @@ -0,0 +1,75 @@ +package volumeattach + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of VolumeAttachments. +func List(client *gophercloud.ServiceClient, serverId string) pagination.Pager { + return pagination.NewPager(client, listURL(client, serverId), func(r pagination.PageResult) pagination.Page { + return VolumeAttachmentsPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the +// CreateOpts struct in this package does. +type CreateOptsBuilder interface { + ToVolumeAttachmentCreateMap() (map[string]interface{}, error) +} + +// CreateOpts specifies volume attachment creation or import parameters. +type CreateOpts struct { + // Device is the device that the volume will attach to the instance as. Omit for "auto" + Device string + + // VolumeID is the ID of the volume to attach to the instance + VolumeID string +} + +// ToVolumeAttachmentCreateMap constructs a request body from CreateOpts. +func (opts CreateOpts) ToVolumeAttachmentCreateMap() (map[string]interface{}, error) { + if opts.VolumeID == "" { + return nil, errors.New("Missing field required for volume attachment creation: VolumeID") + } + + volumeAttachment := make(map[string]interface{}) + volumeAttachment["volumeId"] = opts.VolumeID + if opts.Device != "" { + volumeAttachment["device"] = opts.Device + } + + return map[string]interface{}{"volumeAttachment": volumeAttachment}, nil +} + +// Create requests the creation of a new volume attachment on the server +func Create(client *gophercloud.ServiceClient, serverId string, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToVolumeAttachmentCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(createURL(client, serverId), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Get returns public data about a previously created VolumeAttachment. +func Get(client *gophercloud.ServiceClient, serverId, aId string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, serverId, aId), &res.Body, nil) + return res +} + +// Delete requests the deletion of a previous stored VolumeAttachment from the server. +func Delete(client *gophercloud.ServiceClient, serverId, aId string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, serverId, aId), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go new file mode 100644 index 000000000..26be39e4f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go @@ -0,0 +1,84 @@ +package volumeattach + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// VolumeAttach controls the attachment of a volume to an instance. +type VolumeAttachment struct { + // ID is a unique id of the attachment + ID string `mapstructure:"id"` + + // Device is what device the volume is attached as + Device string `mapstructure:"device"` + + // VolumeID is the ID of the attached volume + VolumeID string `mapstructure:"volumeId"` + + // ServerID is the ID of the instance that has the volume attached + ServerID string `mapstructure:"serverId"` +} + +// VolumeAttachmentsPage stores a single, only page of VolumeAttachments +// results from a List call. +type VolumeAttachmentsPage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a VolumeAttachmentsPage is empty. +func (page VolumeAttachmentsPage) IsEmpty() (bool, error) { + va, err := ExtractVolumeAttachments(page) + return len(va) == 0, err +} + +// ExtractVolumeAttachments interprets a page of results as a slice of +// VolumeAttachments. +func ExtractVolumeAttachments(page pagination.Page) ([]VolumeAttachment, error) { + casted := page.(VolumeAttachmentsPage).Body + var response struct { + VolumeAttachments []VolumeAttachment `mapstructure:"volumeAttachments"` + } + + err := mapstructure.WeakDecode(casted, &response) + + return response.VolumeAttachments, err +} + +type VolumeAttachmentResult struct { + gophercloud.Result +} + +// Extract is a method that attempts to interpret any VolumeAttachment resource +// response as a VolumeAttachment struct. +func (r VolumeAttachmentResult) Extract() (*VolumeAttachment, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + VolumeAttachment *VolumeAttachment `json:"volumeAttachment" mapstructure:"volumeAttachment"` + } + + err := mapstructure.Decode(r.Body, &res) + return res.VolumeAttachment, err +} + +// CreateResult is the response from a Create operation. Call its Extract method to interpret it +// as a VolumeAttachment. +type CreateResult struct { + VolumeAttachmentResult +} + +// GetResult is the response from a Get operation. Call its Extract method to interpret it +// as a VolumeAttachment. +type GetResult struct { + VolumeAttachmentResult +} + +// DeleteResult is the response from a Delete operation. Call its Extract method to determine if +// the call succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/doc.go new file mode 100644 index 000000000..183391a62 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/doc.go @@ -0,0 +1,7 @@ +/* +This is package created is to hold fixtures (which imports testing), +so that importing volumeattach package does not inadvertently import testing into production code +More information here: +https://github.com/rackspace/gophercloud/issues/473 +*/ +package testing diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go new file mode 100644 index 000000000..c469bfbc8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go @@ -0,0 +1,110 @@ +// +build fixtures + +package testing + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput is a sample response to a List call. +const ListOutput = ` +{ + "volumeAttachments": [ + { + "device": "/dev/vdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + }, + { + "device": "/dev/vdc", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" + } + ] +} +` + +// GetOutput is a sample response to a Get call. +const GetOutput = ` +{ + "volumeAttachment": { + "device": "/dev/vdc", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" + } +} +` + +// CreateOutput is a sample response to a Create call. +const CreateOutput = ` +{ + "volumeAttachment": { + "device": "/dev/vdc", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" + } +} +` + +// HandleListSuccessfully configures the test server to respond to a List request. +func HandleListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, ListOutput) + }) +} + +// HandleGetSuccessfully configures the test server to respond to a Get request +// for an existing attachment +func HandleGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, GetOutput) + }) +} + +// HandleCreateSuccessfully configures the test server to respond to a Create request +// for a new attachment +func HandleCreateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` +{ + "volumeAttachment": { + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "device": "/dev/vdc" + } +} +`) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, CreateOutput) + }) +} + +// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a +// an existing attachment +func HandleDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go new file mode 100644 index 000000000..9d9d1786d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go @@ -0,0 +1,25 @@ +package volumeattach + +import "github.com/rackspace/gophercloud" + +const resourcePath = "os-volume_attachments" + +func resourceURL(c *gophercloud.ServiceClient, serverId string) string { + return c.ServiceURL("servers", serverId, resourcePath) +} + +func listURL(c *gophercloud.ServiceClient, serverId string) string { + return resourceURL(c, serverId) +} + +func createURL(c *gophercloud.ServiceClient, serverId string) string { + return resourceURL(c, serverId) +} + +func getURL(c *gophercloud.ServiceClient, serverId, aId string) string { + return c.ServiceURL("servers", serverId, resourcePath, aId) +} + +func deleteURL(c *gophercloud.ServiceClient, serverId, aId string) string { + return getURL(c, serverId, aId) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/doc.go new file mode 100644 index 000000000..5822e1bcf --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/doc.go @@ -0,0 +1,7 @@ +// Package flavors provides information and interaction with the flavor API +// resource in the OpenStack Compute service. +// +// A flavor is an available hardware configuration for a server. Each flavor +// has a unique combination of disk space, memory capacity and priority for CPU +// time. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/requests.go new file mode 100644 index 000000000..59123aaf7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/requests.go @@ -0,0 +1,103 @@ +package flavors + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToFlavorListQuery() (string, error) +} + +// ListOpts helps control the results returned by the List() function. +// For example, a flavor with a minDisk field of 10 will not be returned if you specify MinDisk set to 20. +// Typically, software will use the last ID of the previous call to List to set the Marker for the current call. +type ListOpts struct { + + // ChangesSince, if provided, instructs List to return only those things which have changed since the timestamp provided. + ChangesSince string `q:"changes-since"` + + // MinDisk and MinRAM, if provided, elides flavors which do not meet your criteria. + MinDisk int `q:"minDisk"` + MinRAM int `q:"minRam"` + + // Marker and Limit control paging. + // Marker instructs List where to start listing from. + Marker string `q:"marker"` + + // Limit instructs List to refrain from sending excessively large lists of flavors. + Limit int `q:"limit"` +} + +// ToFlavorListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToFlavorListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListDetail instructs OpenStack to provide a list of flavors. +// You may provide criteria by which List curtails its results for easier processing. +// See ListOpts for more details. +func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(client) + if opts != nil { + query, err := opts.ToFlavorListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + createPage := func(r pagination.PageResult) pagination.Page { + return FlavorPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, url, createPage) +} + +// Get instructs OpenStack to provide details on a single flavor, identified by its ID. +// Use ExtractFlavor to convert its result into a Flavor. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} + +// IDFromName is a convienience function that returns a flavor's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + flavorCount := 0 + flavorID := "" + if name == "" { + return "", fmt.Errorf("A flavor name must be provided.") + } + pager := ListDetail(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + flavorList, err := ExtractFlavors(page) + if err != nil { + return false, err + } + + for _, f := range flavorList { + if f.Name == name { + flavorCount++ + flavorID = f.ID + } + } + return true, nil + }) + + switch flavorCount { + case 0: + return "", fmt.Errorf("Unable to find flavor: %s", name) + case 1: + return flavorID, nil + default: + return "", fmt.Errorf("Found %d flavors matching %s", flavorCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/results.go new file mode 100644 index 000000000..8dddd705c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/results.go @@ -0,0 +1,122 @@ +package flavors + +import ( + "errors" + "reflect" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ErrCannotInterpret is returned by an Extract call if the response body doesn't have the expected structure. +var ErrCannotInterpet = errors.New("Unable to interpret a response body.") + +// GetResult temporarily holds the response from a Get call. +type GetResult struct { + gophercloud.Result +} + +// Extract provides access to the individual Flavor returned by the Get function. +func (gr GetResult) Extract() (*Flavor, error) { + if gr.Err != nil { + return nil, gr.Err + } + + var result struct { + Flavor Flavor `mapstructure:"flavor"` + } + + cfg := &mapstructure.DecoderConfig{ + DecodeHook: defaulter, + Result: &result, + } + decoder, err := mapstructure.NewDecoder(cfg) + if err != nil { + return nil, err + } + err = decoder.Decode(gr.Body) + return &result.Flavor, err +} + +// Flavor records represent (virtual) hardware configurations for server resources in a region. +type Flavor struct { + // The Id field contains the flavor's unique identifier. + // For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance. + ID string `mapstructure:"id"` + + // The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively. + Disk int `mapstructure:"disk"` + RAM int `mapstructure:"ram"` + + // The Name field provides a human-readable moniker for the flavor. + Name string `mapstructure:"name"` + + RxTxFactor float64 `mapstructure:"rxtx_factor"` + + // Swap indicates how much space is reserved for swap. + // If not provided, this field will be set to 0. + Swap int `mapstructure:"swap"` + + // VCPUs indicates how many (virtual) CPUs are available for this flavor. + VCPUs int `mapstructure:"vcpus"` +} + +// FlavorPage contains a single page of the response from a List call. +type FlavorPage struct { + pagination.LinkedPageBase +} + +// IsEmpty determines if a page contains any results. +func (p FlavorPage) IsEmpty() (bool, error) { + flavors, err := ExtractFlavors(p) + if err != nil { + return true, err + } + return len(flavors) == 0, nil +} + +// NextPageURL uses the response's embedded link reference to navigate to the next page of results. +func (p FlavorPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"flavors_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) { + if (from == reflect.String) && (to == reflect.Int) { + return 0, nil + } + return v, nil +} + +// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation. +func ExtractFlavors(page pagination.Page) ([]Flavor, error) { + casted := page.(FlavorPage).Body + var container struct { + Flavors []Flavor `mapstructure:"flavors"` + } + + cfg := &mapstructure.DecoderConfig{ + DecodeHook: defaulter, + Result: &container, + } + decoder, err := mapstructure.NewDecoder(cfg) + if err != nil { + return container.Flavors, err + } + err = decoder.Decode(casted) + if err != nil { + return container.Flavors, err + } + + return container.Flavors, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/urls.go new file mode 100644 index 000000000..683c107dc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/flavors/urls.go @@ -0,0 +1,13 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" +) + +func getURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("flavors", id) +} + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("flavors", "detail") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/doc.go new file mode 100644 index 000000000..0edaa3f02 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/doc.go @@ -0,0 +1,7 @@ +// Package images provides information and interaction with the image API +// resource in the OpenStack Compute service. +// +// An image is a collection of files used to create or rebuild a server. +// Operators provide a number of pre-built OS images by default. You may also +// create custom images from cloud servers you have launched. +package images diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/requests.go new file mode 100644 index 000000000..1e021ad4c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/requests.go @@ -0,0 +1,109 @@ +package images + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToImageListQuery() (string, error) +} + +// ListOpts contain options for limiting the number of Images returned from a call to ListDetail. +type ListOpts struct { + // When the image last changed status (in date-time format). + ChangesSince string `q:"changes-since"` + // The number of Images to return. + Limit int `q:"limit"` + // UUID of the Image at which to set a marker. + Marker string `q:"marker"` + // The name of the Image. + Name string `q:"name"` + // The name of the Server (in URL format). + Server string `q:"server"` + // The current status of the Image. + Status string `q:"status"` + // The value of the type of image (e.g. BASE, SERVER, ALL) + Type string `q:"type"` +} + +// ToImageListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToImageListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListDetail enumerates the available images. +func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listDetailURL(client) + if opts != nil { + query, err := opts.ToImageListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPage := func(r pagination.PageResult) pagination.Page { + return ImagePage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, url, createPage) +} + +// Get acquires additional detail about a specific image by ID. +// Use ExtractImage() to interpret the result as an openstack Image. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var result GetResult + _, result.Err = client.Get(getURL(client, id), &result.Body, nil) + return result +} + +// Delete deletes the specified image ID. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var result DeleteResult + _, result.Err = client.Delete(deleteURL(client, id), nil) + return result +} + +// IDFromName is a convienience function that returns an image's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + imageCount := 0 + imageID := "" + if name == "" { + return "", fmt.Errorf("An image name must be provided.") + } + pager := ListDetail(client, &ListOpts{ + Name: name, + }) + pager.EachPage(func(page pagination.Page) (bool, error) { + imageList, err := ExtractImages(page) + if err != nil { + return false, err + } + + for _, i := range imageList { + if i.Name == name { + imageCount++ + imageID = i.ID + } + } + return true, nil + }) + + switch imageCount { + case 0: + return "", fmt.Errorf("Unable to find image: %s", name) + case 1: + return imageID, nil + default: + return "", fmt.Errorf("Found %d images matching %s", imageCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/results.go new file mode 100644 index 000000000..40e814d1d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/results.go @@ -0,0 +1,95 @@ +package images + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// GetResult temporarily stores a Get response. +type GetResult struct { + gophercloud.Result +} + +// DeleteResult represents the result of an image.Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Extract interprets a GetResult as an Image. +func (gr GetResult) Extract() (*Image, error) { + if gr.Err != nil { + return nil, gr.Err + } + + var decoded struct { + Image Image `mapstructure:"image"` + } + + err := mapstructure.Decode(gr.Body, &decoded) + return &decoded.Image, err +} + +// Image is used for JSON (un)marshalling. +// It provides a description of an OS image. +type Image struct { + // ID contains the image's unique identifier. + ID string + + Created string + + // MinDisk and MinRAM specify the minimum resources a server must provide to be able to install the image. + MinDisk int + MinRAM int + + // Name provides a human-readable moniker for the OS image. + Name string + + // The Progress and Status fields indicate image-creation status. + // Any usable image will have 100% progress. + Progress int + Status string + + Updated string +} + +// ImagePage contains a single page of results from a List operation. +// Use ExtractImages to convert it into a slice of usable structs. +type ImagePage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if a page contains no Image results. +func (page ImagePage) IsEmpty() (bool, error) { + images, err := ExtractImages(page) + if err != nil { + return true, err + } + return len(images) == 0, nil +} + +// NextPageURL uses the response's embedded link reference to navigate to the next page of results. +func (page ImagePage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"images_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractImages converts a page of List results into a slice of usable Image structs. +func ExtractImages(page pagination.Page) ([]Image, error) { + casted := page.(ImagePage).Body + var results struct { + Images []Image `mapstructure:"images"` + } + + err := mapstructure.Decode(casted, &results) + return results.Images, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/urls.go new file mode 100644 index 000000000..b1bf1038f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/images/urls.go @@ -0,0 +1,15 @@ +package images + +import "github.com/rackspace/gophercloud" + +func listDetailURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("images", "detail") +} + +func getURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("images", id) +} + +func deleteURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("images", id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go new file mode 100644 index 000000000..fe4567120 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go @@ -0,0 +1,6 @@ +// Package servers provides information and interaction with the server API +// resource in the OpenStack Compute service. +// +// A server is a virtual machine instance in the compute system. In order for +// one to be provisioned, a valid flavor and image are required. +package servers diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go new file mode 100644 index 000000000..4339a16d4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go @@ -0,0 +1,664 @@ +// +build fixtures + +package servers + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ServerListBody contains the canned body of a servers.List response. +const ServerListBody = ` +{ + "servers": [ + { + "status": "ACTIVE", + "updated": "2014-09-25T13:10:10Z", + "hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362", + "OS-EXT-SRV-ATTR:host": "devstack", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b", + "version": 4, + "addr": "10.0.0.32", + "OS-EXT-IPS:type": "fixed" + } + ] + }, + "links": [ + { + "href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + "rel": "self" + }, + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + "rel": "bookmark" + } + ], + "key_name": null, + "image": { + "id": "f90f6034-2570-4974-8351-6b49732ef2eb", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "rel": "bookmark" + } + ] + }, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-EXT-SRV-ATTR:instance_name": "instance-0000001e", + "OS-SRV-USG:launched_at": "2014-09-25T13:10:10.000000", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack", + "flavor": { + "id": "1", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1", + "rel": "bookmark" + } + ] + }, + "id": "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + "security_groups": [ + { + "name": "default" + } + ], + "OS-SRV-USG:terminated_at": null, + "OS-EXT-AZ:availability_zone": "nova", + "user_id": "9349aff8be7545ac9d2f1d00999a23cd", + "name": "herp", + "created": "2014-09-25T13:10:02Z", + "tenant_id": "fcad67a6189847c4aecfa3c81a05783b", + "OS-DCF:diskConfig": "MANUAL", + "os-extended-volumes:volumes_attached": [], + "accessIPv4": "", + "accessIPv6": "", + "progress": 0, + "OS-EXT-STS:power_state": 1, + "config_drive": "", + "metadata": {} + }, + { + "status": "ACTIVE", + "updated": "2014-09-25T13:04:49Z", + "hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362", + "OS-EXT-SRV-ATTR:host": "devstack", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be", + "version": 4, + "addr": "10.0.0.31", + "OS-EXT-IPS:type": "fixed" + } + ] + }, + "links": [ + { + "href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "self" + }, + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "bookmark" + } + ], + "key_name": null, + "image": { + "id": "f90f6034-2570-4974-8351-6b49732ef2eb", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "rel": "bookmark" + } + ] + }, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-EXT-SRV-ATTR:instance_name": "instance-0000001d", + "OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack", + "flavor": { + "id": "1", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1", + "rel": "bookmark" + } + ] + }, + "id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "security_groups": [ + { + "name": "default" + } + ], + "OS-SRV-USG:terminated_at": null, + "OS-EXT-AZ:availability_zone": "nova", + "user_id": "9349aff8be7545ac9d2f1d00999a23cd", + "name": "derp", + "created": "2014-09-25T13:04:41Z", + "tenant_id": "fcad67a6189847c4aecfa3c81a05783b", + "OS-DCF:diskConfig": "MANUAL", + "os-extended-volumes:volumes_attached": [], + "accessIPv4": "", + "accessIPv6": "", + "progress": 0, + "OS-EXT-STS:power_state": 1, + "config_drive": "", + "metadata": {} + } + ] +} +` + +// SingleServerBody is the canned body of a Get request on an existing server. +const SingleServerBody = ` +{ + "server": { + "status": "ACTIVE", + "updated": "2014-09-25T13:04:49Z", + "hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362", + "OS-EXT-SRV-ATTR:host": "devstack", + "addresses": { + "private": [ + { + "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be", + "version": 4, + "addr": "10.0.0.31", + "OS-EXT-IPS:type": "fixed" + } + ] + }, + "links": [ + { + "href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "self" + }, + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "bookmark" + } + ], + "key_name": null, + "image": { + "id": "f90f6034-2570-4974-8351-6b49732ef2eb", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "rel": "bookmark" + } + ] + }, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "OS-EXT-SRV-ATTR:instance_name": "instance-0000001d", + "OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000", + "OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack", + "flavor": { + "id": "1", + "links": [ + { + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1", + "rel": "bookmark" + } + ] + }, + "id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "security_groups": [ + { + "name": "default" + } + ], + "OS-SRV-USG:terminated_at": null, + "OS-EXT-AZ:availability_zone": "nova", + "user_id": "9349aff8be7545ac9d2f1d00999a23cd", + "name": "derp", + "created": "2014-09-25T13:04:41Z", + "tenant_id": "fcad67a6189847c4aecfa3c81a05783b", + "OS-DCF:diskConfig": "MANUAL", + "os-extended-volumes:volumes_attached": [], + "accessIPv4": "", + "accessIPv6": "", + "progress": 0, + "OS-EXT-STS:power_state": 1, + "config_drive": "", + "metadata": {} + } +} +` + +var ( + // ServerHerp is a Server struct that should correspond to the first result in ServerListBody. + ServerHerp = Server{ + Status: "ACTIVE", + Updated: "2014-09-25T13:10:10Z", + HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362", + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b", + "version": float64(4), + "addr": "10.0.0.32", + "OS-EXT-IPS:type": "fixed", + }, + }, + }, + Links: []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + "rel": "self", + }, + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + "rel": "bookmark", + }, + }, + Image: map[string]interface{}{ + "id": "f90f6034-2570-4974-8351-6b49732ef2eb", + "links": []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "1", + "links": []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1", + "rel": "bookmark", + }, + }, + }, + ID: "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5", + UserID: "9349aff8be7545ac9d2f1d00999a23cd", + Name: "herp", + Created: "2014-09-25T13:10:02Z", + TenantID: "fcad67a6189847c4aecfa3c81a05783b", + Metadata: map[string]interface{}{}, + SecurityGroups: []map[string]interface{}{ + map[string]interface{}{ + "name": "default", + }, + }, + } + + // ServerDerp is a Server struct that should correspond to the second server in ServerListBody. + ServerDerp = Server{ + Status: "ACTIVE", + Updated: "2014-09-25T13:04:49Z", + HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362", + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be", + "version": float64(4), + "addr": "10.0.0.31", + "OS-EXT-IPS:type": "fixed", + }, + }, + }, + Links: []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "self", + }, + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba", + "rel": "bookmark", + }, + }, + Image: map[string]interface{}{ + "id": "f90f6034-2570-4974-8351-6b49732ef2eb", + "links": []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "1", + "links": []interface{}{ + map[string]interface{}{ + "href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1", + "rel": "bookmark", + }, + }, + }, + ID: "9e5476bd-a4ec-4653-93d6-72c93aa682ba", + UserID: "9349aff8be7545ac9d2f1d00999a23cd", + Name: "derp", + Created: "2014-09-25T13:04:41Z", + TenantID: "fcad67a6189847c4aecfa3c81a05783b", + Metadata: map[string]interface{}{}, + SecurityGroups: []map[string]interface{}{ + map[string]interface{}{ + "name": "default", + }, + }, + } +) + +// HandleServerCreationSuccessfully sets up the test server to respond to a server creation request +// with a given response. +func HandleServerCreationSuccessfully(t *testing.T, response string) { + th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "server": { + "name": "derp", + "imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb", + "flavorRef": "1" + } + }`) + + w.WriteHeader(http.StatusAccepted) + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, response) + }) +} + +// HandleServerListSuccessfully sets up the test server to respond to a server List request. +func HandleServerListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/detail", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, ServerListBody) + case "9e5476bd-a4ec-4653-93d6-72c93aa682ba": + fmt.Fprintf(w, `{ "servers": [] }`) + default: + t.Fatalf("/servers/detail invoked with unexpected marker=[%s]", marker) + } + }) +} + +// HandleServerDeletionSuccessfully sets up the test server to respond to a server deletion request. +func HandleServerDeletionSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/asdfasdfasdf", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleServerGetSuccessfully sets up the test server to respond to a server Get request. +func HandleServerGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + fmt.Fprintf(w, SingleServerBody) + }) +} + +// HandleServerUpdateSuccessfully sets up the test server to respond to a server Update request. +func HandleServerUpdateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, `{ "server": { "name": "new-name" } }`) + + fmt.Fprintf(w, SingleServerBody) + }) +} + +// HandleAdminPasswordChangeSuccessfully sets up the test server to respond to a server password +// change request. +func HandleAdminPasswordChangeSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ "changePassword": { "adminPass": "new-password" } }`) + + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleRebootSuccessfully sets up the test server to respond to a reboot request with success. +func HandleRebootSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ "reboot": { "type": "SOFT" } }`) + + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleRebuildSuccessfully sets up the test server to respond to a rebuild request with success. +func HandleRebuildSuccessfully(t *testing.T, response string) { + th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, ` + { + "rebuild": { + "name": "new-name", + "adminPass": "swordfish", + "imageRef": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb", + "accessIPv4": "1.2.3.4" + } + } + `) + + w.WriteHeader(http.StatusAccepted) + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, response) + }) +} + +// HandleServerRescueSuccessfully sets up the test server to respond to a server Rescue request. +func HandleServerRescueSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ "rescue": { "adminPass": "1234567890" } }`) + + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{ "adminPass": "1234567890" }`)) + }) +} + +// HandleMetadatumGetSuccessfully sets up the test server to respond to a metadatum Get request. +func HandleMetadatumGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(`{ "meta": {"foo":"bar"}}`)) + }) +} + +// HandleMetadatumCreateSuccessfully sets up the test server to respond to a metadatum Create request. +func HandleMetadatumCreateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "meta": { + "foo": "bar" + } + }`) + + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(`{ "meta": {"foo":"bar"}}`)) + }) +} + +// HandleMetadatumDeleteSuccessfully sets up the test server to respond to a metadatum Delete request. +func HandleMetadatumDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleMetadataGetSuccessfully sets up the test server to respond to a metadata Get request. +func HandleMetadataGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`)) + }) +} + +// HandleMetadataResetSuccessfully sets up the test server to respond to a metadata Create request. +func HandleMetadataResetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "metadata": { + "foo": "bar", + "this": "that" + } + }`) + + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`)) + }) +} + +// HandleMetadataUpdateSuccessfully sets up the test server to respond to a metadata Update request. +func HandleMetadataUpdateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "metadata": { + "foo": "baz", + "this": "those" + } + }`) + + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(`{ "metadata": {"foo":"baz", "this":"those"}}`)) + }) +} + +// ListAddressesExpected represents an expected repsonse from a ListAddresses request. +var ListAddressesExpected = map[string][]Address{ + "public": []Address{ + Address{ + Version: 4, + Address: "80.56.136.39", + }, + Address{ + Version: 6, + Address: "2001:4800:790e:510:be76:4eff:fe04:82a8", + }, + }, + "private": []Address{ + Address{ + Version: 4, + Address: "10.880.3.154", + }, + }, +} + +// HandleAddressListSuccessfully sets up the test server to respond to a ListAddresses request. +func HandleAddressListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/asdfasdfasdf/ips", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, `{ + "addresses": { + "public": [ + { + "version": 4, + "addr": "50.56.176.35" + }, + { + "version": 6, + "addr": "2001:4800:780e:510:be76:4eff:fe04:84a8" + } + ], + "private": [ + { + "version": 4, + "addr": "10.180.3.155" + } + ] + } + }`) + }) +} + +// ListNetworkAddressesExpected represents an expected repsonse from a ListAddressesByNetwork request. +var ListNetworkAddressesExpected = []Address{ + Address{ + Version: 4, + Address: "50.56.176.35", + }, + Address{ + Version: 6, + Address: "2001:4800:780e:510:be76:4eff:fe04:84a8", + }, +} + +// HandleNetworkAddressListSuccessfully sets up the test server to respond to a ListAddressesByNetwork request. +func HandleNetworkAddressListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/asdfasdfasdf/ips/public", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, `{ + "public": [ + { + "version": 4, + "addr": "50.56.176.35" + }, + { + "version": 6, + "addr": "2001:4800:780e:510:be76:4eff:fe04:84a8" + } + ] + }`) + }) +} + +// HandleCreateServerImageSuccessfully sets up the test server to respond to a TestCreateServerImage request. +func HandleCreateServerImageSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/servers/serverimage/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Location", "https://0.0.0.0/images/xxxx-xxxxx-xxxxx-xxxx") + w.WriteHeader(http.StatusAccepted) + }) +} + diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go new file mode 100644 index 000000000..f9839d9f2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go @@ -0,0 +1,852 @@ +package servers + +import ( + "encoding/base64" + "encoding/json" + "errors" + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" + "github.com/rackspace/gophercloud/openstack/compute/v2/images" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToServerListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the server attributes you want to see returned. Marker and Limit are used +// for pagination. +type ListOpts struct { + // A time/date stamp for when the server last changed status. + ChangesSince string `q:"changes-since"` + + // Name of the image in URL format. + Image string `q:"image"` + + // Name of the flavor in URL format. + Flavor string `q:"flavor"` + + // Name of the server as a string; can be queried with regular expressions. + // Realize that ?name=bob returns both bob and bobb. If you need to match bob + // only, you can use a regular expression matching the syntax of the + // underlying database server implemented for Compute. + Name string `q:"name"` + + // Value of the status of the server so that you can filter on "ACTIVE" for example. + Status string `q:"status"` + + // Name of the host as a string. + Host string `q:"host"` + + // UUID of the server at which you want to set a marker. + Marker string `q:"marker"` + + // Integer value for the limit of values to return. + Limit int `q:"limit"` + + // Bool to show all tenants + AllTenants bool `q:"all_tenants"` +} + +// ToServerListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToServerListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List makes a request against the API to list servers accessible to you. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listDetailURL(client) + + if opts != nil { + query, err := opts.ToServerListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPageFn := func(r pagination.PageResult) pagination.Page { + return ServerPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, url, createPageFn) +} + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. +// The CreateOpts struct in this package does. +type CreateOptsBuilder interface { + ToServerCreateMap() (map[string]interface{}, error) +} + +// Network is used within CreateOpts to control a new server's network attachments. +type Network struct { + // UUID of a nova-network to attach to the newly provisioned server. + // Required unless Port is provided. + UUID string + + // Port of a neutron network to attach to the newly provisioned server. + // Required unless UUID is provided. + Port string + + // FixedIP [optional] specifies a fixed IPv4 address to be used on this network. + FixedIP string +} + +// Personality is an array of files that are injected into the server at launch. +type Personality []*File + +// File is used within CreateOpts and RebuildOpts to inject a file into the server at launch. +// File implements the json.Marshaler interface, so when a Create or Rebuild operation is requested, +// json.Marshal will call File's MarshalJSON method. +type File struct { + // Path of the file + Path string + // Contents of the file. Maximum content size is 255 bytes. + Contents []byte +} + +// MarshalJSON marshals the escaped file, base64 encoding the contents. +func (f *File) MarshalJSON() ([]byte, error) { + file := struct { + Path string `json:"path"` + Contents string `json:"contents"` + }{ + Path: f.Path, + Contents: base64.StdEncoding.EncodeToString(f.Contents), + } + return json.Marshal(file) +} + +// CreateOpts specifies server creation parameters. +type CreateOpts struct { + // Name [required] is the name to assign to the newly launched server. + Name string + + // ImageRef [optional; required if ImageName is not provided] is the ID or full + // URL to the image that contains the server's OS and initial state. + // Also optional if using the boot-from-volume extension. + ImageRef string + + // ImageName [optional; required if ImageRef is not provided] is the name of the + // image that contains the server's OS and initial state. + // Also optional if using the boot-from-volume extension. + ImageName string + + // FlavorRef [optional; required if FlavorName is not provided] is the ID or + // full URL to the flavor that describes the server's specs. + FlavorRef string + + // FlavorName [optional; required if FlavorRef is not provided] is the name of + // the flavor that describes the server's specs. + FlavorName string + + // SecurityGroups [optional] lists the names of the security groups to which this server should belong. + SecurityGroups []string + + // UserData [optional] contains configuration information or scripts to use upon launch. + // Create will base64-encode it for you. + UserData []byte + + // AvailabilityZone [optional] in which to launch the server. + AvailabilityZone string + + // Networks [optional] dictates how this server will be attached to available networks. + // By default, the server will be attached to all isolated networks for the tenant. + Networks []Network + + // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server. + Metadata map[string]string + + // Personality [optional] includes files to inject into the server at launch. + // Create will base64-encode file contents for you. + Personality Personality + + // ConfigDrive [optional] enables metadata injection through a configuration drive. + ConfigDrive bool + + // AdminPass [optional] sets the root user password. If not set, a randomly-generated + // password will be created and returned in the response. + AdminPass string + + // AccessIPv4 [optional] specifies an IPv4 address for the instance. + AccessIPv4 string + + // AccessIPv6 [optional] specifies an IPv6 address for the instance. + AccessIPv6 string +} + +// ToServerCreateMap assembles a request body based on the contents of a CreateOpts. +func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) { + server := make(map[string]interface{}) + + server["name"] = opts.Name + server["imageRef"] = opts.ImageRef + server["imageName"] = opts.ImageName + server["flavorRef"] = opts.FlavorRef + server["flavorName"] = opts.FlavorName + + if opts.UserData != nil { + encoded := base64.StdEncoding.EncodeToString(opts.UserData) + server["user_data"] = &encoded + } + if opts.ConfigDrive { + server["config_drive"] = "true" + } + if opts.AvailabilityZone != "" { + server["availability_zone"] = opts.AvailabilityZone + } + if opts.Metadata != nil { + server["metadata"] = opts.Metadata + } + if opts.AdminPass != "" { + server["adminPass"] = opts.AdminPass + } + if opts.AccessIPv4 != "" { + server["accessIPv4"] = opts.AccessIPv4 + } + if opts.AccessIPv6 != "" { + server["accessIPv6"] = opts.AccessIPv6 + } + + if len(opts.SecurityGroups) > 0 { + securityGroups := make([]map[string]interface{}, len(opts.SecurityGroups)) + for i, groupName := range opts.SecurityGroups { + securityGroups[i] = map[string]interface{}{"name": groupName} + } + server["security_groups"] = securityGroups + } + + if len(opts.Networks) > 0 { + networks := make([]map[string]interface{}, len(opts.Networks)) + for i, net := range opts.Networks { + networks[i] = make(map[string]interface{}) + if net.UUID != "" { + networks[i]["uuid"] = net.UUID + } + if net.Port != "" { + networks[i]["port"] = net.Port + } + if net.FixedIP != "" { + networks[i]["fixed_ip"] = net.FixedIP + } + } + server["networks"] = networks + } + + if len(opts.Personality) > 0 { + server["personality"] = opts.Personality + } + + return map[string]interface{}{"server": server}, nil +} + +// Create requests a server to be provisioned to the user in the current tenant. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToServerCreateMap() + if err != nil { + res.Err = err + return res + } + + // If ImageRef isn't provided, use ImageName to ascertain the image ID. + if reqBody["server"].(map[string]interface{})["imageRef"].(string) == "" { + imageName := reqBody["server"].(map[string]interface{})["imageName"].(string) + if imageName == "" { + res.Err = errors.New("One and only one of ImageRef and ImageName must be provided.") + return res + } + imageID, err := images.IDFromName(client, imageName) + if err != nil { + res.Err = err + return res + } + reqBody["server"].(map[string]interface{})["imageRef"] = imageID + } + delete(reqBody["server"].(map[string]interface{}), "imageName") + + // If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID. + if reqBody["server"].(map[string]interface{})["flavorRef"].(string) == "" { + flavorName := reqBody["server"].(map[string]interface{})["flavorName"].(string) + if flavorName == "" { + res.Err = errors.New("One and only one of FlavorRef and FlavorName must be provided.") + return res + } + flavorID, err := flavors.IDFromName(client, flavorName) + if err != nil { + res.Err = err + return res + } + reqBody["server"].(map[string]interface{})["flavorRef"] = flavorID + } + delete(reqBody["server"].(map[string]interface{}), "flavorName") + + _, res.Err = client.Post(listURL(client), reqBody, &res.Body, nil) + return res +} + +// Delete requests that a server previously provisioned be removed from your account. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(deleteURL(client, id), nil) + return res +} + +// Get requests details on a single server, by ID. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var result GetResult + _, result.Err = client.Get(getURL(client, id), &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 203}, + }) + return result +} + +// UpdateOptsBuilder allows extensions to add additional attributes to the Update request. +type UpdateOptsBuilder interface { + ToServerUpdateMap() map[string]interface{} +} + +// UpdateOpts specifies the base attributes that may be updated on an existing server. +type UpdateOpts struct { + // Name [optional] changes the displayed name of the server. + // The server host name will *not* change. + // Server names are not constrained to be unique, even within the same tenant. + Name string + + // AccessIPv4 [optional] provides a new IPv4 address for the instance. + AccessIPv4 string + + // AccessIPv6 [optional] provides a new IPv6 address for the instance. + AccessIPv6 string +} + +// ToServerUpdateMap formats an UpdateOpts structure into a request body. +func (opts UpdateOpts) ToServerUpdateMap() map[string]interface{} { + server := make(map[string]string) + if opts.Name != "" { + server["name"] = opts.Name + } + if opts.AccessIPv4 != "" { + server["accessIPv4"] = opts.AccessIPv4 + } + if opts.AccessIPv6 != "" { + server["accessIPv6"] = opts.AccessIPv6 + } + return map[string]interface{}{"server": server} +} + +// Update requests that various attributes of the indicated server be changed. +func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var result UpdateResult + reqBody := opts.ToServerUpdateMap() + _, result.Err = client.Put(updateURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return result +} + +// ChangeAdminPassword alters the administrator or root password for a specified server. +func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) ActionResult { + var req struct { + ChangePassword struct { + AdminPass string `json:"adminPass"` + } `json:"changePassword"` + } + + req.ChangePassword.AdminPass = newPassword + + var res ActionResult + _, res.Err = client.Post(actionURL(client, id), req, nil, nil) + return res +} + +// ErrArgument errors occur when an argument supplied to a package function +// fails to fall within acceptable values. For example, the Reboot() function +// expects the "how" parameter to be one of HardReboot or SoftReboot. These +// constants are (currently) strings, leading someone to wonder if they can pass +// other string values instead, perhaps in an effort to break the API of their +// provider. Reboot() returns this error in this situation. +// +// Function identifies which function was called/which function is generating +// the error. +// Argument identifies which formal argument was responsible for producing the +// error. +// Value provides the value as it was passed into the function. +type ErrArgument struct { + Function, Argument string + Value interface{} +} + +// Error yields a useful diagnostic for debugging purposes. +func (e *ErrArgument) Error() string { + return fmt.Sprintf("Bad argument in call to %s, formal parameter %s, value %#v", e.Function, e.Argument, e.Value) +} + +func (e *ErrArgument) String() string { + return e.Error() +} + +// RebootMethod describes the mechanisms by which a server reboot can be requested. +type RebootMethod string + +// These constants determine how a server should be rebooted. +// See the Reboot() function for further details. +const ( + SoftReboot RebootMethod = "SOFT" + HardReboot RebootMethod = "HARD" + OSReboot = SoftReboot + PowerCycle = HardReboot +) + +// Reboot requests that a given server reboot. +// Two methods exist for rebooting a server: +// +// HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the machine, or if a VM, +// terminating it at the hypervisor level. +// It's done. Caput. Full stop. +// Then, after a brief while, power is restored or the VM instance restarted. +// +// SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures. +// E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine. +func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) ActionResult { + var res ActionResult + + if (how != SoftReboot) && (how != HardReboot) { + res.Err = &ErrArgument{ + Function: "Reboot", + Argument: "how", + Value: how, + } + return res + } + + reqBody := struct { + C map[string]string `json:"reboot"` + }{ + map[string]string{"type": string(how)}, + } + + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) + return res +} + +// RebuildOptsBuilder is an interface that allows extensions to override the +// default behaviour of rebuild options +type RebuildOptsBuilder interface { + ToServerRebuildMap() (map[string]interface{}, error) +} + +// RebuildOpts represents the configuration options used in a server rebuild +// operation +type RebuildOpts struct { + // Required. The ID of the image you want your server to be provisioned on + ImageID string + + // Name to set the server to + Name string + + // Required. The server's admin password + AdminPass string + + // AccessIPv4 [optional] provides a new IPv4 address for the instance. + AccessIPv4 string + + // AccessIPv6 [optional] provides a new IPv6 address for the instance. + AccessIPv6 string + + // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server. + Metadata map[string]string + + // Personality [optional] includes files to inject into the server at launch. + // Rebuild will base64-encode file contents for you. + Personality Personality +} + +// ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON +func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) { + var err error + server := make(map[string]interface{}) + + if opts.AdminPass == "" { + err = fmt.Errorf("AdminPass is required") + } + + if opts.ImageID == "" { + err = fmt.Errorf("ImageID is required") + } + + if err != nil { + return server, err + } + + server["name"] = opts.Name + server["adminPass"] = opts.AdminPass + server["imageRef"] = opts.ImageID + + if opts.AccessIPv4 != "" { + server["accessIPv4"] = opts.AccessIPv4 + } + + if opts.AccessIPv6 != "" { + server["accessIPv6"] = opts.AccessIPv6 + } + + if opts.Metadata != nil { + server["metadata"] = opts.Metadata + } + + if len(opts.Personality) > 0 { + server["personality"] = opts.Personality + } + + return map[string]interface{}{"rebuild": server}, nil +} + +// Rebuild will reprovision the server according to the configuration options +// provided in the RebuildOpts struct. +func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) RebuildResult { + var result RebuildResult + + if id == "" { + result.Err = fmt.Errorf("ID is required") + return result + } + + reqBody, err := opts.ToServerRebuildMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, nil) + return result +} + +// ResizeOptsBuilder is an interface that allows extensions to override the default structure of +// a Resize request. +type ResizeOptsBuilder interface { + ToServerResizeMap() (map[string]interface{}, error) +} + +// ResizeOpts represents the configuration options used to control a Resize operation. +type ResizeOpts struct { + // FlavorRef is the ID of the flavor you wish your server to become. + FlavorRef string +} + +// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON request body for the +// Resize request. +func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) { + resize := map[string]interface{}{ + "flavorRef": opts.FlavorRef, + } + + return map[string]interface{}{"resize": resize}, nil +} + +// Resize instructs the provider to change the flavor of the server. +// Note that this implies rebuilding it. +// Unfortunately, one cannot pass rebuild parameters to the resize function. +// When the resize completes, the server will be in RESIZE_VERIFY state. +// While in this state, you can explore the use of the new server's configuration. +// If you like it, call ConfirmResize() to commit the resize permanently. +// Otherwise, call RevertResize() to restore the old configuration. +func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) ActionResult { + var res ActionResult + reqBody, err := opts.ToServerResizeMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) + return res +} + +// ConfirmResize confirms a previous resize operation on a server. +// See Resize() for more details. +func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult { + var res ActionResult + + reqBody := map[string]interface{}{"confirmResize": nil} + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ + OkCodes: []int{201, 202, 204}, + }) + return res +} + +// RevertResize cancels a previous resize operation on a server. +// See Resize() for more details. +func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult { + var res ActionResult + reqBody := map[string]interface{}{"revertResize": nil} + _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) + return res +} + +// RescueOptsBuilder is an interface that allows extensions to override the +// default structure of a Rescue request. +type RescueOptsBuilder interface { + ToServerRescueMap() (map[string]interface{}, error) +} + +// RescueOpts represents the configuration options used to control a Rescue +// option. +type RescueOpts struct { + // AdminPass is the desired administrative password for the instance in + // RESCUE mode. If it's left blank, the server will generate a password. + AdminPass string +} + +// ToServerRescueMap formats a RescueOpts as a map that can be used as a JSON +// request body for the Rescue request. +func (opts RescueOpts) ToServerRescueMap() (map[string]interface{}, error) { + server := make(map[string]interface{}) + if opts.AdminPass != "" { + server["adminPass"] = opts.AdminPass + } + return map[string]interface{}{"rescue": server}, nil +} + +// Rescue instructs the provider to place the server into RESCUE mode. +func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) RescueResult { + var result RescueResult + + if id == "" { + result.Err = fmt.Errorf("ID is required") + return result + } + reqBody, err := opts.ToServerRescueMap() + if err != nil { + result.Err = err + return result + } + + _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return result +} + +// ResetMetadataOptsBuilder allows extensions to add additional parameters to the +// Reset request. +type ResetMetadataOptsBuilder interface { + ToMetadataResetMap() (map[string]interface{}, error) +} + +// MetadataOpts is a map that contains key-value pairs. +type MetadataOpts map[string]string + +// ToMetadataResetMap assembles a body for a Reset request based on the contents of a MetadataOpts. +func (opts MetadataOpts) ToMetadataResetMap() (map[string]interface{}, error) { + return map[string]interface{}{"metadata": opts}, nil +} + +// ToMetadataUpdateMap assembles a body for an Update request based on the contents of a MetadataOpts. +func (opts MetadataOpts) ToMetadataUpdateMap() (map[string]interface{}, error) { + return map[string]interface{}{"metadata": opts}, nil +} + +// ResetMetadata will create multiple new key-value pairs for the given server ID. +// Note: Using this operation will erase any already-existing metadata and create +// the new metadata provided. To keep any already-existing metadata, use the +// UpdateMetadatas or UpdateMetadata function. +func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) ResetMetadataResult { + var res ResetMetadataResult + metadata, err := opts.ToMetadataResetMap() + if err != nil { + res.Err = err + return res + } + _, res.Err = client.Put(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Metadata requests all the metadata for the given server ID. +func Metadata(client *gophercloud.ServiceClient, id string) GetMetadataResult { + var res GetMetadataResult + _, res.Err = client.Get(metadataURL(client, id), &res.Body, nil) + return res +} + +// UpdateMetadataOptsBuilder allows extensions to add additional parameters to the +// Create request. +type UpdateMetadataOptsBuilder interface { + ToMetadataUpdateMap() (map[string]interface{}, error) +} + +// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID. +// This operation does not affect already-existing metadata that is not specified +// by opts. +func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult { + var res UpdateMetadataResult + metadata, err := opts.ToMetadataUpdateMap() + if err != nil { + res.Err = err + return res + } + _, res.Err = client.Post(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// MetadatumOptsBuilder allows extensions to add additional parameters to the +// Create request. +type MetadatumOptsBuilder interface { + ToMetadatumCreateMap() (map[string]interface{}, string, error) +} + +// MetadatumOpts is a map of length one that contains a key-value pair. +type MetadatumOpts map[string]string + +// ToMetadatumCreateMap assembles a body for a Create request based on the contents of a MetadataumOpts. +func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) { + if len(opts) != 1 { + return nil, "", errors.New("CreateMetadatum operation must have 1 and only 1 key-value pair.") + } + metadatum := map[string]interface{}{"meta": opts} + var key string + for k := range metadatum["meta"].(MetadatumOpts) { + key = k + } + return metadatum, key, nil +} + +// CreateMetadatum will create or update the key-value pair with the given key for the given server ID. +func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts MetadatumOptsBuilder) CreateMetadatumResult { + var res CreateMetadatumResult + metadatum, key, err := opts.ToMetadatumCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Put(metadatumURL(client, id, key), metadatum, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Metadatum requests the key-value pair with the given key for the given server ID. +func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumResult { + var res GetMetadatumResult + _, res.Err = client.Request("GET", metadatumURL(client, id, key), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + }) + return res +} + +// DeleteMetadatum will delete the key-value pair with the given key for the given server ID. +func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) DeleteMetadatumResult { + var res DeleteMetadatumResult + _, res.Err = client.Delete(metadatumURL(client, id, key), nil) + return res +} + +// ListAddresses makes a request against the API to list the servers IP addresses. +func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return AddressPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, listAddressesURL(client, id), createPageFn) +} + +// ListAddressesByNetwork makes a request against the API to list the servers IP addresses +// for the given network. +func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return NetworkAddressPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), createPageFn) +} + +type CreateImageOpts struct { + // Name [required] of the image/snapshot + Name string + // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the created image. + Metadata map[string]string +} + +type CreateImageOptsBuilder interface { + ToServerCreateImageMap() (map[string]interface{}, error) +} + +// ToServerCreateImageMap formats a CreateImageOpts structure into a request body. +func (opts CreateImageOpts) ToServerCreateImageMap() (map[string]interface{}, error) { + var err error + img := make(map[string]interface{}) + if opts.Name == "" { + return nil, fmt.Errorf("Cannot create a server image without a name") + } + img["name"] = opts.Name + if opts.Metadata != nil { + img["metadata"] = opts.Metadata + } + createImage := make(map[string]interface{}) + createImage["createImage"] = img + return createImage, err +} + +// CreateImage makes a request against the nova API to schedule an image to be created of the server +func CreateImage(client *gophercloud.ServiceClient, serverId string, opts CreateImageOptsBuilder) CreateImageResult { + var res CreateImageResult + reqBody, err := opts.ToServerCreateImageMap() + if err != nil { + res.Err = err + return res + } + response, err := client.Post(actionURL(client, serverId), reqBody, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + res.Err = err + res.Header = response.Header + return res +} + +// IDFromName is a convienience function that returns a server's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + serverCount := 0 + serverID := "" + if name == "" { + return "", fmt.Errorf("A server name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + serverList, err := ExtractServers(page) + if err != nil { + return false, err + } + + for _, s := range serverList { + if s.Name == name { + serverCount++ + serverID = s.ID + } + } + return true, nil + }) + + switch serverCount { + case 0: + return "", fmt.Errorf("Unable to find server: %s", name) + case 1: + return serverID, nil + default: + return "", fmt.Errorf("Found %d servers matching %s", serverCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go new file mode 100644 index 000000000..f27870984 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go @@ -0,0 +1,372 @@ +package servers + +import ( + "reflect" + "fmt" + "path" + "net/url" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type serverResult struct { + gophercloud.Result +} + +// Extract interprets any serverResult as a Server, if possible. +func (r serverResult) Extract() (*Server, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Server Server `mapstructure:"server"` + } + + config := &mapstructure.DecoderConfig{ + DecodeHook: toMapFromString, + Result: &response, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + + err = decoder.Decode(r.Body) + if err != nil { + return nil, err + } + + return &response.Server, nil +} + +// CreateResult temporarily contains the response from a Create call. +type CreateResult struct { + serverResult +} + +// GetResult temporarily contains the response from a Get call. +type GetResult struct { + serverResult +} + +// UpdateResult temporarily contains the response from an Update call. +type UpdateResult struct { + serverResult +} + +// DeleteResult temporarily contains the response from a Delete call. +type DeleteResult struct { + gophercloud.ErrResult +} + +// RebuildResult temporarily contains the response from a Rebuild call. +type RebuildResult struct { + serverResult +} + +// ActionResult represents the result of server action operations, like reboot +type ActionResult struct { + gophercloud.ErrResult +} + +// RescueResult represents the result of a server rescue operation +type RescueResult struct { + ActionResult +} + +// CreateImageResult represents the result of an image creation operation +type CreateImageResult struct { + gophercloud.Result +} + +// ExtractImageID gets the ID of the newly created server image from the header +func (res CreateImageResult) ExtractImageID() (string, error) { + if res.Err != nil { + return "", res.Err + } + // Get the image id from the header + u, err := url.ParseRequestURI(res.Header.Get("Location")) + if err != nil { + return "", fmt.Errorf("Failed to parse the image id: %s", err.Error()) + } + imageId := path.Base(u.Path) + if imageId == "." || imageId == "/" { + return "", fmt.Errorf("Failed to parse the ID of newly created image: %s", u) + } + return imageId, nil +} + +// Extract interprets any RescueResult as an AdminPass, if possible. +func (r RescueResult) Extract() (string, error) { + if r.Err != nil { + return "", r.Err + } + + var response struct { + AdminPass string `mapstructure:"adminPass"` + } + + err := mapstructure.Decode(r.Body, &response) + return response.AdminPass, err +} + +// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account. +type Server struct { + // ID uniquely identifies this server amongst all other servers, including those not accessible to the current tenant. + ID string + + // TenantID identifies the tenant owning this server resource. + TenantID string `mapstructure:"tenant_id"` + + // UserID uniquely identifies the user account owning the tenant. + UserID string `mapstructure:"user_id"` + + // Name contains the human-readable name for the server. + Name string + + // Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created. + Updated string + Created string + + HostID string + + // Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE. + Status string + + // Progress ranges from 0..100. + // A request made against the server completes only once Progress reaches 100. + Progress int + + // AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration. + AccessIPv4, AccessIPv6 string + + // Image refers to a JSON object, which itself indicates the OS image used to deploy the server. + Image map[string]interface{} + + // Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server. + Flavor map[string]interface{} + + // Addresses includes a list of all IP addresses assigned to the server, keyed by pool. + Addresses map[string]interface{} + + // Metadata includes a list of all user-specified key-value pairs attached to the server. + Metadata map[string]interface{} + + // Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference. + Links []interface{} + + // KeyName indicates which public key was injected into the server on launch. + KeyName string `json:"key_name" mapstructure:"key_name"` + + // AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place. + // Note that this is the ONLY time this field will be valid. + AdminPass string `json:"adminPass" mapstructure:"adminPass"` + + // SecurityGroups includes the security groups that this instance has applied to it + SecurityGroups []map[string]interface{} `json:"security_groups" mapstructure:"security_groups"` +} + +// ServerPage abstracts the raw results of making a List() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the +// data provided through the ExtractServers call. +type ServerPage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if a page contains no Server results. +func (page ServerPage) IsEmpty() (bool, error) { + servers, err := ExtractServers(page) + if err != nil { + return true, err + } + return len(servers) == 0, nil +} + +// NextPageURL uses the response's embedded link reference to navigate to the next page of results. +func (page ServerPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"servers_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities. +func ExtractServers(page pagination.Page) ([]Server, error) { + casted := page.(ServerPage).Body + + var response struct { + Servers []Server `mapstructure:"servers"` + } + + config := &mapstructure.DecoderConfig{ + DecodeHook: toMapFromString, + Result: &response, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + + err = decoder.Decode(casted) + + return response.Servers, err +} + +// MetadataResult contains the result of a call for (potentially) multiple key-value pairs. +type MetadataResult struct { + gophercloud.Result +} + +// GetMetadataResult temporarily contains the response from a metadata Get call. +type GetMetadataResult struct { + MetadataResult +} + +// ResetMetadataResult temporarily contains the response from a metadata Reset call. +type ResetMetadataResult struct { + MetadataResult +} + +// UpdateMetadataResult temporarily contains the response from a metadata Update call. +type UpdateMetadataResult struct { + MetadataResult +} + +// MetadatumResult contains the result of a call for individual a single key-value pair. +type MetadatumResult struct { + gophercloud.Result +} + +// GetMetadatumResult temporarily contains the response from a metadatum Get call. +type GetMetadatumResult struct { + MetadatumResult +} + +// CreateMetadatumResult temporarily contains the response from a metadatum Create call. +type CreateMetadatumResult struct { + MetadatumResult +} + +// DeleteMetadatumResult temporarily contains the response from a metadatum Delete call. +type DeleteMetadatumResult struct { + gophercloud.ErrResult +} + +// Extract interprets any MetadataResult as a Metadata, if possible. +func (r MetadataResult) Extract() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Metadata map[string]string `mapstructure:"metadata"` + } + + err := mapstructure.Decode(r.Body, &response) + return response.Metadata, err +} + +// Extract interprets any MetadatumResult as a Metadatum, if possible. +func (r MetadatumResult) Extract() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Metadatum map[string]string `mapstructure:"meta"` + } + + err := mapstructure.Decode(r.Body, &response) + return response.Metadatum, err +} + +func toMapFromString(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) { + if (from == reflect.String) && (to == reflect.Map) { + return map[string]interface{}{}, nil + } + return data, nil +} + +// Address represents an IP address. +type Address struct { + Version int `mapstructure:"version"` + Address string `mapstructure:"addr"` +} + +// AddressPage abstracts the raw results of making a ListAddresses() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned +// to the client, you may only safely access the data provided through the ExtractAddresses call. +type AddressPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if an AddressPage contains no networks. +func (r AddressPage) IsEmpty() (bool, error) { + addresses, err := ExtractAddresses(r) + if err != nil { + return true, err + } + return len(addresses) == 0, nil +} + +// ExtractAddresses interprets the results of a single page from a ListAddresses() call, +// producing a map of addresses. +func ExtractAddresses(page pagination.Page) (map[string][]Address, error) { + casted := page.(AddressPage).Body + + var response struct { + Addresses map[string][]Address `mapstructure:"addresses"` + } + + err := mapstructure.Decode(casted, &response) + if err != nil { + return nil, err + } + + return response.Addresses, err +} + +// NetworkAddressPage abstracts the raw results of making a ListAddressesByNetwork() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned +// to the client, you may only safely access the data provided through the ExtractAddresses call. +type NetworkAddressPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a NetworkAddressPage contains no addresses. +func (r NetworkAddressPage) IsEmpty() (bool, error) { + addresses, err := ExtractNetworkAddresses(r) + if err != nil { + return true, err + } + return len(addresses) == 0, nil +} + +// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call, +// producing a slice of addresses. +func ExtractNetworkAddresses(page pagination.Page) ([]Address, error) { + casted := page.(NetworkAddressPage).Body + + var response map[string][]Address + err := mapstructure.Decode(casted, &response) + if err != nil { + return nil, err + } + + var key string + for k := range response { + key = k + } + + return response[key], err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go new file mode 100644 index 000000000..899835493 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go @@ -0,0 +1,47 @@ +package servers + +import "github.com/rackspace/gophercloud" + +func createURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("servers") +} + +func listURL(client *gophercloud.ServiceClient) string { + return createURL(client) +} + +func listDetailURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("servers", "detail") +} + +func deleteURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("servers", id) +} + +func getURL(client *gophercloud.ServiceClient, id string) string { + return deleteURL(client, id) +} + +func updateURL(client *gophercloud.ServiceClient, id string) string { + return deleteURL(client, id) +} + +func actionURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("servers", id, "action") +} + +func metadatumURL(client *gophercloud.ServiceClient, id, key string) string { + return client.ServiceURL("servers", id, "metadata", key) +} + +func metadataURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("servers", id, "metadata") +} + +func listAddressesURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("servers", id, "ips") +} + +func listAddressesByNetworkURL(client *gophercloud.ServiceClient, id, network string) string { + return client.ServiceURL("servers", id, "ips", network) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go new file mode 100644 index 000000000..e6baf7416 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go @@ -0,0 +1,20 @@ +package servers + +import "github.com/rackspace/gophercloud" + +// WaitForStatus will continually poll a server until it successfully transitions to a specified +// status. It will do this for at most the number of seconds specified. +func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error { + return gophercloud.WaitFor(secs, func() (bool, error) { + current, err := Get(c, id).Extract() + if err != nil { + return false, err + } + + if current.Status == status { + return true, nil + } + + return false, nil + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/doc.go new file mode 100644 index 000000000..45b9cfb4e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/doc.go @@ -0,0 +1,11 @@ +// Package configurations provides information and interaction with the +// configuration API resource in the Rackspace Database service. +// +// A configuration group is a collection of key/value pairs which define how a +// particular database operates. These key/value pairs are specific to each +// datastore type and serve like settings. Some directives are capable of being +// applied dynamically, while other directives require a server restart to take +// effect. The configuration group can be applied to an instance at creation or +// applied to an existing instance to modify the behavior of the running +// datastore on the instance. +package configurations diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go new file mode 100644 index 000000000..ae6541615 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/fixtures.go @@ -0,0 +1,157 @@ +package configurations + +import ( + "fmt" + "time" +) + +var ( + timestamp = "2015-11-12T14:22:42Z" + timeVal, _ = time.Parse(time.RFC3339, timestamp) +) + +var singleConfigJSON = ` +{ + "created": "` + timestamp + `", + "datastore_name": "mysql", + "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb", + "datastore_version_name": "5.6", + "description": "example_description", + "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + "name": "example-configuration-name", + "updated": "` + timestamp + `" +} +` + +var singleConfigWithValuesJSON = ` +{ + "created": "` + timestamp + `", + "datastore_name": "mysql", + "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb", + "datastore_version_name": "5.6", + "description": "example description", + "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + "instance_count": 0, + "name": "example-configuration-name", + "updated": "` + timestamp + `", + "values": { + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120 + } +} +` + +var ( + ListConfigsJSON = fmt.Sprintf(`{"configurations": [%s]}`, singleConfigJSON) + GetConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigJSON) + CreateConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigWithValuesJSON) +) + +var CreateReq = ` +{ + "configuration": { + "datastore": { + "type": "a00000a0-00a0-0a00-00a0-000a000000aa", + "version": "b00000b0-00b0-0b00-00b0-000b000000bb" + }, + "description": "example description", + "name": "example-configuration-name", + "values": { + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120 + } + } +} +` + +var UpdateReq = ` +{ + "configuration": { + "values": { + "connect_timeout": 300 + } + } +} +` + +var ListInstancesJSON = ` +{ + "instances": [ + { + "id": "d4603f69-ec7e-4e9b-803f-600b9205576f", + "name": "json_rack_instance" + } + ] +} +` + +var ListParamsJSON = ` +{ + "configuration-parameters": [ + { + "max": 1, + "min": 0, + "name": "innodb_file_per_table", + "restart_required": true, + "type": "integer" + }, + { + "max": 4294967296, + "min": 0, + "name": "key_buffer_size", + "restart_required": false, + "type": "integer" + }, + { + "max": 65535, + "min": 2, + "name": "connect_timeout", + "restart_required": false, + "type": "integer" + }, + { + "max": 4294967296, + "min": 0, + "name": "join_buffer_size", + "restart_required": false, + "type": "integer" + } + ] +} +` + +var GetParamJSON = ` +{ + "max": 1, + "min": 0, + "name": "innodb_file_per_table", + "restart_required": true, + "type": "integer" +} +` + +var ExampleConfig = Config{ + Created: timeVal, + DatastoreName: "mysql", + DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb", + DatastoreVersionName: "5.6", + Description: "example_description", + ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + Name: "example-configuration-name", + Updated: timeVal, +} + +var ExampleConfigWithValues = Config{ + Created: timeVal, + DatastoreName: "mysql", + DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb", + DatastoreVersionName: "5.6", + Description: "example description", + ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + Name: "example-configuration-name", + Updated: timeVal, + Values: map[string]interface{}{ + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120, + }, +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go new file mode 100644 index 000000000..83c710206 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/requests.go @@ -0,0 +1,287 @@ +package configurations + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/instances" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all of the available configurations. +func List(client *gophercloud.ServiceClient) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return ConfigPage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, baseURL(client), pageFn) +} + +// CreateOptsBuilder is a top-level interface which renders a JSON map. +type CreateOptsBuilder interface { + ToConfigCreateMap() (map[string]interface{}, error) +} + +// DatastoreOpts is the primary options struct for creating and modifying +// how configuration resources are associated with datastores. +type DatastoreOpts struct { + // [OPTIONAL] The type of datastore. Defaults to "MySQL". + Type string + + // [OPTIONAL] The specific version of a datastore. Defaults to "5.6". + Version string +} + +// ToMap renders a JSON map for a datastore setting. +func (opts DatastoreOpts) ToMap() (map[string]string, error) { + datastore := map[string]string{} + + if opts.Type != "" { + datastore["type"] = opts.Type + } + + if opts.Version != "" { + datastore["version"] = opts.Version + } + + return datastore, nil +} + +// CreateOpts is the struct responsible for configuring new configurations. +type CreateOpts struct { + // [REQUIRED] The configuration group name + Name string + + // [REQUIRED] A map of user-defined configuration settings that will define + // how each associated datastore works. Each key/value pair is specific to a + // datastore type. + Values map[string]interface{} + + // [OPTIONAL] Associates the configuration group with a particular datastore. + Datastore *DatastoreOpts + + // [OPTIONAL] A human-readable explanation for the group. + Description string +} + +// ToConfigCreateMap casts a CreateOpts struct into a JSON map. +func (opts CreateOpts) ToConfigCreateMap() (map[string]interface{}, error) { + if opts.Name == "" { + return nil, errors.New("Name is a required field") + } + if len(opts.Values) == 0 { + return nil, errors.New("Values must be a populated map") + } + + config := map[string]interface{}{ + "name": opts.Name, + "values": opts.Values, + } + + if opts.Datastore != nil { + ds, err := opts.Datastore.ToMap() + if err != nil { + return config, err + } + config["datastore"] = ds + } + + if opts.Description != "" { + config["description"] = opts.Description + } + + return map[string]interface{}{"configuration": config}, nil +} + +// Create will create a new configuration group. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToConfigCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONBody: &reqBody, + JSONResponse: &res.Body, + }) + + return res +} + +// Get will retrieve the details for a specified configuration group. +func Get(client *gophercloud.ServiceClient, configID string) GetResult { + var res GetResult + + _, res.Err = client.Request("GET", resourceURL(client, configID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONResponse: &res.Body, + }) + + return res +} + +// UpdateOptsBuilder is the top-level interface for casting update options into +// JSON maps. +type UpdateOptsBuilder interface { + ToConfigUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the struct responsible for modifying existing configurations. +type UpdateOpts struct { + // [OPTIONAL] The configuration group name + Name string + + // [OPTIONAL] A map of user-defined configuration settings that will define + // how each associated datastore works. Each key/value pair is specific to a + // datastore type. + Values map[string]interface{} + + // [OPTIONAL] Associates the configuration group with a particular datastore. + Datastore *DatastoreOpts + + // [OPTIONAL] A human-readable explanation for the group. + Description string +} + +// ToConfigUpdateMap will cast an UpdateOpts struct into a JSON map. +func (opts UpdateOpts) ToConfigUpdateMap() (map[string]interface{}, error) { + config := map[string]interface{}{} + + if opts.Name != "" { + config["name"] = opts.Name + } + + if opts.Description != "" { + config["description"] = opts.Description + } + + if opts.Datastore != nil { + ds, err := opts.Datastore.ToMap() + if err != nil { + return config, err + } + config["datastore"] = ds + } + + if len(opts.Values) > 0 { + config["values"] = opts.Values + } + + return map[string]interface{}{"configuration": config}, nil +} + +// Update will modify an existing configuration group by performing a merge +// between new and existing values. If the key already exists, the new value +// will overwrite. All other keys will remain unaffected. +func Update(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToConfigUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("PATCH", resourceURL(client, configID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONBody: &reqBody, + }) + + return res +} + +// Replace will modify an existing configuration group by overwriting the +// entire parameter group with the new values provided. Any existing keys not +// included in UpdateOptsBuilder will be deleted. +func Replace(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) ReplaceResult { + var res ReplaceResult + + reqBody, err := opts.ToConfigUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("PUT", resourceURL(client, configID), gophercloud.RequestOpts{ + OkCodes: []int{202}, + JSONBody: &reqBody, + }) + + return res +} + +// Delete will permanently delete a configuration group. Please note that +// config groups cannot be deleted whilst still attached to running instances - +// you must detach and then delete them. +func Delete(client *gophercloud.ServiceClient, configID string) DeleteResult { + var res DeleteResult + + _, res.Err = client.Request("DELETE", resourceURL(client, configID), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} + +// ListInstances will list all the instances associated with a particular +// configuration group. +func ListInstances(client *gophercloud.ServiceClient, configID string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return instances.InstancePage{pagination.LinkedPageBase{PageResult: r}} + } + return pagination.NewPager(client, instancesURL(client, configID), pageFn) +} + +// ListDatastoreParams will list all the available and supported parameters +// that can be used for a particular datastore ID and a particular version. +// For example, if you are wondering how you can configure a MySQL 5.6 instance, +// you can use this operation (you will need to retrieve the MySQL datastore ID +// by using the datastores API). +func ListDatastoreParams(client *gophercloud.ServiceClient, datastoreID, versionID string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return ParamPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, listDSParamsURL(client, datastoreID, versionID), pageFn) +} + +// GetDatastoreParam will retrieve information about a specific configuration +// parameter. For example, you can use this operation to understand more about +// "innodb_file_per_table" configuration param for MySQL datastores. You will +// need the param's ID first, which can be attained by using the ListDatastoreParams +// operation. +func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) ParamResult { + var res ParamResult + + _, res.Err = client.Request("GET", getDSParamURL(client, datastoreID, versionID, paramID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONResponse: &res.Body, + }) + + return res +} + +// ListGlobalParams is similar to ListDatastoreParams but does not require a +// DatastoreID. +func ListGlobalParams(client *gophercloud.ServiceClient, versionID string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return ParamPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, listGlobalParamsURL(client, versionID), pageFn) +} + +// GetGlobalParam is similar to GetDatastoreParam but does not require a +// DatastoreID. +func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) ParamResult { + var res ParamResult + + _, res.Err = client.Request("GET", getGlobalParamURL(client, versionID, paramID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONResponse: &res.Body, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go new file mode 100644 index 000000000..d0d1d6e99 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/results.go @@ -0,0 +1,197 @@ +package configurations + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Config represents a configuration group API resource. +type Config struct { + Created time.Time `mapstructure:"-"` + Updated time.Time `mapstructure:"-"` + DatastoreName string `mapstructure:"datastore_name"` + DatastoreVersionID string `mapstructure:"datastore_version_id"` + DatastoreVersionName string `mapstructure:"datastore_version_name"` + Description string + ID string + Name string + Values map[string]interface{} +} + +// ConfigPage contains a page of Config resources in a paginated collection. +type ConfigPage struct { + pagination.SinglePageBase +} + +// IsEmpty indicates whether a ConfigPage is empty. +func (r ConfigPage) IsEmpty() (bool, error) { + is, err := ExtractConfigs(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractConfigs will retrieve a slice of Config structs from a page. +func ExtractConfigs(page pagination.Page) ([]Config, error) { + casted := page.(ConfigPage).Body + + var resp struct { + Configs []Config `mapstructure:"configurations" json:"configurations"` + } + + if err := mapstructure.Decode(casted, &resp); err != nil { + return nil, err + } + + var vals []interface{} + switch casted.(type) { + case map[string]interface{}: + vals = casted.(map[string]interface{})["configurations"].([]interface{}) + case map[string][]interface{}: + vals = casted.(map[string][]interface{})["configurations"] + default: + return resp.Configs, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, v := range vals { + val := v.(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Configs, err + } + resp.Configs[i].Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Configs, err + } + resp.Configs[i].Updated = updatedTime + } + } + + return resp.Configs, nil +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will retrieve a Config resource from an operation result. +func (r commonResult) Extract() (*Config, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Config Config `mapstructure:"configuration"` + } + + err := mapstructure.Decode(r.Body, &response) + val := r.Body.(map[string]interface{})["configuration"].(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Config, err + } + response.Config.Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Config, err + } + response.Config.Updated = updatedTime + } + + return &response.Config, err +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + commonResult +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + commonResult +} + +// UpdateResult represents the result of an Update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// ReplaceResult represents the result of a Replace operation. +type ReplaceResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Param represents a configuration parameter API resource. +type Param struct { + Max int + Min int + Name string + RestartRequired bool `mapstructure:"restart_required" json:"restart_required"` + Type string +} + +// ParamPage contains a page of Param resources in a paginated collection. +type ParamPage struct { + pagination.SinglePageBase +} + +// IsEmpty indicates whether a ParamPage is empty. +func (r ParamPage) IsEmpty() (bool, error) { + is, err := ExtractParams(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractParams will retrieve a slice of Param structs from a page. +func ExtractParams(page pagination.Page) ([]Param, error) { + casted := page.(ParamPage).Body + + var resp struct { + Params []Param `mapstructure:"configuration-parameters" json:"configuration-parameters"` + } + + err := mapstructure.Decode(casted, &resp) + return resp.Params, err +} + +// ParamResult represents the result of an operation which retrieves details +// about a particular configuration param. +type ParamResult struct { + gophercloud.Result +} + +// Extract will retrieve a param from an operation result. +func (r ParamResult) Extract() (*Param, error) { + if r.Err != nil { + return nil, r.Err + } + + var param Param + + err := mapstructure.Decode(r.Body, ¶m) + return ¶m, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go new file mode 100644 index 000000000..abea96158 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/configurations/urls.go @@ -0,0 +1,31 @@ +package configurations + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("configurations") +} + +func resourceURL(c *gophercloud.ServiceClient, configID string) string { + return c.ServiceURL("configurations", configID) +} + +func instancesURL(c *gophercloud.ServiceClient, configID string) string { + return c.ServiceURL("configurations", configID, "instances") +} + +func listDSParamsURL(c *gophercloud.ServiceClient, datastoreID, versionID string) string { + return c.ServiceURL("datastores", datastoreID, "versions", versionID, "parameters") +} + +func getDSParamURL(c *gophercloud.ServiceClient, datastoreID, versionID, paramID string) string { + return c.ServiceURL("datastores", datastoreID, "versions", versionID, "parameters", paramID) +} + +func listGlobalParamsURL(c *gophercloud.ServiceClient, versionID string) string { + return c.ServiceURL("datastores", "versions", versionID, "parameters") +} + +func getGlobalParamURL(c *gophercloud.ServiceClient, versionID, paramID string) string { + return c.ServiceURL("datastores", "versions", versionID, "parameters", paramID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/doc.go new file mode 100644 index 000000000..15275fe5d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/doc.go @@ -0,0 +1,6 @@ +// Package flavors provides information and interaction with the database API +// resource in the OpenStack Database service. +// +// A database, when referred to here, refers to the database engine running on +// an instance. +package databases diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/fixtures.go new file mode 100644 index 000000000..3e677211b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/fixtures.go @@ -0,0 +1,61 @@ +package databases + +import ( + "testing" + + "github.com/rackspace/gophercloud/testhelper/fixture" +) + +var ( + instanceID = "{instanceID}" + resURL = "/instances/" + instanceID + "/databases" +) + +var createDBsReq = ` +{ + "databases": [ + { + "character_set": "utf8", + "collate": "utf8_general_ci", + "name": "testingdb" + }, + { + "name": "sampledb" + } + ] +} +` + +var listDBsResp = ` +{ + "databases": [ + { + "name": "anotherexampledb" + }, + { + "name": "exampledb" + }, + { + "name": "nextround" + }, + { + "name": "sampledb" + }, + { + "name": "testingdb" + } + ] +} +` + +func HandleCreate(t *testing.T) { + fixture.SetupHandler(t, resURL, "POST", createDBsReq, "", 202) +} + +func HandleList(t *testing.T) { + fixture.SetupHandler(t, resURL, "GET", "", listDBsResp, 200) +} + +func HandleDelete(t *testing.T) { + fixture.SetupHandler(t, resURL+"/{dbName}", "DELETE", "", "", 202) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go new file mode 100644 index 000000000..f1eb5d9ae --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/requests.go @@ -0,0 +1,115 @@ +package databases + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder builds create options +type CreateOptsBuilder interface { + ToDBCreateMap() (map[string]interface{}, error) +} + +// DatabaseOpts is the struct responsible for configuring a database; often in +// the context of an instance. +type CreateOpts struct { + // [REQUIRED] Specifies the name of the database. Valid names can be composed + // of the following characters: letters (either case); numbers; these + // characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is + // permitted anywhere. Prohibited characters that are forbidden include: + // single quotes, double quotes, back quotes, semicolons, commas, backslashes, + // and forward slashes. + Name string + + // [OPTIONAL] Set of symbols and encodings. The default character set is + // "utf8". See http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for + // supported character sets. + CharSet string + + // [OPTIONAL] Set of rules for comparing characters in a character set. The + // default value for collate is "utf8_general_ci". See + // http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for supported + // collations. + Collate string +} + +// ToMap is a helper function to convert individual DB create opt structures +// into sub-maps. +func (opts CreateOpts) ToMap() (map[string]string, error) { + if opts.Name == "" { + return nil, fmt.Errorf("Name is a required field") + } + if len(opts.Name) > 64 { + return nil, fmt.Errorf("Name must be less than 64 chars long") + } + + db := map[string]string{"name": opts.Name} + + if opts.CharSet != "" { + db["character_set"] = opts.CharSet + } + if opts.Collate != "" { + db["collate"] = opts.Collate + } + return db, nil +} + +// BatchCreateOpts allows for multiple databases to created and modified. +type BatchCreateOpts []CreateOpts + +// ToDBCreateMap renders a JSON map for creating DBs. +func (opts BatchCreateOpts) ToDBCreateMap() (map[string]interface{}, error) { + dbs := make([]map[string]string, len(opts)) + for i, db := range opts { + dbMap, err := db.ToMap() + if err != nil { + return nil, err + } + dbs[i] = dbMap + } + return map[string]interface{}{"databases": dbs}, nil +} + +// Create will create a new database within the specified instance. If the +// specified instance does not exist, a 404 error will be returned. +func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToDBCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("POST", baseURL(client, instanceID), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + + return res +} + +// List will list all of the databases for a specified instance. Note: this +// operation will only return user-defined databases; it will exclude system +// databases like "mysql", "information_schema", "lost+found" etc. +func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return DBPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, baseURL(client, instanceID), createPageFn) +} + +// Delete will permanently delete the database within a specified instance. +// All contained data inside the database will also be permanently deleted. +func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) DeleteResult { + var res DeleteResult + + _, res.Err = client.Request("DELETE", dbURL(client, instanceID, dbName), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/results.go new file mode 100644 index 000000000..7d4b6aeb2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/results.go @@ -0,0 +1,72 @@ +package databases + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Database represents a Database API resource. +type Database struct { + // Specifies the name of the MySQL database. + Name string + + // Set of symbols and encodings. The default character set is utf8. + CharSet string + + // Set of rules for comparing characters in a character set. The default + // value for collate is utf8_general_ci. + Collate string +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// DBPage represents a single page of a paginated DB collection. +type DBPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks to see whether the collection is empty. +func (page DBPage) IsEmpty() (bool, error) { + dbs, err := ExtractDBs(page) + if err != nil { + return true, err + } + return len(dbs) == 0, nil +} + +// NextPageURL will retrieve the next page URL. +func (page DBPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"databases_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractDBs will convert a generic pagination struct into a more +// relevant slice of DB structs. +func ExtractDBs(page pagination.Page) ([]Database, error) { + casted := page.(DBPage).Body + + var response struct { + Databases []Database `mapstructure:"databases"` + } + + err := mapstructure.Decode(casted, &response) + return response.Databases, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/urls.go new file mode 100644 index 000000000..027ca5847 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/databases/urls.go @@ -0,0 +1,11 @@ +package databases + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient, instanceID string) string { + return c.ServiceURL("instances", instanceID, "databases") +} + +func dbURL(c *gophercloud.ServiceClient, instanceID, dbName string) string { + return c.ServiceURL("instances", instanceID, "databases", dbName) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/doc.go new file mode 100644 index 000000000..ae14026b5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/doc.go @@ -0,0 +1,3 @@ +// Package datastores provides information and interaction with the datastore +// API resource in the Rackspace Database service. +package datastores diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go new file mode 100644 index 000000000..fd767cd3b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/fixtures.go @@ -0,0 +1,100 @@ +package datastores + +import ( + "fmt" + + "github.com/rackspace/gophercloud" +) + +const version1JSON = ` +{ + "id": "b00000b0-00b0-0b00-00b0-000b000000bb", + "links": [ + { + "href": "https://10.240.28.38:8779/v1.0/1234/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb", + "rel": "self" + }, + { + "href": "https://10.240.28.38:8779/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb", + "rel": "bookmark" + } + ], + "name": "5.1" +} +` + +const version2JSON = ` +{ + "id": "c00000b0-00c0-0c00-00c0-000b000000cc", + "links": [ + { + "href": "https://10.240.28.38:8779/v1.0/1234/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc", + "rel": "self" + }, + { + "href": "https://10.240.28.38:8779/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc", + "rel": "bookmark" + } + ], + "name": "5.2" +} +` + +var versionsJSON = fmt.Sprintf(`"versions": [%s, %s]`, version1JSON, version2JSON) + +var singleDSJSON = fmt.Sprintf(` +{ + "default_version": "c00000b0-00c0-0c00-00c0-000b000000cc", + "id": "10000000-0000-0000-0000-000000000001", + "links": [ + { + "href": "https://10.240.28.38:8779/v1.0/1234/datastores/10000000-0000-0000-0000-000000000001", + "rel": "self" + }, + { + "href": "https://10.240.28.38:8779/datastores/10000000-0000-0000-0000-000000000001", + "rel": "bookmark" + } + ], + "name": "mysql", + %s +} +`, versionsJSON) + +var ( + ListDSResp = fmt.Sprintf(`{"datastores":[%s]}`, singleDSJSON) + GetDSResp = fmt.Sprintf(`{"datastore":%s}`, singleDSJSON) + ListVersionsResp = fmt.Sprintf(`{%s}`, versionsJSON) + GetVersionResp = fmt.Sprintf(`{"version":%s}`, version1JSON) +) + +var ExampleVersion1 = Version{ + ID: "b00000b0-00b0-0b00-00b0-000b000000bb", + Links: []gophercloud.Link{ + gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb"}, + gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/versions/b00000b0-00b0-0b00-00b0-000b000000bb"}, + }, + Name: "5.1", +} + +var exampleVersion2 = Version{ + ID: "c00000b0-00c0-0c00-00c0-000b000000cc", + Links: []gophercloud.Link{ + gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc"}, + gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/versions/c00000b0-00c0-0c00-00c0-000b000000cc"}, + }, + Name: "5.2", +} + +var ExampleVersions = []Version{ExampleVersion1, exampleVersion2} + +var ExampleDatastore = Datastore{ + DefaultVersion: "c00000b0-00c0-0c00-00c0-000b000000cc", + ID: "10000000-0000-0000-0000-000000000001", + Links: []gophercloud.Link{ + gophercloud.Link{Rel: "self", Href: "https://10.240.28.38:8779/v1.0/1234/datastores/10000000-0000-0000-0000-000000000001"}, + gophercloud.Link{Rel: "bookmark", Href: "https://10.240.28.38:8779/datastores/10000000-0000-0000-0000-000000000001"}, + }, + Name: "mysql", + Versions: ExampleVersions, +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go new file mode 100644 index 000000000..9e147ab2d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/requests.go @@ -0,0 +1,47 @@ +package datastores + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all available datastore types that instances can use. +func List(client *gophercloud.ServiceClient) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return DatastorePage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, baseURL(client), pageFn) +} + +// Get will retrieve the details of a specified datastore type. +func Get(client *gophercloud.ServiceClient, datastoreID string) GetResult { + var res GetResult + + _, res.Err = client.Request("GET", resourceURL(client, datastoreID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONResponse: &res.Body, + }) + + return res +} + +// ListVersions will list all of the available versions for a specified +// datastore type. +func ListVersions(client *gophercloud.ServiceClient, datastoreID string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return VersionPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, versionsURL(client, datastoreID), pageFn) +} + +// GetVersion will retrieve the details of a specified datastore version. +func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) GetVersionResult { + var res GetVersionResult + + _, res.Err = client.Request("GET", versionURL(client, datastoreID, versionID), gophercloud.RequestOpts{ + OkCodes: []int{200}, + JSONResponse: &res.Body, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go new file mode 100644 index 000000000..a86a3cc60 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/results.go @@ -0,0 +1,123 @@ +package datastores + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Version represents a version API resource. Multiple versions belong to a Datastore. +type Version struct { + ID string + Links []gophercloud.Link + Name string +} + +// Datastore represents a Datastore API resource. +type Datastore struct { + DefaultVersion string `json:"default_version" mapstructure:"default_version"` + ID string + Links []gophercloud.Link + Name string + Versions []Version +} + +// DatastorePartial is a meta structure which is used in various API responses. +// It is a lightweight and truncated version of a full Datastore resource, +// offering details of the Version, Type and VersionID only. +type DatastorePartial struct { + Version string + Type string + VersionID string `json:"version_id" mapstructure:"version_id"` +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// GetVersionResult represents the result of getting a version. +type GetVersionResult struct { + gophercloud.Result +} + +// DatastorePage represents a page of datastore resources. +type DatastorePage struct { + pagination.SinglePageBase +} + +// IsEmpty indicates whether a Datastore collection is empty. +func (r DatastorePage) IsEmpty() (bool, error) { + is, err := ExtractDatastores(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractDatastores retrieves a slice of datastore structs from a paginated +// collection. +func ExtractDatastores(page pagination.Page) ([]Datastore, error) { + casted := page.(DatastorePage).Body + + var resp struct { + Datastores []Datastore `mapstructure:"datastores" json:"datastores"` + } + + err := mapstructure.Decode(casted, &resp) + return resp.Datastores, err +} + +// Extract retrieves a single Datastore struct from an operation result. +func (r GetResult) Extract() (*Datastore, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Datastore Datastore `mapstructure:"datastore"` + } + + err := mapstructure.Decode(r.Body, &response) + return &response.Datastore, err +} + +// DatastorePage represents a page of version resources. +type VersionPage struct { + pagination.SinglePageBase +} + +// IsEmpty indicates whether a collection of version resources is empty. +func (r VersionPage) IsEmpty() (bool, error) { + is, err := ExtractVersions(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractVersions retrieves a slice of versions from a paginated collection. +func ExtractVersions(page pagination.Page) ([]Version, error) { + casted := page.(VersionPage).Body + + var resp struct { + Versions []Version `mapstructure:"versions" json:"versions"` + } + + err := mapstructure.Decode(casted, &resp) + return resp.Versions, err +} + +// Extract retrieves a single Version struct from an operation result. +func (r GetVersionResult) Extract() (*Version, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Version Version `mapstructure:"version"` + } + + err := mapstructure.Decode(r.Body, &response) + return &response.Version, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/urls.go new file mode 100644 index 000000000..c4d52480e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/datastores/urls.go @@ -0,0 +1,19 @@ +package datastores + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("datastores") +} + +func resourceURL(c *gophercloud.ServiceClient, dsID string) string { + return c.ServiceURL("datastores", dsID) +} + +func versionsURL(c *gophercloud.ServiceClient, dsID string) string { + return c.ServiceURL("datastores", dsID, "versions") +} + +func versionURL(c *gophercloud.ServiceClient, dsID, versionID string) string { + return c.ServiceURL("datastores", dsID, "versions", versionID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/doc.go new file mode 100644 index 000000000..4d281d562 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/doc.go @@ -0,0 +1,7 @@ +// Package flavors provides information and interaction with the flavor API +// resource in the OpenStack Database service. +// +// A flavor is an available hardware configuration for a database instance. +// Each flavor has a unique combination of disk space, memory capacity and +// priority for CPU time. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/fixtures.go new file mode 100644 index 000000000..f0016bcb2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/fixtures.go @@ -0,0 +1,50 @@ +package flavors + +import ( + "fmt" + "testing" + + "github.com/rackspace/gophercloud/testhelper/fixture" +) + +const flavor = ` +{ + "id": %d, + "links": [ + { + "href": "https://openstack.example.com/v1.0/1234/flavors/%d", + "rel": "self" + }, + { + "href": "https://openstack.example.com/flavors/%d", + "rel": "bookmark" + } + ], + "name": "%s", + "ram": %d +} +` + +var ( + flavorID = "{flavorID}" + _baseURL = "/flavors" + resURL = "/flavors/" + flavorID +) + +var ( + flavor1 = fmt.Sprintf(flavor, 1, 1, 1, "m1.tiny", 512) + flavor2 = fmt.Sprintf(flavor, 2, 2, 2, "m1.small", 1024) + flavor3 = fmt.Sprintf(flavor, 3, 3, 3, "m1.medium", 2048) + flavor4 = fmt.Sprintf(flavor, 4, 4, 4, "m1.large", 4096) + + listFlavorsResp = fmt.Sprintf(`{"flavors":[%s, %s, %s, %s]}`, flavor1, flavor2, flavor3, flavor4) + getFlavorResp = fmt.Sprintf(`{"flavor": %s}`, flavor1) +) + +func HandleList(t *testing.T) { + fixture.SetupHandler(t, _baseURL, "GET", "", listFlavorsResp, 200) +} + +func HandleGet(t *testing.T) { + fixture.SetupHandler(t, resURL, "GET", "", getFlavorResp, 200) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/requests.go new file mode 100644 index 000000000..fa34446b8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/requests.go @@ -0,0 +1,29 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all available hardware flavors that an instance can use. The +// operation is identical to the one supported by the Nova API, but without the +// "disk" property. +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return FlavorPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, listURL(client), createPage) +} + +// Get will retrieve information for a specified hardware flavor. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var gr GetResult + + _, gr.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &gr.Body, + OkCodes: []int{200}, + }) + + return gr +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/results.go new file mode 100644 index 000000000..2cee010aa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/results.go @@ -0,0 +1,92 @@ +package flavors + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// GetResult temporarily holds the response from a Get call. +type GetResult struct { + gophercloud.Result +} + +// Extract provides access to the individual Flavor returned by the Get function. +func (gr GetResult) Extract() (*Flavor, error) { + if gr.Err != nil { + return nil, gr.Err + } + + var result struct { + Flavor Flavor `mapstructure:"flavor"` + } + + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + WeaklyTypedInput: true, + Result: &result, + }) + + err = decoder.Decode(gr.Body) + return &result.Flavor, err +} + +// Flavor records represent (virtual) hardware configurations for server resources in a region. +type Flavor struct { + // The flavor's unique identifier. + ID string `mapstructure:"id"` + + // The RAM capacity for the flavor. + RAM int `mapstructure:"ram"` + + // The Name field provides a human-readable moniker for the flavor. + Name string `mapstructure:"name"` + + // Links to access the flavor. + Links []gophercloud.Link +} + +// FlavorPage contains a single page of the response from a List call. +type FlavorPage struct { + pagination.LinkedPageBase +} + +// IsEmpty determines if a page contains any results. +func (p FlavorPage) IsEmpty() (bool, error) { + flavors, err := ExtractFlavors(p) + if err != nil { + return true, err + } + return len(flavors) == 0, nil +} + +// NextPageURL uses the response's embedded link reference to navigate to the next page of results. +func (p FlavorPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"flavors_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation. +func ExtractFlavors(page pagination.Page) ([]Flavor, error) { + casted := page.(FlavorPage).Body + var container struct { + Flavors []Flavor `mapstructure:"flavors"` + } + + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + WeaklyTypedInput: true, + Result: &container, + }) + + err = decoder.Decode(casted) + + return container.Flavors, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/urls.go new file mode 100644 index 000000000..80da11f9b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/flavors/urls.go @@ -0,0 +1,11 @@ +package flavors + +import "github.com/rackspace/gophercloud" + +func getURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("flavors", id) +} + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("flavors") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/doc.go new file mode 100644 index 000000000..dc5c90f95 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/doc.go @@ -0,0 +1,7 @@ +// Package instances provides information and interaction with the instance API +// resource in the OpenStack Database service. +// +// A database instance is an isolated database environment with compute and +// storage resources in a single tenant environment on a shared physical host +// machine. +package instances diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/fixtures.go new file mode 100644 index 000000000..af7b185a6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/fixtures.go @@ -0,0 +1,169 @@ +package instances + +import ( + "fmt" + "testing" + "time" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/openstack/db/v1/flavors" + "github.com/rackspace/gophercloud/testhelper/fixture" +) + +var ( + timestamp = "2015-11-12T14:22:42Z" + timeVal, _ = time.Parse(time.RFC3339, timestamp) +) + +var instance = ` +{ + "created": "` + timestamp + `", + "datastore": { + "type": "mysql", + "version": "5.6" + }, + "flavor": { + "id": "1", + "links": [ + { + "href": "https://my-openstack.com/v1.0/1234/flavors/1", + "rel": "self" + }, + { + "href": "https://my-openstack.com/v1.0/1234/flavors/1", + "rel": "bookmark" + } + ] + }, + "links": [ + { + "href": "https://my-openstack.com/v1.0/1234/instances/1", + "rel": "self" + } + ], + "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com", + "id": "{instanceID}", + "name": "json_rack_instance", + "status": "BUILD", + "updated": "` + timestamp + `", + "volume": { + "size": 2 + } +} +` + +var createReq = ` +{ + "instance": { + "databases": [ + { + "character_set": "utf8", + "collate": "utf8_general_ci", + "name": "sampledb" + }, + { + "name": "nextround" + } + ], + "flavorRef": "1", + "name": "json_rack_instance", + "users": [ + { + "databases": [ + { + "name": "sampledb" + } + ], + "name": "demouser", + "password": "demopassword" + } + ], + "volume": { + "size": 2 + } + } +} +` + +var ( + instanceID = "{instanceID}" + rootURL = "/instances" + resURL = rootURL + "/" + instanceID + uRootURL = resURL + "/root" + aURL = resURL + "/action" +) + +var ( + restartReq = `{"restart": {}}` + resizeReq = `{"resize": {"flavorRef": "2"}}` + resizeVolReq = `{"resize": {"volume": {"size": 4}}}` +) + +var ( + createResp = fmt.Sprintf(`{"instance": %s}`, instance) + listInstancesResp = fmt.Sprintf(`{"instances":[%s]}`, instance) + getInstanceResp = createResp + enableUserResp = `{"user":{"name":"root","password":"secretsecret"}}` + isUserEnabledResp = `{"rootEnabled":true}` +) + +var expectedInstance = Instance{ + Created: timeVal, + Updated: timeVal, + Flavor: flavors.Flavor{ + ID: "1", + Links: []gophercloud.Link{ + gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "self"}, + gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "bookmark"}, + }, + }, + Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com", + ID: instanceID, + Links: []gophercloud.Link{ + gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/instances/1", Rel: "self"}, + }, + Name: "json_rack_instance", + Status: "BUILD", + Volume: Volume{Size: 2}, + Datastore: datastores.DatastorePartial{ + Type: "mysql", + Version: "5.6", + }, +} + +func HandleCreate(t *testing.T) { + fixture.SetupHandler(t, rootURL, "POST", createReq, createResp, 200) +} + +func HandleList(t *testing.T) { + fixture.SetupHandler(t, rootURL, "GET", "", listInstancesResp, 200) +} + +func HandleGet(t *testing.T) { + fixture.SetupHandler(t, resURL, "GET", "", getInstanceResp, 200) +} + +func HandleDelete(t *testing.T) { + fixture.SetupHandler(t, resURL, "DELETE", "", "", 202) +} + +func HandleEnableRoot(t *testing.T) { + fixture.SetupHandler(t, uRootURL, "POST", "", enableUserResp, 200) +} + +func HandleIsRootEnabled(t *testing.T) { + fixture.SetupHandler(t, uRootURL, "GET", "", isUserEnabledResp, 200) +} + +func HandleRestart(t *testing.T) { + fixture.SetupHandler(t, aURL, "POST", restartReq, "", 202) +} + +func HandleResize(t *testing.T) { + fixture.SetupHandler(t, aURL, "POST", resizeReq, "", 202) +} + +func HandleResizeVol(t *testing.T) { + fixture.SetupHandler(t, aURL, "POST", resizeVolReq, "", 202) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/requests.go new file mode 100644 index 000000000..f4a63b814 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/requests.go @@ -0,0 +1,238 @@ +package instances + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + db "github.com/rackspace/gophercloud/openstack/db/v1/databases" + "github.com/rackspace/gophercloud/openstack/db/v1/users" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder is the top-level interface for create options. +type CreateOptsBuilder interface { + ToInstanceCreateMap() (map[string]interface{}, error) +} + +// DatastoreOpts represents the configuration for how an instance stores data. +type DatastoreOpts struct { + Version string + Type string +} + +func (opts DatastoreOpts) ToMap() (map[string]string, error) { + return map[string]string{ + "version": opts.Version, + "type": opts.Type, + }, nil +} + +// CreateOpts is the struct responsible for configuring a new database instance. +type CreateOpts struct { + // Either the integer UUID (in string form) of the flavor, or its URI + // reference as specified in the response from the List() call. Required. + FlavorRef string + + // Specifies the volume size in gigabytes (GB). The value must be between 1 + // and 300. Required. + Size int + + // Name of the instance to create. The length of the name is limited to + // 255 characters and any characters are permitted. Optional. + Name string + + // A slice of database information options. + Databases db.CreateOptsBuilder + + // A slice of user information options. + Users users.CreateOptsBuilder + + // Options to configure the type of datastore the instance will use. This is + // optional, and if excluded will default to MySQL. + Datastore *DatastoreOpts +} + +// ToInstanceCreateMap will render a JSON map. +func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) { + if opts.Size > 300 || opts.Size < 1 { + return nil, fmt.Errorf("Size (GB) must be between 1-300") + } + if opts.FlavorRef == "" { + return nil, fmt.Errorf("FlavorRef is a required field") + } + + instance := map[string]interface{}{ + "volume": map[string]int{"size": opts.Size}, + "flavorRef": opts.FlavorRef, + } + + if opts.Name != "" { + instance["name"] = opts.Name + } + if opts.Databases != nil { + dbs, err := opts.Databases.ToDBCreateMap() + if err != nil { + return nil, err + } + instance["databases"] = dbs["databases"] + } + if opts.Users != nil { + users, err := opts.Users.ToUserCreateMap() + if err != nil { + return nil, err + } + instance["users"] = users["users"] + } + + return map[string]interface{}{"instance": instance}, nil +} + +// Create asynchronously provisions a new database instance. It requires the +// user to specify a flavor and a volume size. The API service then provisions +// the instance with the requested flavor and sets up a volume of the specified +// size, which is the storage for the database instance. +// +// Although this call only allows the creation of 1 instance per request, you +// can create an instance with multiple databases and users. The default +// binding for a MySQL instance is port 3306. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToInstanceCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{ + JSONBody: &reqBody, + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// List retrieves the status and information for all database instances. +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return InstancePage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, baseURL(client), createPageFn) +} + +// Get retrieves the status and information for a specified database instance. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + + _, res.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// Delete permanently destroys the database instance. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + + _, res.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} + +// EnableRootUser enables the login from any host for the root user and +// provides the user with a generated root password. +func EnableRootUser(client *gophercloud.ServiceClient, id string) UserRootResult { + var res UserRootResult + + _, res.Err = client.Request("POST", userRootURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// IsRootEnabled checks an instance to see if root access is enabled. It returns +// True if root user is enabled for the specified database instance or False +// otherwise. +func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) { + var res gophercloud.Result + + _, err := client.Request("GET", userRootURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res.Body.(map[string]interface{})["rootEnabled"] == true, err +} + +// Restart will restart only the MySQL Instance. Restarting MySQL will +// erase any dynamic configuration settings that you have made within MySQL. +// The MySQL service will be unavailable until the instance restarts. +func Restart(client *gophercloud.ServiceClient, id string) ActionResult { + var res ActionResult + + _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{ + JSONBody: map[string]interface{}{"restart": struct{}{}}, + OkCodes: []int{202}, + }) + + return res +} + +// Resize changes the memory size of the instance, assuming a valid +// flavorRef is provided. It will also restart the MySQL service. +func Resize(client *gophercloud.ServiceClient, id, flavorRef string) ActionResult { + var res ActionResult + + type resize struct { + FlavorRef string `json:"flavorRef"` + } + + type req struct { + Resize resize `json:"resize"` + } + + reqBody := req{Resize: resize{FlavorRef: flavorRef}} + + _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{ + JSONBody: reqBody, + OkCodes: []int{202}, + }) + + return res +} + +// ResizeVolume will resize the attached volume for an instance. It supports +// only increasing the volume size and does not support decreasing the size. +// The volume size is in gigabytes (GB) and must be an integer. +func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) ActionResult { + var res ActionResult + + type volume struct { + Size int `json:"size"` + } + + type resize struct { + Volume volume `json:"volume"` + } + + type req struct { + Resize resize `json:"resize"` + } + + reqBody := req{Resize: resize{Volume: volume{Size: size}}} + + _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{ + JSONBody: reqBody, + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/results.go new file mode 100644 index 000000000..95aed166b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/results.go @@ -0,0 +1,213 @@ +package instances + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/openstack/db/v1/flavors" + "github.com/rackspace/gophercloud/openstack/db/v1/users" + "github.com/rackspace/gophercloud/pagination" +) + +// Volume represents information about an attached volume for a database instance. +type Volume struct { + // The size in GB of the volume + Size int + + Used float64 +} + +// Instance represents a remote MySQL instance. +type Instance struct { + // Indicates the datetime that the instance was created + Created time.Time `mapstructure:"-"` + + // Indicates the most recent datetime that the instance was updated. + Updated time.Time `mapstructure:"-"` + + // Indicates the hardware flavor the instance uses. + Flavor flavors.Flavor + + // A DNS-resolvable hostname associated with the database instance (rather + // than an IPv4 address). Since the hostname always resolves to the correct + // IP address of the database instance, this relieves the user from the task + // of maintaining the mapping. Note that although the IP address may likely + // change on resizing, migrating, and so forth, the hostname always resolves + // to the correct database instance. + Hostname string + + // Indicates the unique identifier for the instance resource. + ID string + + // Exposes various links that reference the instance resource. + Links []gophercloud.Link + + // The human-readable name of the instance. + Name string + + // The build status of the instance. + Status string + + // Information about the attached volume of the instance. + Volume Volume + + // Indicates how the instance stores data. + Datastore datastores.DatastorePartial +} + +type commonResult struct { + gophercloud.Result +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Extract will extract an Instance from various result structs. +func (r commonResult) Extract() (*Instance, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Instance Instance `mapstructure:"instance"` + } + + err := mapstructure.Decode(r.Body, &response) + val := r.Body.(map[string]interface{})["instance"].(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Instance, err + } + response.Instance.Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Instance, err + } + response.Instance.Updated = updatedTime + } + + return &response.Instance, err +} + +// InstancePage represents a single page of a paginated instance collection. +type InstancePage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks to see whether the collection is empty. +func (page InstancePage) IsEmpty() (bool, error) { + instances, err := ExtractInstances(page) + if err != nil { + return true, err + } + return len(instances) == 0, nil +} + +// NextPageURL will retrieve the next page URL. +func (page InstancePage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"instances_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractInstances will convert a generic pagination struct into a more +// relevant slice of Instance structs. +func ExtractInstances(page pagination.Page) ([]Instance, error) { + casted := page.(InstancePage).Body + + var resp struct { + Instances []Instance `mapstructure:"instances"` + } + + if err := mapstructure.Decode(casted, &resp); err != nil { + return nil, err + } + + var vals []interface{} + switch casted.(type) { + case map[string]interface{}: + vals = casted.(map[string]interface{})["instances"].([]interface{}) + case map[string][]interface{}: + vals = casted.(map[string][]interface{})["instances"] + default: + return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, v := range vals { + val := v.(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Instances, err + } + resp.Instances[i].Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Instances, err + } + resp.Instances[i].Updated = updatedTime + } + } + + return resp.Instances, nil +} + +// UserRootResult represents the result of an operation to enable the root user. +type UserRootResult struct { + gophercloud.Result +} + +// Extract will extract root user information from a UserRootResult. +func (r UserRootResult) Extract() (*users.User, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + User users.User `mapstructure:"user"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.User, err +} + +// ActionResult represents the result of action requests, such as: restarting +// an instance service, resizing its memory allocation, and resizing its +// attached volume size. +type ActionResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/urls.go new file mode 100644 index 000000000..28c0bec3d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/instances/urls.go @@ -0,0 +1,19 @@ +package instances + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("instances") +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id) +} + +func userRootURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id, "root") +} + +func actionURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id, "action") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/doc.go new file mode 100644 index 000000000..cf07832f3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/doc.go @@ -0,0 +1,3 @@ +// Package users provides information and interaction with the user API +// resource in the OpenStack Database service. +package users diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/fixtures.go new file mode 100644 index 000000000..516b335e0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/fixtures.go @@ -0,0 +1,37 @@ +package users + +import ( + "fmt" + "testing" + + "github.com/rackspace/gophercloud/testhelper/fixture" +) + +const user1 = ` +{"databases": [{"name": "databaseA"}],"name": "dbuser3"%s} +` + +const user2 = ` +{"databases": [{"name": "databaseB"},{"name": "databaseC"}],"name": "dbuser4"%s} +` + +var ( + instanceID = "{instanceID}" + _rootURL = "/instances/" + instanceID + "/users" + pUser1 = fmt.Sprintf(user1, `,"password":"secretsecret"`) + pUser2 = fmt.Sprintf(user2, `,"password":"secretsecret"`) + createReq = fmt.Sprintf(`{"users":[%s, %s]}`, pUser1, pUser2) + listResp = fmt.Sprintf(`{"users":[%s, %s]}`, fmt.Sprintf(user1, ""), fmt.Sprintf(user2, "")) +) + +func HandleCreate(t *testing.T) { + fixture.SetupHandler(t, _rootURL, "POST", createReq, "", 202) +} + +func HandleList(t *testing.T) { + fixture.SetupHandler(t, _rootURL, "GET", "", listResp, 200) +} + +func HandleDelete(t *testing.T) { + fixture.SetupHandler(t, _rootURL+"/{userName}", "DELETE", "", "", 202) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/requests.go new file mode 100644 index 000000000..7533fc494 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/requests.go @@ -0,0 +1,132 @@ +package users + +import ( + "errors" + + "github.com/rackspace/gophercloud" + db "github.com/rackspace/gophercloud/openstack/db/v1/databases" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder is the top-level interface for creating JSON maps. +type CreateOptsBuilder interface { + ToUserCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the struct responsible for configuring a new user; often in the +// context of an instance. +type CreateOpts struct { + // [REQUIRED] Specifies a name for the user. Valid names can be composed + // of the following characters: letters (either case); numbers; these + // characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is + // permitted anywhere. Prohibited characters that are forbidden include: + // single quotes, double quotes, back quotes, semicolons, commas, backslashes, + // and forward slashes. Spaces at the front or end of a user name are also + // not permitted. + Name string + + // [REQUIRED] Specifies a password for the user. + Password string + + // [OPTIONAL] An array of databases that this user will connect to. The + // "name" field is the only requirement for each option. + Databases db.BatchCreateOpts + + // [OPTIONAL] Specifies the host from which a user is allowed to connect to + // the database. Possible values are a string containing an IPv4 address or + // "%" to allow connecting from any host. Optional; the default is "%". + Host string +} + +// ToMap is a convenience function for creating sub-maps for individual users. +func (opts CreateOpts) ToMap() (map[string]interface{}, error) { + + if opts.Name == "root" { + return nil, errors.New("root is a reserved user name and cannot be used") + } + if opts.Name == "" { + return nil, errors.New("Name is a required field") + } + if opts.Password == "" { + return nil, errors.New("Password is a required field") + } + + user := map[string]interface{}{ + "name": opts.Name, + "password": opts.Password, + } + + if opts.Host != "" { + user["host"] = opts.Host + } + + dbs := make([]map[string]string, len(opts.Databases)) + for i, db := range opts.Databases { + dbs[i] = map[string]string{"name": db.Name} + } + + if len(dbs) > 0 { + user["databases"] = dbs + } + + return user, nil +} + +// BatchCreateOpts allows multiple users to be created at once. +type BatchCreateOpts []CreateOpts + +// ToUserCreateMap will generate a JSON map. +func (opts BatchCreateOpts) ToUserCreateMap() (map[string]interface{}, error) { + users := make([]map[string]interface{}, len(opts)) + for i, opt := range opts { + user, err := opt.ToMap() + if err != nil { + return nil, err + } + users[i] = user + } + return map[string]interface{}{"users": users}, nil +} + +// Create asynchronously provisions a new user for the specified database +// instance based on the configuration defined in CreateOpts. If databases are +// assigned for a particular user, the user will be granted all privileges +// for those specified databases. "root" is a reserved name and cannot be used. +func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToUserCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("POST", baseURL(client, instanceID), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + + return res +} + +// List will list all the users associated with a specified database instance, +// along with their associated databases. This operation will not return any +// system users or administrators for a database. +func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return UserPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, baseURL(client, instanceID), createPageFn) +} + +// Delete will permanently delete a user from a specified database instance. +func Delete(client *gophercloud.ServiceClient, instanceID, userName string) DeleteResult { + var res DeleteResult + + _, res.Err = client.Request("DELETE", userURL(client, instanceID, userName), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/results.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/results.go new file mode 100644 index 000000000..217ddd8da --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/results.go @@ -0,0 +1,73 @@ +package users + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + db "github.com/rackspace/gophercloud/openstack/db/v1/databases" + "github.com/rackspace/gophercloud/pagination" +) + +// User represents a database user +type User struct { + // The user name + Name string + + // The user password + Password string + + // The databases associated with this user + Databases []db.Database +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// UserPage represents a single page of a paginated user collection. +type UserPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks to see whether the collection is empty. +func (page UserPage) IsEmpty() (bool, error) { + users, err := ExtractUsers(page) + if err != nil { + return true, err + } + return len(users) == 0, nil +} + +// NextPageURL will retrieve the next page URL. +func (page UserPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"users_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractUsers will convert a generic pagination struct into a more +// relevant slice of User structs. +func ExtractUsers(page pagination.Page) ([]User, error) { + casted := page.(UserPage).Body + + var response struct { + Users []User `mapstructure:"users"` + } + + err := mapstructure.Decode(casted, &response) + + return response.Users, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/urls.go new file mode 100644 index 000000000..2a3cacdaf --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/db/v1/users/urls.go @@ -0,0 +1,11 @@ +package users + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient, instanceID string) string { + return c.ServiceURL("instances", instanceID, "users") +} + +func userURL(c *gophercloud.ServiceClient, instanceID, userName string) string { + return c.ServiceURL("instances", instanceID, "users", userName) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/endpoint_location.go b/vendor/github.com/rackspace/gophercloud/openstack/endpoint_location.go new file mode 100644 index 000000000..29d02c43f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/endpoint_location.go @@ -0,0 +1,91 @@ +package openstack + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens" + tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens" +) + +// V2EndpointURL discovers the endpoint URL for a specific service from a ServiceCatalog acquired +// during the v2 identity service. The specified EndpointOpts are used to identify a unique, +// unambiguous endpoint to return. It's an error both when multiple endpoints match the provided +// criteria and when none do. The minimum that can be specified is a Type, but you will also often +// need to specify a Name and/or a Region depending on what's available on your OpenStack +// deployment. +func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) { + // Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided. + var endpoints = make([]tokens2.Endpoint, 0, 1) + for _, entry := range catalog.Entries { + if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) { + for _, endpoint := range entry.Endpoints { + if opts.Region == "" || endpoint.Region == opts.Region { + endpoints = append(endpoints, endpoint) + } + } + } + } + + // Report an error if the options were ambiguous. + if len(endpoints) > 1 { + return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints) + } + + // Extract the appropriate URL from the matching Endpoint. + for _, endpoint := range endpoints { + switch opts.Availability { + case gophercloud.AvailabilityPublic: + return gophercloud.NormalizeURL(endpoint.PublicURL), nil + case gophercloud.AvailabilityInternal: + return gophercloud.NormalizeURL(endpoint.InternalURL), nil + case gophercloud.AvailabilityAdmin: + return gophercloud.NormalizeURL(endpoint.AdminURL), nil + default: + return "", fmt.Errorf("Unexpected availability in endpoint query: %s", opts.Availability) + } + } + + // Report an error if there were no matching endpoints. + return "", gophercloud.ErrEndpointNotFound +} + +// V3EndpointURL discovers the endpoint URL for a specific service from a Catalog acquired +// during the v3 identity service. The specified EndpointOpts are used to identify a unique, +// unambiguous endpoint to return. It's an error both when multiple endpoints match the provided +// criteria and when none do. The minimum that can be specified is a Type, but you will also often +// need to specify a Name and/or a Region depending on what's available on your OpenStack +// deployment. +func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) { + // Extract Endpoints from the catalog entries that match the requested Type, Interface, + // Name if provided, and Region if provided. + var endpoints = make([]tokens3.Endpoint, 0, 1) + for _, entry := range catalog.Entries { + if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) { + for _, endpoint := range entry.Endpoints { + if opts.Availability != gophercloud.AvailabilityAdmin && + opts.Availability != gophercloud.AvailabilityPublic && + opts.Availability != gophercloud.AvailabilityInternal { + return "", fmt.Errorf("Unexpected availability in endpoint query: %s", opts.Availability) + } + if (opts.Availability == gophercloud.Availability(endpoint.Interface)) && + (opts.Region == "" || endpoint.Region == opts.Region) { + endpoints = append(endpoints, endpoint) + } + } + } + } + + // Report an error if the options were ambiguous. + if len(endpoints) > 1 { + return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints) + } + + // Extract the URL from the matching Endpoint. + for _, endpoint := range endpoints { + return gophercloud.NormalizeURL(endpoint.URL), nil + } + + // Report an error if there were no matching endpoints. + return "", gophercloud.ErrEndpointNotFound +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/docs.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/docs.go new file mode 100644 index 000000000..895417871 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/docs.go @@ -0,0 +1,16 @@ +// Package roles provides functionality to interact with and control roles on +// the API. +// +// A role represents a personality that a user can assume when performing a +// specific set of operations. If a role includes a set of rights and +// privileges, a user assuming that role inherits those rights and privileges. +// +// When a token is generated, the list of roles that user can assume is returned +// back to them. Services that are being called by that user determine how they +// interpret the set of roles a user has and to which operations or resources +// each role grants access. +// +// It is up to individual services such as Compute or Image to assign meaning +// to these roles. As far as the Identity service is concerned, a role is an +// arbitrary name assigned by the user. +package roles diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/fixtures.go new file mode 100644 index 000000000..8256f0fe8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/fixtures.go @@ -0,0 +1,48 @@ +package roles + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/OS-KSADM/roles", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "roles": [ + { + "id": "123", + "name": "compute:admin", + "description": "Nova Administrator" + } + ] +} + `) + }) +} + +func MockAddUserRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusCreated) + }) +} + +func MockDeleteUserRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/requests.go new file mode 100644 index 000000000..9a333140b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/requests.go @@ -0,0 +1,33 @@ +package roles + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List is the operation responsible for listing all available global roles +// that a user can adopt. +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return RolePage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, rootURL(client), createPage) +} + +// AddUserRole is the operation responsible for assigning a particular role to +// a user. This is confined to the scope of the user's tenant - so the tenant +// ID is a required argument. +func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult { + var result UserRoleResult + _, result.Err = client.Put(userRoleURL(client, tenantID, userID, roleID), nil, nil, nil) + return result +} + +// DeleteUserRole is the operation responsible for deleting a particular role +// from a user. This is confined to the scope of the user's tenant - so the +// tenant ID is a required argument. +func DeleteUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult { + var result UserRoleResult + _, result.Err = client.Delete(userRoleURL(client, tenantID, userID, roleID), nil) + return result +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/results.go new file mode 100644 index 000000000..ebb3aa530 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/results.go @@ -0,0 +1,53 @@ +package roles + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Role represents an API role resource. +type Role struct { + // The unique ID for the role. + ID string + + // The human-readable name of the role. + Name string + + // The description of the role. + Description string + + // The associated service for this role. + ServiceID string +} + +// RolePage is a single page of a user Role collection. +type RolePage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a page of Tenants contains any results. +func (page RolePage) IsEmpty() (bool, error) { + users, err := ExtractRoles(page) + if err != nil { + return false, err + } + return len(users) == 0, nil +} + +// ExtractRoles returns a slice of roles contained in a single page of results. +func ExtractRoles(page pagination.Page) ([]Role, error) { + casted := page.(RolePage).Body + var response struct { + Roles []Role `mapstructure:"roles"` + } + + err := mapstructure.Decode(casted, &response) + return response.Roles, err +} + +// UserRoleResult represents the result of either an AddUserRole or +// a DeleteUserRole operation. +type UserRoleResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/urls.go new file mode 100644 index 000000000..61b31551d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles/urls.go @@ -0,0 +1,21 @@ +package roles + +import "github.com/rackspace/gophercloud" + +const ( + ExtPath = "OS-KSADM" + RolePath = "roles" + UserPath = "users" +) + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(ExtPath, RolePath, id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(ExtPath, RolePath) +} + +func userRoleURL(c *gophercloud.ServiceClient, tenantID, userID, roleID string) string { + return c.ServiceURL("tenants", tenantID, UserPath, userID, RolePath, ExtPath, roleID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/delegate.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/delegate.go new file mode 100644 index 000000000..fd6e80ea6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/delegate.go @@ -0,0 +1,52 @@ +package extensions + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + common "github.com/rackspace/gophercloud/openstack/common/extensions" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtensionPage is a single page of Extension results. +type ExtensionPage struct { + common.ExtensionPage +} + +// IsEmpty returns true if the current page contains at least one Extension. +func (page ExtensionPage) IsEmpty() (bool, error) { + is, err := ExtractExtensions(page) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the +// elements into a slice of Extension structs. +func ExtractExtensions(page pagination.Page) ([]common.Extension, error) { + // Identity v2 adds an intermediate "values" object. + + var resp struct { + Extensions struct { + Values []common.Extension `mapstructure:"values"` + } `mapstructure:"extensions"` + } + + err := mapstructure.Decode(page.(ExtensionPage).Body, &resp) + return resp.Extensions.Values, err +} + +// Get retrieves information for a specific extension using its alias. +func Get(c *gophercloud.ServiceClient, alias string) common.GetResult { + return common.Get(c, alias) +} + +// List returns a Pager which allows you to iterate over the full collection of extensions. +// It does not accept query parameters. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return common.List(c).WithPageCreator(func(r pagination.PageResult) pagination.Page { + return ExtensionPage{ + ExtensionPage: common.ExtensionPage{SinglePageBase: pagination.SinglePageBase(r)}, + } + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/doc.go new file mode 100644 index 000000000..791e4e391 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/doc.go @@ -0,0 +1,3 @@ +// Package extensions provides information and interaction with the +// different extensions available for the OpenStack Identity service. +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/fixtures.go new file mode 100644 index 000000000..96cb7d24a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/extensions/fixtures.go @@ -0,0 +1,60 @@ +// +build fixtures + +package extensions + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput provides a single Extension result. It differs from the delegated implementation +// by the introduction of an intermediate "values" member. +const ListOutput = ` +{ + "extensions": { + "values": [ + { + "updated": "2013-01-20T00:00:00-00:00", + "name": "Neutron Service Type Management", + "links": [], + "namespace": "http://docs.openstack.org/ext/neutron/service-type/api/v1.0", + "alias": "service-type", + "description": "API for retrieving service providers for Neutron advanced services" + } + ] + } +} +` + +// HandleListExtensionsSuccessfully creates an HTTP handler that returns ListOutput for a List +// call. +func HandleListExtensionsSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/extensions", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + + fmt.Fprintf(w, ` +{ + "extensions": { + "values": [ + { + "updated": "2013-01-20T00:00:00-00:00", + "name": "Neutron Service Type Management", + "links": [], + "namespace": "http://docs.openstack.org/ext/neutron/service-type/api/v1.0", + "alias": "service-type", + "description": "API for retrieving service providers for Neutron advanced services" + } + ] + } +} + `) + }) + +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/doc.go new file mode 100644 index 000000000..0c2d49d56 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/doc.go @@ -0,0 +1,7 @@ +// Package tenants provides information and interaction with the +// tenants API resource for the OpenStack Identity service. +// +// See http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2 +// and http://developer.openstack.org/api-ref-identity-v2.html#admin-tenants +// for more information. +package tenants diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/fixtures.go new file mode 100644 index 000000000..7f044ac3b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/fixtures.go @@ -0,0 +1,65 @@ +// +build fixtures + +package tenants + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +// ListOutput provides a single page of Tenant results. +const ListOutput = ` +{ + "tenants": [ + { + "id": "1234", + "name": "Red Team", + "description": "The team that is red", + "enabled": true + }, + { + "id": "9876", + "name": "Blue Team", + "description": "The team that is blue", + "enabled": false + } + ] +} +` + +// RedTeam is a Tenant fixture. +var RedTeam = Tenant{ + ID: "1234", + Name: "Red Team", + Description: "The team that is red", + Enabled: true, +} + +// BlueTeam is a Tenant fixture. +var BlueTeam = Tenant{ + ID: "9876", + Name: "Blue Team", + Description: "The team that is blue", + Enabled: false, +} + +// ExpectedTenantSlice is the slice of tenants expected to be returned from ListOutput. +var ExpectedTenantSlice = []Tenant{RedTeam, BlueTeam} + +// HandleListTenantsSuccessfully creates an HTTP handler at `/tenants` on the test handler mux that +// responds with a list of two tenants. +func HandleListTenantsSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/tenants", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ListOutput) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/requests.go new file mode 100644 index 000000000..5a359f5c9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/requests.go @@ -0,0 +1,33 @@ +package tenants + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts filters the Tenants that are returned by the List call. +type ListOpts struct { + // Marker is the ID of the last Tenant on the previous page. + Marker string `q:"marker"` + + // Limit specifies the page size. + Limit int `q:"limit"` +} + +// List enumerates the Tenants to which the current token has access. +func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return TenantPage{pagination.LinkedPageBase{PageResult: r}} + } + + url := listURL(client) + if opts != nil { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return pagination.Pager{Err: err} + } + url += q.String() + } + + return pagination.NewPager(client, url, createPage) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/results.go new file mode 100644 index 000000000..c1220c384 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/results.go @@ -0,0 +1,62 @@ +package tenants + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Tenant is a grouping of users in the identity service. +type Tenant struct { + // ID is a unique identifier for this tenant. + ID string `mapstructure:"id"` + + // Name is a friendlier user-facing name for this tenant. + Name string `mapstructure:"name"` + + // Description is a human-readable explanation of this Tenant's purpose. + Description string `mapstructure:"description"` + + // Enabled indicates whether or not a tenant is active. + Enabled bool `mapstructure:"enabled"` +} + +// TenantPage is a single page of Tenant results. +type TenantPage struct { + pagination.LinkedPageBase +} + +// IsEmpty determines whether or not a page of Tenants contains any results. +func (page TenantPage) IsEmpty() (bool, error) { + tenants, err := ExtractTenants(page) + if err != nil { + return false, err + } + return len(tenants) == 0, nil +} + +// NextPageURL extracts the "next" link from the tenants_links section of the result. +func (page TenantPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"tenants_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractTenants returns a slice of Tenants contained in a single page of results. +func ExtractTenants(page pagination.Page) ([]Tenant, error) { + casted := page.(TenantPage).Body + var response struct { + Tenants []Tenant `mapstructure:"tenants"` + } + + err := mapstructure.Decode(casted, &response) + return response.Tenants, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/urls.go new file mode 100644 index 000000000..1dd6ce023 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tenants/urls.go @@ -0,0 +1,7 @@ +package tenants + +import "github.com/rackspace/gophercloud" + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("tenants") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/doc.go new file mode 100644 index 000000000..31cacc5e1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/doc.go @@ -0,0 +1,5 @@ +// Package tokens provides information and interaction with the token API +// resource for the OpenStack Identity service. +// For more information, see: +// http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2 +package tokens diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/errors.go new file mode 100644 index 000000000..3dfdc08db --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/errors.go @@ -0,0 +1,30 @@ +package tokens + +import ( + "errors" + "fmt" +) + +var ( + // ErrUserIDProvided is returned if you attempt to authenticate with a UserID. + ErrUserIDProvided = unacceptedAttributeErr("UserID") + + // ErrAPIKeyProvided is returned if you attempt to authenticate with an APIKey. + ErrAPIKeyProvided = unacceptedAttributeErr("APIKey") + + // ErrDomainIDProvided is returned if you attempt to authenticate with a DomainID. + ErrDomainIDProvided = unacceptedAttributeErr("DomainID") + + // ErrDomainNameProvided is returned if you attempt to authenticate with a DomainName. + ErrDomainNameProvided = unacceptedAttributeErr("DomainName") + + // ErrUsernameRequired is returned if you attempt to authenticate without a Username. + ErrUsernameRequired = errors.New("You must supply a Username in your AuthOptions.") + + // ErrPasswordRequired is returned if you don't provide a password. + ErrPasswordRequired = errors.New("Please supply a Password in your AuthOptions.") +) + +func unacceptedAttributeErr(attribute string) error { + return fmt.Errorf("The base Identity V2 API does not accept authentication by %s", attribute) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/fixtures.go new file mode 100644 index 000000000..6245259e1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/fixtures.go @@ -0,0 +1,195 @@ +// +build fixtures + +package tokens + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/rackspace/gophercloud/openstack/identity/v2/tenants" + th "github.com/rackspace/gophercloud/testhelper" + thclient "github.com/rackspace/gophercloud/testhelper/client" +) + +// ExpectedToken is the token that should be parsed from TokenCreationResponse. +var ExpectedToken = &Token{ + ID: "aaaabbbbccccdddd", + ExpiresAt: time.Date(2014, time.January, 31, 15, 30, 58, 0, time.UTC), + Tenant: tenants.Tenant{ + ID: "fc394f2ab2df4114bde39905f800dc57", + Name: "test", + Description: "There are many tenants. This one is yours.", + Enabled: true, + }, +} + +// ExpectedServiceCatalog is the service catalog that should be parsed from TokenCreationResponse. +var ExpectedServiceCatalog = &ServiceCatalog{ + Entries: []CatalogEntry{ + CatalogEntry{ + Name: "inscrutablewalrus", + Type: "something", + Endpoints: []Endpoint{ + Endpoint{ + PublicURL: "http://something0:1234/v2/", + Region: "region0", + }, + Endpoint{ + PublicURL: "http://something1:1234/v2/", + Region: "region1", + }, + }, + }, + CatalogEntry{ + Name: "arbitrarypenguin", + Type: "else", + Endpoints: []Endpoint{ + Endpoint{ + PublicURL: "http://else0:4321/v3/", + Region: "region0", + }, + }, + }, + }, +} + +// ExpectedUser is the token that should be parsed from TokenGetResponse. +var ExpectedUser = &User{ + ID: "a530fefc3d594c4ba2693a4ecd6be74e", + Name: "apiserver", + Roles: []Role{{"member"}, {"service"}}, + UserName: "apiserver", +} + +// TokenCreationResponse is a JSON response that contains ExpectedToken and ExpectedServiceCatalog. +const TokenCreationResponse = ` +{ + "access": { + "token": { + "issued_at": "2014-01-30T15:30:58.000000Z", + "expires": "2014-01-31T15:30:58Z", + "id": "aaaabbbbccccdddd", + "tenant": { + "description": "There are many tenants. This one is yours.", + "enabled": true, + "id": "fc394f2ab2df4114bde39905f800dc57", + "name": "test" + } + }, + "serviceCatalog": [ + { + "endpoints": [ + { + "publicURL": "http://something0:1234/v2/", + "region": "region0" + }, + { + "publicURL": "http://something1:1234/v2/", + "region": "region1" + } + ], + "type": "something", + "name": "inscrutablewalrus" + }, + { + "endpoints": [ + { + "publicURL": "http://else0:4321/v3/", + "region": "region0" + } + ], + "type": "else", + "name": "arbitrarypenguin" + } + ] + } +} +` + +// TokenGetResponse is a JSON response that contains ExpectedToken and ExpectedUser. +const TokenGetResponse = ` +{ + "access": { + "token": { + "issued_at": "2014-01-30T15:30:58.000000Z", + "expires": "2014-01-31T15:30:58Z", + "id": "aaaabbbbccccdddd", + "tenant": { + "description": "There are many tenants. This one is yours.", + "enabled": true, + "id": "fc394f2ab2df4114bde39905f800dc57", + "name": "test" + } + }, + "serviceCatalog": [], + "user": { + "id": "a530fefc3d594c4ba2693a4ecd6be74e", + "name": "apiserver", + "roles": [ + { + "name": "member" + }, + { + "name": "service" + } + ], + "roles_links": [], + "username": "apiserver" + } + } +}` + +// HandleTokenPost expects a POST against a /tokens handler, ensures that the request body has been +// constructed properly given certain auth options, and returns the result. +func HandleTokenPost(t *testing.T, requestJSON string) { + th.Mux.HandleFunc("/tokens", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + if requestJSON != "" { + th.TestJSONRequest(t, r, requestJSON) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, TokenCreationResponse) + }) +} + +// HandleTokenGet expects a Get against a /tokens handler, ensures that the request body has been +// constructed properly given certain auth options, and returns the result. +func HandleTokenGet(t *testing.T, token string) { + th.Mux.HandleFunc("/tokens/"+token, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "X-Auth-Token", thclient.TokenID) + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, TokenGetResponse) + }) +} + +// IsSuccessful ensures that a CreateResult was successful and contains the correct token and +// service catalog. +func IsSuccessful(t *testing.T, result CreateResult) { + token, err := result.ExtractToken() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, ExpectedToken, token) + + serviceCatalog, err := result.ExtractServiceCatalog() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, ExpectedServiceCatalog, serviceCatalog) +} + +// GetIsSuccessful ensures that a GetResult was successful and contains the correct token and +// User Info. +func GetIsSuccessful(t *testing.T, result GetResult) { + token, err := result.ExtractToken() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, ExpectedToken, token) + + user, err := result.ExtractUser() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, ExpectedUser, user) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/requests.go new file mode 100644 index 000000000..1f514386d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/requests.go @@ -0,0 +1,99 @@ +package tokens + +import ( + "fmt" + + "github.com/rackspace/gophercloud" +) + +// AuthOptionsBuilder describes any argument that may be passed to the Create call. +type AuthOptionsBuilder interface { + + // ToTokenCreateMap assembles the Create request body, returning an error if parameters are + // missing or inconsistent. + ToTokenCreateMap() (map[string]interface{}, error) +} + +// AuthOptions wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder +// interface. +type AuthOptions struct { + gophercloud.AuthOptions +} + +// WrapOptions embeds a root AuthOptions struct in a package-specific one. +func WrapOptions(original gophercloud.AuthOptions) AuthOptions { + return AuthOptions{AuthOptions: original} +} + +// ToTokenCreateMap converts AuthOptions into nested maps that can be serialized into a JSON +// request. +func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) { + // Error out if an unsupported auth option is present. + if auth.UserID != "" { + return nil, ErrUserIDProvided + } + if auth.APIKey != "" { + return nil, ErrAPIKeyProvided + } + if auth.DomainID != "" { + return nil, ErrDomainIDProvided + } + if auth.DomainName != "" { + return nil, ErrDomainNameProvided + } + + // Populate the request map. + authMap := make(map[string]interface{}) + + if auth.Username != "" { + if auth.Password != "" { + authMap["passwordCredentials"] = map[string]interface{}{ + "username": auth.Username, + "password": auth.Password, + } + } else { + return nil, ErrPasswordRequired + } + } else if auth.TokenID != "" { + authMap["token"] = map[string]interface{}{ + "id": auth.TokenID, + } + } else { + return nil, fmt.Errorf("You must provide either username/password or tenantID/token values.") + } + + if auth.TenantID != "" { + authMap["tenantId"] = auth.TenantID + } + if auth.TenantName != "" { + authMap["tenantName"] = auth.TenantName + } + + return map[string]interface{}{"auth": authMap}, nil +} + +// Create authenticates to the identity service and attempts to acquire a Token. +// If successful, the CreateResult +// Generally, rather than interact with this call directly, end users should call openstack.AuthenticatedClient(), +// which abstracts all of the gory details about navigating service catalogs and such. +func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) CreateResult { + request, err := auth.ToTokenCreateMap() + if err != nil { + return CreateResult{gophercloud.Result{Err: err}} + } + + var result CreateResult + _, result.Err = client.Post(CreateURL(client), request, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 203}, + }) + return result +} + +// Validates and retrieves information for user's token. +func Get(client *gophercloud.ServiceClient, token string) GetResult { + var result GetResult + _, result.Err = client.Get(GetURL(client, token), &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 203}, + }) + return result +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/results.go new file mode 100644 index 000000000..67c577b8d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/results.go @@ -0,0 +1,170 @@ +package tokens + +import ( + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/identity/v2/tenants" +) + +// Token provides only the most basic information related to an authentication token. +type Token struct { + // ID provides the primary means of identifying a user to the OpenStack API. + // OpenStack defines this field as an opaque value, so do not depend on its content. + // It is safe, however, to compare for equality. + ID string + + // ExpiresAt provides a timestamp in ISO 8601 format, indicating when the authentication token becomes invalid. + // After this point in time, future API requests made using this authentication token will respond with errors. + // Either the caller will need to reauthenticate manually, or more preferably, the caller should exploit automatic re-authentication. + // See the AuthOptions structure for more details. + ExpiresAt time.Time + + // Tenant provides information about the tenant to which this token grants access. + Tenant tenants.Tenant +} + +// Authorization need user info which can get from token authentication's response +type Role struct { + Name string `mapstructure:"name"` +} +type User struct { + ID string `mapstructure:"id"` + Name string `mapstructure:"name"` + UserName string `mapstructure:"username"` + Roles []Role `mapstructure:"roles"` +} + +// Endpoint represents a single API endpoint offered by a service. +// It provides the public and internal URLs, if supported, along with a region specifier, again if provided. +// The significance of the Region field will depend upon your provider. +// +// In addition, the interface offered by the service will have version information associated with it +// through the VersionId, VersionInfo, and VersionList fields, if provided or supported. +// +// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value (""). +type Endpoint struct { + TenantID string `mapstructure:"tenantId"` + PublicURL string `mapstructure:"publicURL"` + InternalURL string `mapstructure:"internalURL"` + AdminURL string `mapstructure:"adminURL"` + Region string `mapstructure:"region"` + VersionID string `mapstructure:"versionId"` + VersionInfo string `mapstructure:"versionInfo"` + VersionList string `mapstructure:"versionList"` +} + +// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing. +// Each class of service, such as cloud DNS or block storage services, will have a single +// CatalogEntry representing it. +// +// Note: when looking for the desired service, try, whenever possible, to key off the type field. +// Otherwise, you'll tie the representation of the service to a specific provider. +type CatalogEntry struct { + // Name will contain the provider-specified name for the service. + Name string `mapstructure:"name"` + + // Type will contain a type string if OpenStack defines a type for the service. + // Otherwise, for provider-specific services, the provider may assign their own type strings. + Type string `mapstructure:"type"` + + // Endpoints will let the caller iterate over all the different endpoints that may exist for + // the service. + Endpoints []Endpoint `mapstructure:"endpoints"` +} + +// ServiceCatalog provides a view into the service catalog from a previous, successful authentication. +type ServiceCatalog struct { + Entries []CatalogEntry +} + +// CreateResult defers the interpretation of a created token. +// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog. +type CreateResult struct { + gophercloud.Result +} + +// GetResult is the deferred response from a Get call, which is the same with a Created token. +// Use ExtractUser() to interpret it as a User. +type GetResult struct { + CreateResult +} + +// ExtractToken returns the just-created Token from a CreateResult. +func (result CreateResult) ExtractToken() (*Token, error) { + if result.Err != nil { + return nil, result.Err + } + + var response struct { + Access struct { + Token struct { + Expires string `mapstructure:"expires"` + ID string `mapstructure:"id"` + Tenant tenants.Tenant `mapstructure:"tenant"` + } `mapstructure:"token"` + } `mapstructure:"access"` + } + + err := mapstructure.Decode(result.Body, &response) + if err != nil { + return nil, err + } + + expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires) + if err != nil { + return nil, err + } + + return &Token{ + ID: response.Access.Token.ID, + ExpiresAt: expiresTs, + Tenant: response.Access.Token.Tenant, + }, nil +} + +// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token. +func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) { + if result.Err != nil { + return nil, result.Err + } + + var response struct { + Access struct { + Entries []CatalogEntry `mapstructure:"serviceCatalog"` + } `mapstructure:"access"` + } + + err := mapstructure.Decode(result.Body, &response) + if err != nil { + return nil, err + } + + return &ServiceCatalog{Entries: response.Access.Entries}, nil +} + +// createErr quickly packs an error in a CreateResult. +func createErr(err error) CreateResult { + return CreateResult{gophercloud.Result{Err: err}} +} + +// ExtractUser returns the User from a GetResult. +func (result GetResult) ExtractUser() (*User, error) { + if result.Err != nil { + return nil, result.Err + } + + var response struct { + Access struct { + User User `mapstructure:"user"` + } `mapstructure:"access"` + } + + err := mapstructure.Decode(result.Body, &response) + if err != nil { + return nil, err + } + + return &response.Access.User, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/urls.go new file mode 100644 index 000000000..ee1393299 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/tokens/urls.go @@ -0,0 +1,13 @@ +package tokens + +import "github.com/rackspace/gophercloud" + +// CreateURL generates the URL used to create new Tokens. +func CreateURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("tokens") +} + +// GetURL generates the URL used to Validate Tokens. +func GetURL(client *gophercloud.ServiceClient, token string) string { + return client.ServiceURL("tokens", token) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/doc.go new file mode 100644 index 000000000..82abcb9fc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/doc.go @@ -0,0 +1 @@ +package users diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/fixtures.go new file mode 100644 index 000000000..8941868dd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/fixtures.go @@ -0,0 +1,163 @@ +package users + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListUserResponse(t *testing.T) { + th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "users":[ + { + "id": "u1000", + "name": "John Smith", + "username": "jqsmith", + "email": "john.smith@example.org", + "enabled": true, + "tenant_id": "12345" + }, + { + "id": "u1001", + "name": "Jane Smith", + "username": "jqsmith", + "email": "jane.smith@example.org", + "enabled": true, + "tenant_id": "12345" + } + ] +} + `) + }) +} + +func mockCreateUserResponse(t *testing.T) { + th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "user": { + "name": "new_user", + "tenant_id": "12345", + "enabled": false, + "email": "new_user@foo.com" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "name": "new_user", + "tenant_id": "12345", + "enabled": false, + "email": "new_user@foo.com", + "id": "c39e3de9be2d4c779f1dfd6abacc176d" + } +} +`) + }) +} + +func mockGetUserResponse(t *testing.T) { + th.Mux.HandleFunc("/users/new_user", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "name": "new_user", + "tenant_id": "12345", + "enabled": false, + "email": "new_user@foo.com", + "id": "c39e3de9be2d4c779f1dfd6abacc176d" + } +} +`) + }) +} + +func mockUpdateUserResponse(t *testing.T) { + th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "user": { + "name": "new_name", + "enabled": true, + "email": "new_email@foo.com" + } +} +`) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "name": "new_name", + "tenant_id": "12345", + "enabled": true, + "email": "new_email@foo.com", + "id": "c39e3de9be2d4c779f1dfd6abacc176d" + } +} +`) + }) +} + +func mockDeleteUserResponse(t *testing.T) { + th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} + +func mockListRolesResponse(t *testing.T) { + th.Mux.HandleFunc("/tenants/1d8b6120dcc640fda4fc9194ffc80273/users/c39e3de9be2d4c779f1dfd6abacc176d/roles", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "roles": [ + { + "id": "9fe2ff9ee4384b1894a90878d3e92bab", + "name": "foo_role" + }, + { + "id": "1ea3d56793574b668e85960fbf651e13", + "name": "admin" + } + ] +} + `) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/requests.go new file mode 100644 index 000000000..88be45ecc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/requests.go @@ -0,0 +1,161 @@ +package users + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +func List(client *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return UserPage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, rootURL(client), createPage) +} + +// EnabledState represents whether the user is enabled or not. +type EnabledState *bool + +// Useful variables to use when creating or updating users. +var ( + iTrue = true + iFalse = false + + Enabled EnabledState = &iTrue + Disabled EnabledState = &iFalse +) + +// CommonOpts are the parameters that are shared between CreateOpts and +// UpdateOpts +type CommonOpts struct { + // Either a name or username is required. When provided, the value must be + // unique or a 409 conflict error will be returned. If you provide a name but + // omit a username, the latter will be set to the former; and vice versa. + Name, Username string + + // The ID of the tenant to which you want to assign this user. + TenantID string + + // Indicates whether this user is enabled or not. + Enabled EnabledState + + // The email address of this user. + Email string +} + +// CreateOpts represents the options needed when creating new users. +type CreateOpts CommonOpts + +// CreateOptsBuilder describes struct types that can be accepted by the Create call. +type CreateOptsBuilder interface { + ToUserCreateMap() (map[string]interface{}, error) +} + +// ToUserCreateMap assembles a request body based on the contents of a CreateOpts. +func (opts CreateOpts) ToUserCreateMap() (map[string]interface{}, error) { + m := make(map[string]interface{}) + + if opts.Name == "" && opts.Username == "" { + return m, errors.New("Either a Name or Username must be provided") + } + + if opts.Name != "" { + m["name"] = opts.Name + } + if opts.Username != "" { + m["username"] = opts.Username + } + if opts.Enabled != nil { + m["enabled"] = &opts.Enabled + } + if opts.Email != "" { + m["email"] = opts.Email + } + if opts.TenantID != "" { + m["tenant_id"] = opts.TenantID + } + + return map[string]interface{}{"user": m}, nil +} + +// Create is the operation responsible for creating new users. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToUserCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(rootURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + + return res +} + +// Get requests details on a single user, either by ID. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var result GetResult + _, result.Err = client.Get(ResourceURL(client, id), &result.Body, nil) + return result +} + +// UpdateOptsBuilder allows extensions to add additional attributes to the Update request. +type UpdateOptsBuilder interface { + ToUserUpdateMap() map[string]interface{} +} + +// UpdateOpts specifies the base attributes that may be updated on an existing server. +type UpdateOpts CommonOpts + +// ToUserUpdateMap formats an UpdateOpts structure into a request body. +func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} { + m := make(map[string]interface{}) + + if opts.Name != "" { + m["name"] = opts.Name + } + if opts.Username != "" { + m["username"] = opts.Username + } + if opts.Enabled != nil { + m["enabled"] = &opts.Enabled + } + if opts.Email != "" { + m["email"] = opts.Email + } + if opts.TenantID != "" { + m["tenant_id"] = opts.TenantID + } + + return map[string]interface{}{"user": m} +} + +// Update is the operation responsible for updating exist users by their UUID. +func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var result UpdateResult + reqBody := opts.ToUserUpdateMap() + _, result.Err = client.Put(ResourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return result +} + +// Delete is the operation responsible for permanently deleting an API user. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var result DeleteResult + _, result.Err = client.Delete(ResourceURL(client, id), nil) + return result +} + +func ListRoles(client *gophercloud.ServiceClient, tenantID, userID string) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return RolePage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, listRolesURL(client, tenantID, userID), createPage) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/results.go new file mode 100644 index 000000000..f531d5d02 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/results.go @@ -0,0 +1,128 @@ +package users + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// User represents a user resource that exists on the API. +type User struct { + // The UUID for this user. + ID string + + // The human name for this user. + Name string + + // The username for this user. + Username string + + // Indicates whether the user is enabled (true) or disabled (false). + Enabled bool + + // The email address for this user. + Email string + + // The ID of the tenant to which this user belongs. + TenantID string `mapstructure:"tenant_id"` +} + +// Role assigns specific responsibilities to users, allowing them to accomplish +// certain API operations whilst scoped to a service. +type Role struct { + // UUID of the role + ID string + + // Name of the role + Name string +} + +// UserPage is a single page of a User collection. +type UserPage struct { + pagination.SinglePageBase +} + +// RolePage is a single page of a user Role collection. +type RolePage struct { + pagination.SinglePageBase +} + +// IsEmpty determines whether or not a page of Tenants contains any results. +func (page UserPage) IsEmpty() (bool, error) { + users, err := ExtractUsers(page) + if err != nil { + return false, err + } + return len(users) == 0, nil +} + +// ExtractUsers returns a slice of Tenants contained in a single page of results. +func ExtractUsers(page pagination.Page) ([]User, error) { + casted := page.(UserPage).Body + var response struct { + Users []User `mapstructure:"users"` + } + + err := mapstructure.Decode(casted, &response) + return response.Users, err +} + +// IsEmpty determines whether or not a page of Tenants contains any results. +func (page RolePage) IsEmpty() (bool, error) { + users, err := ExtractRoles(page) + if err != nil { + return false, err + } + return len(users) == 0, nil +} + +// ExtractRoles returns a slice of Roles contained in a single page of results. +func ExtractRoles(page pagination.Page) ([]Role, error) { + casted := page.(RolePage).Body + var response struct { + Roles []Role `mapstructure:"roles"` + } + + err := mapstructure.Decode(casted, &response) + return response.Roles, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract interprets any commonResult as a User, if possible. +func (r commonResult) Extract() (*User, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + User User `mapstructure:"user"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.User, err +} + +// CreateResult represents the result of a Create operation +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a Get operation +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an Update operation +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a Delete operation +type DeleteResult struct { + commonResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/urls.go new file mode 100644 index 000000000..7ec4385d7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v2/users/urls.go @@ -0,0 +1,21 @@ +package users + +import "github.com/rackspace/gophercloud" + +const ( + tenantPath = "tenants" + userPath = "users" + rolePath = "roles" +) + +func ResourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(userPath, id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(userPath) +} + +func listRolesURL(c *gophercloud.ServiceClient, tenantID, userID string) string { + return c.ServiceURL(tenantPath, tenantID, userPath, userID, rolePath) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/doc.go new file mode 100644 index 000000000..85163949a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/doc.go @@ -0,0 +1,6 @@ +// Package endpoints provides information and interaction with the service +// endpoints API resource in the OpenStack Identity service. +// +// For more information, see: +// http://developer.openstack.org/api-ref-identity-v3.html#endpoints-v3 +package endpoints diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/errors.go new file mode 100644 index 000000000..854957ff9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/errors.go @@ -0,0 +1,21 @@ +package endpoints + +import "fmt" + +func requiredAttribute(attribute string) error { + return fmt.Errorf("You must specify %s for this endpoint.", attribute) +} + +var ( + // ErrAvailabilityRequired is reported if an Endpoint is created without an Availability. + ErrAvailabilityRequired = requiredAttribute("an availability") + + // ErrNameRequired is reported if an Endpoint is created without a Name. + ErrNameRequired = requiredAttribute("a name") + + // ErrURLRequired is reported if an Endpoint is created without a URL. + ErrURLRequired = requiredAttribute("a URL") + + // ErrServiceIDRequired is reported if an Endpoint is created without a ServiceID. + ErrServiceIDRequired = requiredAttribute("a serviceID") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/requests.go new file mode 100644 index 000000000..99a495d59 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/requests.go @@ -0,0 +1,123 @@ +package endpoints + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// EndpointOpts contains the subset of Endpoint attributes that should be used to create or update an Endpoint. +type EndpointOpts struct { + Availability gophercloud.Availability + Name string + Region string + URL string + ServiceID string +} + +// Create inserts a new Endpoint into the service catalog. +// Within EndpointOpts, Region may be omitted by being left as "", but all other fields are required. +func Create(client *gophercloud.ServiceClient, opts EndpointOpts) CreateResult { + // Redefined so that Region can be re-typed as a *string, which can be omitted from the JSON output. + type endpoint struct { + Interface string `json:"interface"` + Name string `json:"name"` + Region *string `json:"region,omitempty"` + URL string `json:"url"` + ServiceID string `json:"service_id"` + } + + type request struct { + Endpoint endpoint `json:"endpoint"` + } + + // Ensure that EndpointOpts is fully populated. + if opts.Availability == "" { + return createErr(ErrAvailabilityRequired) + } + if opts.Name == "" { + return createErr(ErrNameRequired) + } + if opts.URL == "" { + return createErr(ErrURLRequired) + } + if opts.ServiceID == "" { + return createErr(ErrServiceIDRequired) + } + + // Populate the request body. + reqBody := request{ + Endpoint: endpoint{ + Interface: string(opts.Availability), + Name: opts.Name, + URL: opts.URL, + ServiceID: opts.ServiceID, + }, + } + reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region) + + var result CreateResult + _, result.Err = client.Post(listURL(client), reqBody, &result.Body, nil) + return result +} + +// ListOpts allows finer control over the endpoints returned by a List call. +// All fields are optional. +type ListOpts struct { + Availability gophercloud.Availability `q:"interface"` + ServiceID string `q:"service_id"` + Page int `q:"page"` + PerPage int `q:"per_page"` +} + +// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria. +func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + u := listURL(client) + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return pagination.Pager{Err: err} + } + u += q.String() + createPage := func(r pagination.PageResult) pagination.Page { + return EndpointPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, u, createPage) +} + +// Update changes an existing endpoint with new data. +// All fields are optional in the provided EndpointOpts. +func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointOpts) UpdateResult { + type endpoint struct { + Interface *string `json:"interface,omitempty"` + Name *string `json:"name,omitempty"` + Region *string `json:"region,omitempty"` + URL *string `json:"url,omitempty"` + ServiceID *string `json:"service_id,omitempty"` + } + + type request struct { + Endpoint endpoint `json:"endpoint"` + } + + reqBody := request{Endpoint: endpoint{}} + reqBody.Endpoint.Interface = gophercloud.MaybeString(string(opts.Availability)) + reqBody.Endpoint.Name = gophercloud.MaybeString(opts.Name) + reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region) + reqBody.Endpoint.URL = gophercloud.MaybeString(opts.URL) + reqBody.Endpoint.ServiceID = gophercloud.MaybeString(opts.ServiceID) + + var result UpdateResult + _, result.Err = client.Request("PATCH", endpointURL(client, endpointID), gophercloud.RequestOpts{ + JSONBody: &reqBody, + JSONResponse: &result.Body, + OkCodes: []int{200}, + }) + return result +} + +// Delete removes an endpoint from the service catalog. +func Delete(client *gophercloud.ServiceClient, endpointID string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(endpointURL(client, endpointID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/results.go new file mode 100644 index 000000000..128112295 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/results.go @@ -0,0 +1,82 @@ +package endpoints + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete Endpoint. +// An error is returned if the original call or the extraction failed. +func (r commonResult) Extract() (*Endpoint, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Endpoint `json:"endpoint"` + } + + err := mapstructure.Decode(r.Body, &res) + + return &res.Endpoint, err +} + +// CreateResult is the deferred result of a Create call. +type CreateResult struct { + commonResult +} + +// createErr quickly wraps an error in a CreateResult. +func createErr(err error) CreateResult { + return CreateResult{commonResult{gophercloud.Result{Err: err}}} +} + +// UpdateResult is the deferred result of an Update call. +type UpdateResult struct { + commonResult +} + +// DeleteResult is the deferred result of an Delete call. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Endpoint describes the entry point for another service's API. +type Endpoint struct { + ID string `mapstructure:"id" json:"id"` + Availability gophercloud.Availability `mapstructure:"interface" json:"interface"` + Name string `mapstructure:"name" json:"name"` + Region string `mapstructure:"region" json:"region"` + ServiceID string `mapstructure:"service_id" json:"service_id"` + URL string `mapstructure:"url" json:"url"` +} + +// EndpointPage is a single page of Endpoint results. +type EndpointPage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if no Endpoints were returned. +func (p EndpointPage) IsEmpty() (bool, error) { + es, err := ExtractEndpoints(p) + if err != nil { + return true, err + } + return len(es) == 0, nil +} + +// ExtractEndpoints extracts an Endpoint slice from a Page. +func ExtractEndpoints(page pagination.Page) ([]Endpoint, error) { + var response struct { + Endpoints []Endpoint `mapstructure:"endpoints"` + } + + err := mapstructure.Decode(page.(EndpointPage).Body, &response) + + return response.Endpoints, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/urls.go new file mode 100644 index 000000000..547d7b102 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/endpoints/urls.go @@ -0,0 +1,11 @@ +package endpoints + +import "github.com/rackspace/gophercloud" + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("endpoints") +} + +func endpointURL(client *gophercloud.ServiceClient, endpointID string) string { + return client.ServiceURL("endpoints", endpointID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/doc.go new file mode 100644 index 000000000..bdbc674d6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/doc.go @@ -0,0 +1,3 @@ +// Package roles provides information and interaction with the roles API +// resource for the OpenStack Identity service. +package roles diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/requests.go new file mode 100644 index 000000000..d95c1e52f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/requests.go @@ -0,0 +1,50 @@ +package roles + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListAssignmentsOptsBuilder allows extensions to add additional parameters to +// the ListAssignments request. +type ListAssignmentsOptsBuilder interface { + ToRolesListAssignmentsQuery() (string, error) +} + +// ListAssignmentsOpts allows you to query the ListAssignments method. +// Specify one of or a combination of GroupId, RoleId, ScopeDomainId, ScopeProjectId, +// and/or UserId to search for roles assigned to corresponding entities. +// Effective lists effective assignments at the user, project, and domain level, +// allowing for the effects of group membership. +type ListAssignmentsOpts struct { + GroupId string `q:"group.id"` + RoleId string `q:"role.id"` + ScopeDomainId string `q:"scope.domain.id"` + ScopeProjectId string `q:"scope.project.id"` + UserId string `q:"user.id"` + Effective bool `q:"effective"` +} + +// ToRolesListAssignmentsQuery formats a ListAssignmentsOpts into a query string. +func (opts ListAssignmentsOpts) ToRolesListAssignmentsQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListAssignments enumerates the roles assigned to a specified resource. +func ListAssignments(client *gophercloud.ServiceClient, opts ListAssignmentsOptsBuilder) pagination.Pager { + url := listAssignmentsURL(client) + query, err := opts.ToRolesListAssignmentsQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + createPage := func(r pagination.PageResult) pagination.Page { + return RoleAssignmentsPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, url, createPage) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/results.go new file mode 100644 index 000000000..d25abd25d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/results.go @@ -0,0 +1,81 @@ +package roles + +import ( + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// RoleAssignment is the result of a role assignments query. +type RoleAssignment struct { + Role Role `json:"role,omitempty"` + Scope Scope `json:"scope,omitempty"` + User User `json:"user,omitempty"` + Group Group `json:"group,omitempty"` +} + +type Role struct { + ID string `json:"id,omitempty"` +} + +type Scope struct { + Domain Domain `json:"domain,omitempty"` + Project Project `json:"domain,omitempty"` +} + +type Domain struct { + ID string `json:"id,omitempty"` +} + +type Project struct { + ID string `json:"id,omitempty"` +} + +type User struct { + ID string `json:"id,omitempty"` +} + +type Group struct { + ID string `json:"id,omitempty"` +} + +// RoleAssignmentsPage is a single page of RoleAssignments results. +type RoleAssignmentsPage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if the page contains no results. +func (p RoleAssignmentsPage) IsEmpty() (bool, error) { + roleAssignments, err := ExtractRoleAssignments(p) + if err != nil { + return true, err + } + return len(roleAssignments) == 0, nil +} + +// NextPageURL uses the response's embedded link reference to navigate to the next page of results. +func (page RoleAssignmentsPage) NextPageURL() (string, error) { + type resp struct { + Links struct { + Next string `mapstructure:"next"` + } `mapstructure:"links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return r.Links.Next, nil +} + +// ExtractRoleAssignments extracts a slice of RoleAssignments from a Collection acquired from List. +func ExtractRoleAssignments(page pagination.Page) ([]RoleAssignment, error) { + var response struct { + RoleAssignments []RoleAssignment `mapstructure:"role_assignments"` + } + + err := mapstructure.Decode(page.(RoleAssignmentsPage).Body, &response) + return response.RoleAssignments, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/urls.go new file mode 100644 index 000000000..b009340d0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/roles/urls.go @@ -0,0 +1,7 @@ +package roles + +import "github.com/rackspace/gophercloud" + +func listAssignmentsURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("role_assignments") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/doc.go new file mode 100644 index 000000000..fa5641185 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/doc.go @@ -0,0 +1,3 @@ +// Package services provides information and interaction with the services API +// resource for the OpenStack Identity service. +package services diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/requests.go new file mode 100644 index 000000000..3ee924f3e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/requests.go @@ -0,0 +1,77 @@ +package services + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type response struct { + Service Service `json:"service"` +} + +// Create adds a new service of the requested type to the catalog. +func Create(client *gophercloud.ServiceClient, serviceType string) CreateResult { + type request struct { + Type string `json:"type"` + } + + req := request{Type: serviceType} + + var result CreateResult + _, result.Err = client.Post(listURL(client), req, &result.Body, nil) + return result +} + +// ListOpts allows you to query the List method. +type ListOpts struct { + ServiceType string `q:"type"` + PerPage int `q:"perPage"` + Page int `q:"page"` +} + +// List enumerates the services available to a specific user. +func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + u := listURL(client) + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return pagination.Pager{Err: err} + } + u += q.String() + createPage := func(r pagination.PageResult) pagination.Page { + return ServicePage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, u, createPage) +} + +// Get returns additional information about a service, given its ID. +func Get(client *gophercloud.ServiceClient, serviceID string) GetResult { + var result GetResult + _, result.Err = client.Get(serviceURL(client, serviceID), &result.Body, nil) + return result +} + +// Update changes the service type of an existing service. +func Update(client *gophercloud.ServiceClient, serviceID string, serviceType string) UpdateResult { + type request struct { + Type string `json:"type"` + } + + req := request{Type: serviceType} + + var result UpdateResult + _, result.Err = client.Request("PATCH", serviceURL(client, serviceID), gophercloud.RequestOpts{ + JSONBody: &req, + JSONResponse: &result.Body, + OkCodes: []int{200}, + }) + return result +} + +// Delete removes an existing service. +// It either deletes all associated endpoints, or fails until all endpoints are deleted. +func Delete(client *gophercloud.ServiceClient, serviceID string) DeleteResult { + var res DeleteResult + _, res.Err = client.Delete(serviceURL(client, serviceID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/results.go new file mode 100644 index 000000000..1d0d14128 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/results.go @@ -0,0 +1,80 @@ +package services + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete Service. +// An error is returned if the original call or the extraction failed. +func (r commonResult) Extract() (*Service, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Service `json:"service"` + } + + err := mapstructure.Decode(r.Body, &res) + + return &res.Service, err +} + +// CreateResult is the deferred result of a Create call. +type CreateResult struct { + commonResult +} + +// GetResult is the deferred result of a Get call. +type GetResult struct { + commonResult +} + +// UpdateResult is the deferred result of an Update call. +type UpdateResult struct { + commonResult +} + +// DeleteResult is the deferred result of an Delete call. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Service is the result of a list or information query. +type Service struct { + Description *string `json:"description,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` +} + +// ServicePage is a single page of Service results. +type ServicePage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if the page contains no results. +func (p ServicePage) IsEmpty() (bool, error) { + services, err := ExtractServices(p) + if err != nil { + return true, err + } + return len(services) == 0, nil +} + +// ExtractServices extracts a slice of Services from a Collection acquired from List. +func ExtractServices(page pagination.Page) ([]Service, error) { + var response struct { + Services []Service `mapstructure:"services"` + } + + err := mapstructure.Decode(page.(ServicePage).Body, &response) + return response.Services, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/urls.go new file mode 100644 index 000000000..85443a48a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/services/urls.go @@ -0,0 +1,11 @@ +package services + +import "github.com/rackspace/gophercloud" + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("services") +} + +func serviceURL(client *gophercloud.ServiceClient, serviceID string) string { + return client.ServiceURL("services", serviceID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/doc.go new file mode 100644 index 000000000..76ff5f473 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/doc.go @@ -0,0 +1,6 @@ +// Package tokens provides information and interaction with the token API +// resource for the OpenStack Identity service. +// +// For more information, see: +// http://developer.openstack.org/api-ref-identity-v3.html#tokens-v3 +package tokens diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go new file mode 100644 index 000000000..44761092b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go @@ -0,0 +1,72 @@ +package tokens + +import ( + "errors" + "fmt" +) + +func unacceptedAttributeErr(attribute string) error { + return fmt.Errorf("The base Identity V3 API does not accept authentication by %s", attribute) +} + +func redundantWithTokenErr(attribute string) error { + return fmt.Errorf("%s may not be provided when authenticating with a TokenID", attribute) +} + +func redundantWithUserID(attribute string) error { + return fmt.Errorf("%s may not be provided when authenticating with a UserID", attribute) +} + +var ( + // ErrAPIKeyProvided indicates that an APIKey was provided but can't be used. + ErrAPIKeyProvided = unacceptedAttributeErr("APIKey") + + // ErrTenantIDProvided indicates that a TenantID was provided but can't be used. + ErrTenantIDProvided = unacceptedAttributeErr("TenantID") + + // ErrTenantNameProvided indicates that a TenantName was provided but can't be used. + ErrTenantNameProvided = unacceptedAttributeErr("TenantName") + + // ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead. + ErrUsernameWithToken = redundantWithTokenErr("Username") + + // ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead. + ErrUserIDWithToken = redundantWithTokenErr("UserID") + + // ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead. + ErrDomainIDWithToken = redundantWithTokenErr("DomainID") + + // ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s + ErrDomainNameWithToken = redundantWithTokenErr("DomainName") + + // ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once. + ErrUsernameOrUserID = errors.New("Exactly one of Username and UserID must be provided for password authentication") + + // ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used. + ErrDomainIDWithUserID = redundantWithUserID("DomainID") + + // ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used. + ErrDomainNameWithUserID = redundantWithUserID("DomainName") + + // ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it. + // It may also indicate that both a DomainID and a DomainName were provided at once. + ErrDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName to authenticate by Username") + + // ErrMissingPassword indicates that no password was provided and no token is available. + ErrMissingPassword = errors.New("You must provide a password to authenticate") + + // ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present. + ErrScopeDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName in a Scope with ProjectName") + + // ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope. + ErrScopeProjectIDOrProjectName = errors.New("You must provide at most one of ProjectID or ProjectName in a Scope") + + // ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope. + ErrScopeProjectIDAlone = errors.New("ProjectID must be supplied alone in a Scope") + + // ErrScopeDomainName indicates that a DomainName was provided alone in a Scope. + ErrScopeDomainName = errors.New("DomainName must be supplied with a ProjectName or ProjectID in a Scope.") + + // ErrScopeEmpty indicates that no credentials were provided in a Scope. + ErrScopeEmpty = errors.New("You must provide either a Project or Domain in a Scope") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go new file mode 100644 index 000000000..d449ca36e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go @@ -0,0 +1,281 @@ +package tokens + +import ( + "net/http" + + "github.com/rackspace/gophercloud" +) + +// Scope allows a created token to be limited to a specific domain or project. +type Scope struct { + ProjectID string + ProjectName string + DomainID string + DomainName string +} + +func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string { + h := c.AuthenticatedHeaders() + h["X-Subject-Token"] = subjectToken + return h +} + +// Create authenticates and either generates a new token, or changes the Scope of an existing token. +func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope *Scope) CreateResult { + type domainReq struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + } + + type projectReq struct { + Domain *domainReq `json:"domain,omitempty"` + Name *string `json:"name,omitempty"` + ID *string `json:"id,omitempty"` + } + + type userReq struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Password string `json:"password"` + Domain *domainReq `json:"domain,omitempty"` + } + + type passwordReq struct { + User userReq `json:"user"` + } + + type tokenReq struct { + ID string `json:"id"` + } + + type identityReq struct { + Methods []string `json:"methods"` + Password *passwordReq `json:"password,omitempty"` + Token *tokenReq `json:"token,omitempty"` + } + + type scopeReq struct { + Domain *domainReq `json:"domain,omitempty"` + Project *projectReq `json:"project,omitempty"` + } + + type authReq struct { + Identity identityReq `json:"identity"` + Scope *scopeReq `json:"scope,omitempty"` + } + + type request struct { + Auth authReq `json:"auth"` + } + + // Populate the request structure based on the provided arguments. Create and return an error + // if insufficient or incompatible information is present. + var req request + + // Test first for unrecognized arguments. + if options.APIKey != "" { + return createErr(ErrAPIKeyProvided) + } + if options.TenantID != "" { + return createErr(ErrTenantIDProvided) + } + if options.TenantName != "" { + return createErr(ErrTenantNameProvided) + } + + if options.Password == "" { + if c.TokenID != "" { + // Because we aren't using password authentication, it's an error to also provide any of the user-based authentication + // parameters. + if options.Username != "" { + return createErr(ErrUsernameWithToken) + } + if options.UserID != "" { + return createErr(ErrUserIDWithToken) + } + if options.DomainID != "" { + return createErr(ErrDomainIDWithToken) + } + if options.DomainName != "" { + return createErr(ErrDomainNameWithToken) + } + + // Configure the request for Token authentication. + req.Auth.Identity.Methods = []string{"token"} + req.Auth.Identity.Token = &tokenReq{ + ID: c.TokenID, + } + } else { + // If no password or token ID are available, authentication can't continue. + return createErr(ErrMissingPassword) + } + } else { + // Password authentication. + req.Auth.Identity.Methods = []string{"password"} + + // At least one of Username and UserID must be specified. + if options.Username == "" && options.UserID == "" { + return createErr(ErrUsernameOrUserID) + } + + if options.Username != "" { + // If Username is provided, UserID may not be provided. + if options.UserID != "" { + return createErr(ErrUsernameOrUserID) + } + + // Either DomainID or DomainName must also be specified. + if options.DomainID == "" && options.DomainName == "" { + return createErr(ErrDomainIDOrDomainName) + } + + if options.DomainID != "" { + if options.DomainName != "" { + return createErr(ErrDomainIDOrDomainName) + } + + // Configure the request for Username and Password authentication with a DomainID. + req.Auth.Identity.Password = &passwordReq{ + User: userReq{ + Name: &options.Username, + Password: options.Password, + Domain: &domainReq{ID: &options.DomainID}, + }, + } + } + + if options.DomainName != "" { + // Configure the request for Username and Password authentication with a DomainName. + req.Auth.Identity.Password = &passwordReq{ + User: userReq{ + Name: &options.Username, + Password: options.Password, + Domain: &domainReq{Name: &options.DomainName}, + }, + } + } + } + + if options.UserID != "" { + // If UserID is specified, neither DomainID nor DomainName may be. + if options.DomainID != "" { + return createErr(ErrDomainIDWithUserID) + } + if options.DomainName != "" { + return createErr(ErrDomainNameWithUserID) + } + + // Configure the request for UserID and Password authentication. + req.Auth.Identity.Password = &passwordReq{ + User: userReq{ID: &options.UserID, Password: options.Password}, + } + } + } + + // Add a "scope" element if a Scope has been provided. + if scope != nil { + if scope.ProjectName != "" { + // ProjectName provided: either DomainID or DomainName must also be supplied. + // ProjectID may not be supplied. + if scope.DomainID == "" && scope.DomainName == "" { + return createErr(ErrScopeDomainIDOrDomainName) + } + if scope.ProjectID != "" { + return createErr(ErrScopeProjectIDOrProjectName) + } + + if scope.DomainID != "" { + // ProjectName + DomainID + req.Auth.Scope = &scopeReq{ + Project: &projectReq{ + Name: &scope.ProjectName, + Domain: &domainReq{ID: &scope.DomainID}, + }, + } + } + + if scope.DomainName != "" { + // ProjectName + DomainName + req.Auth.Scope = &scopeReq{ + Project: &projectReq{ + Name: &scope.ProjectName, + Domain: &domainReq{Name: &scope.DomainName}, + }, + } + } + } else if scope.ProjectID != "" { + // ProjectID provided. ProjectName, DomainID, and DomainName may not be provided. + if scope.DomainID != "" { + return createErr(ErrScopeProjectIDAlone) + } + if scope.DomainName != "" { + return createErr(ErrScopeProjectIDAlone) + } + + // ProjectID + req.Auth.Scope = &scopeReq{ + Project: &projectReq{ID: &scope.ProjectID}, + } + } else if scope.DomainID != "" { + // DomainID provided. ProjectID, ProjectName, and DomainName may not be provided. + if scope.DomainName != "" { + return createErr(ErrScopeDomainIDOrDomainName) + } + + // DomainID + req.Auth.Scope = &scopeReq{ + Domain: &domainReq{ID: &scope.DomainID}, + } + } else if scope.DomainName != "" { + return createErr(ErrScopeDomainName) + } else { + return createErr(ErrScopeEmpty) + } + } + + var result CreateResult + var response *http.Response + response, result.Err = c.Post(tokenURL(c), req, &result.Body, nil) + if result.Err != nil { + return result + } + result.Header = response.Header + return result +} + +// Get validates and retrieves information about another token. +func Get(c *gophercloud.ServiceClient, token string) GetResult { + var result GetResult + var response *http.Response + response, result.Err = c.Get(tokenURL(c), &result.Body, &gophercloud.RequestOpts{ + MoreHeaders: subjectTokenHeaders(c, token), + OkCodes: []int{200, 203}, + }) + if result.Err != nil { + return result + } + result.Header = response.Header + return result +} + +// Validate determines if a specified token is valid or not. +func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { + response, err := c.Request("HEAD", tokenURL(c), gophercloud.RequestOpts{ + MoreHeaders: subjectTokenHeaders(c, token), + OkCodes: []int{204, 404}, + }) + if err != nil { + return false, err + } + + return response.StatusCode == 204, nil +} + +// Revoke immediately makes specified token invalid. +func Revoke(c *gophercloud.ServiceClient, token string) RevokeResult { + var res RevokeResult + _, res.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{ + MoreHeaders: subjectTokenHeaders(c, token), + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/results.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/results.go new file mode 100644 index 000000000..d134f7d4d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/results.go @@ -0,0 +1,139 @@ +package tokens + +import ( + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" +) + +// Endpoint represents a single API endpoint offered by a service. +// It matches either a public, internal or admin URL. +// If supported, it contains a region specifier, again if provided. +// The significance of the Region field will depend upon your provider. +type Endpoint struct { + ID string `mapstructure:"id"` + Region string `mapstructure:"region"` + Interface string `mapstructure:"interface"` + URL string `mapstructure:"url"` +} + +// CatalogEntry provides a type-safe interface to an Identity API V3 service catalog listing. +// Each class of service, such as cloud DNS or block storage services, could have multiple +// CatalogEntry representing it (one by interface type, e.g public, admin or internal). +// +// Note: when looking for the desired service, try, whenever possible, to key off the type field. +// Otherwise, you'll tie the representation of the service to a specific provider. +type CatalogEntry struct { + + // Service ID + ID string `mapstructure:"id"` + + // Name will contain the provider-specified name for the service. + Name string `mapstructure:"name"` + + // Type will contain a type string if OpenStack defines a type for the service. + // Otherwise, for provider-specific services, the provider may assign their own type strings. + Type string `mapstructure:"type"` + + // Endpoints will let the caller iterate over all the different endpoints that may exist for + // the service. + Endpoints []Endpoint `mapstructure:"endpoints"` +} + +// ServiceCatalog provides a view into the service catalog from a previous, successful authentication. +type ServiceCatalog struct { + Entries []CatalogEntry +} + +// commonResult is the deferred result of a Create or a Get call. +type commonResult struct { + gophercloud.Result +} + +// Extract is a shortcut for ExtractToken. +// This function is deprecated and still present for backward compatibility. +func (r commonResult) Extract() (*Token, error) { + return r.ExtractToken() +} + +// ExtractToken interprets a commonResult as a Token. +func (r commonResult) ExtractToken() (*Token, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Token struct { + ExpiresAt string `mapstructure:"expires_at"` + } `mapstructure:"token"` + } + + var token Token + + // Parse the token itself from the stored headers. + token.ID = r.Header.Get("X-Subject-Token") + + err := mapstructure.Decode(r.Body, &response) + if err != nil { + return nil, err + } + + // Attempt to parse the timestamp. + token.ExpiresAt, err = time.Parse(gophercloud.RFC3339Milli, response.Token.ExpiresAt) + + return &token, err +} + +// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token. +func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) { + if result.Err != nil { + return nil, result.Err + } + + var response struct { + Token struct { + Entries []CatalogEntry `mapstructure:"catalog"` + } `mapstructure:"token"` + } + + err := mapstructure.Decode(result.Body, &response) + if err != nil { + return nil, err + } + + return &ServiceCatalog{Entries: response.Token.Entries}, nil +} + +// CreateResult defers the interpretation of a created token. +// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog. +type CreateResult struct { + commonResult +} + +// createErr quickly creates a CreateResult that reports an error. +func createErr(err error) CreateResult { + return CreateResult{ + commonResult: commonResult{Result: gophercloud.Result{Err: err}}, + } +} + +// GetResult is the deferred response from a Get call. +type GetResult struct { + commonResult +} + +// RevokeResult is the deferred response from a Revoke call. +type RevokeResult struct { + commonResult +} + +// Token is a string that grants a user access to a controlled set of services in an OpenStack provider. +// Each Token is valid for a set length of time. +type Token struct { + // ID is the issued token. + ID string + + // ExpiresAt is the timestamp at which this token will no longer be accepted. + ExpiresAt time.Time +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/urls.go new file mode 100644 index 000000000..360b60a82 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/urls.go @@ -0,0 +1,7 @@ +package tokens + +import "github.com/rackspace/gophercloud" + +func tokenURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("auth", "tokens") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/doc.go new file mode 100644 index 000000000..0208ee20e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/doc.go @@ -0,0 +1,4 @@ +// Package apiversions provides information and interaction with the different +// API versions for the OpenStack Neutron service. This functionality is not +// restricted to this particular version. +package apiversions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/errors.go new file mode 100644 index 000000000..76bdb14f7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/errors.go @@ -0,0 +1 @@ +package apiversions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/requests.go new file mode 100644 index 000000000..9fb6de141 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/requests.go @@ -0,0 +1,21 @@ +package apiversions + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListVersions lists all the Neutron API versions available to end-users +func ListVersions(c *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(c, apiVersionsURL(c), func(r pagination.PageResult) pagination.Page { + return APIVersionPage{pagination.SinglePageBase(r)} + }) +} + +// ListVersionResources lists all of the different API resources for a particular +// API versions. Typical resources for Neutron might be: networks, subnets, etc. +func ListVersionResources(c *gophercloud.ServiceClient, v string) pagination.Pager { + return pagination.NewPager(c, apiInfoURL(c, v), func(r pagination.PageResult) pagination.Page { + return APIVersionResourcePage{pagination.SinglePageBase(r)} + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/results.go new file mode 100644 index 000000000..97159341f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/results.go @@ -0,0 +1,77 @@ +package apiversions + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud/pagination" +) + +// APIVersion represents an API version for Neutron. It contains the status of +// the API, and its unique ID. +type APIVersion struct { + Status string `mapstructure:"status" json:"status"` + ID string `mapstructure:"id" json:"id"` +} + +// APIVersionPage is the page returned by a pager when traversing over a +// collection of API versions. +type APIVersionPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an APIVersionPage struct is empty. +func (r APIVersionPage) IsEmpty() (bool, error) { + is, err := ExtractAPIVersions(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractAPIVersions takes a collection page, extracts all of the elements, +// and returns them a slice of APIVersion structs. It is effectively a cast. +func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) { + var resp struct { + Versions []APIVersion `mapstructure:"versions"` + } + + err := mapstructure.Decode(page.(APIVersionPage).Body, &resp) + + return resp.Versions, err +} + +// APIVersionResource represents a generic API resource. It contains the name +// of the resource and its plural collection name. +type APIVersionResource struct { + Name string `mapstructure:"name" json:"name"` + Collection string `mapstructure:"collection" json:"collection"` +} + +// APIVersionResourcePage is a concrete type which embeds the common +// SinglePageBase struct, and is used when traversing API versions collections. +type APIVersionResourcePage struct { + pagination.SinglePageBase +} + +// IsEmpty is a concrete function which indicates whether an +// APIVersionResourcePage is empty or not. +func (r APIVersionResourcePage) IsEmpty() (bool, error) { + is, err := ExtractVersionResources(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractVersionResources accepts a Page struct, specifically a +// APIVersionResourcePage struct, and extracts the elements into a slice of +// APIVersionResource structs. In other words, the collection is mapped into +// a relevant slice. +func ExtractVersionResources(page pagination.Page) ([]APIVersionResource, error) { + var resp struct { + APIVersionResources []APIVersionResource `mapstructure:"resources"` + } + + err := mapstructure.Decode(page.(APIVersionResourcePage).Body, &resp) + + return resp.APIVersionResources, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/urls.go new file mode 100644 index 000000000..58aa2b61f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/apiversions/urls.go @@ -0,0 +1,15 @@ +package apiversions + +import ( + "strings" + + "github.com/rackspace/gophercloud" +) + +func apiVersionsURL(c *gophercloud.ServiceClient) string { + return c.Endpoint +} + +func apiInfoURL(c *gophercloud.ServiceClient, version string) string { + return c.Endpoint + strings.TrimRight(version, "/") + "/" +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/common/common_tests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/common/common_tests.go new file mode 100644 index 000000000..41603510d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/common/common_tests.go @@ -0,0 +1,14 @@ +package common + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/testhelper/client" +) + +const TokenID = client.TokenID + +func ServiceClient() *gophercloud.ServiceClient { + sc := client.ServiceClient() + sc.ResourceBase = sc.Endpoint + "v2.0/" + return sc +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/delegate.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/delegate.go new file mode 100644 index 000000000..d08e1fda9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/delegate.go @@ -0,0 +1,41 @@ +package extensions + +import ( + "github.com/rackspace/gophercloud" + common "github.com/rackspace/gophercloud/openstack/common/extensions" + "github.com/rackspace/gophercloud/pagination" +) + +// Extension is a single OpenStack extension. +type Extension struct { + common.Extension +} + +// GetResult wraps a GetResult from common. +type GetResult struct { + common.GetResult +} + +// ExtractExtensions interprets a Page as a slice of Extensions. +func ExtractExtensions(page pagination.Page) ([]Extension, error) { + inner, err := common.ExtractExtensions(page) + if err != nil { + return nil, err + } + outer := make([]Extension, len(inner)) + for index, ext := range inner { + outer[index] = Extension{ext} + } + return outer, nil +} + +// Get retrieves information for a specific extension using its alias. +func Get(c *gophercloud.ServiceClient, alias string) GetResult { + return GetResult{common.Get(c, alias)} +} + +// List returns a Pager which allows you to iterate over the full collection of extensions. +// It does not accept query parameters. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return common.List(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/doc.go new file mode 100644 index 000000000..dad3a844f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/doc.go @@ -0,0 +1,3 @@ +// Package external provides information and interaction with the external +// extension for the OpenStack Networking service. +package external diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/requests.go new file mode 100644 index 000000000..097ae37f2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/requests.go @@ -0,0 +1,69 @@ +package external + +import ( + "time" + + "github.com/rackspace/gophercloud/openstack/networking/v2/networks" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +// CreateOpts is the structure used when creating new external network +// resources. It embeds networks.CreateOpts and so inherits all of its required +// and optional fields, with the addition of the External field. +type CreateOpts struct { + Parent networks.CreateOpts + External bool +} + +// ToNetworkCreateMap casts a CreateOpts struct to a map. +func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) { + + // DO NOT REMOVE. Though this line seemingly does nothing of value, it is a + // splint to prevent the unit test from failing on Go Tip. We suspect it is a + // compiler issue that will hopefully be worked out prior to our next release. + // Again, for all the unit tests to pass, this line is necessary and sufficient + // at the moment. We should reassess after the Go 1.5 release to determine + // if this line is still needed. + time.Sleep(0 * time.Millisecond) + + outer, err := o.Parent.ToNetworkCreateMap() + if err != nil { + return nil, err + } + + outer["network"].(map[string]interface{})["router:external"] = o.External + + return outer, nil +} + +// UpdateOpts is the structure used when updating existing external network +// resources. It embeds networks.UpdateOpts and so inherits all of its required +// and optional fields, with the addition of the External field. +type UpdateOpts struct { + Parent networks.UpdateOpts + External bool +} + +// ToNetworkUpdateMap casts an UpdateOpts struct to a map. +func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) { + outer, err := o.Parent.ToNetworkUpdateMap() + if err != nil { + return nil, err + } + + outer["network"].(map[string]interface{})["router:external"] = o.External + + return outer, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/results.go new file mode 100644 index 000000000..54dbf4bb6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external/results.go @@ -0,0 +1,81 @@ +package external + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud/openstack/networking/v2/networks" + "github.com/rackspace/gophercloud/pagination" +) + +// NetworkExternal represents a decorated form of a Network with based on the +// "external-net" extension. +type NetworkExternal struct { + // UUID for the network + ID string `mapstructure:"id" json:"id"` + + // Human-readable name for the network. Might not be unique. + Name string `mapstructure:"name" json:"name"` + + // The administrative state of network. If false (down), the network does not forward packets. + AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"` + + // Indicates whether network is currently operational. Possible values include + // `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values. + Status string `mapstructure:"status" json:"status"` + + // Subnets associated with this network. + Subnets []string `mapstructure:"subnets" json:"subnets"` + + // Owner of network. Only admin users can specify a tenant_id other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` + + // Specifies whether the network resource can be accessed by any tenant or not. + Shared bool `mapstructure:"shared" json:"shared"` + + // Specifies whether the network is an external network or not. + External bool `mapstructure:"router:external" json:"router:external"` +} + +func commonExtract(e error, response interface{}) (*NetworkExternal, error) { + if e != nil { + return nil, e + } + + var res struct { + Network *NetworkExternal `json:"network"` + } + + err := mapstructure.Decode(response, &res) + + return res.Network, err +} + +// ExtractGet decorates a GetResult struct returned from a networks.Get() +// function with extended attributes. +func ExtractGet(r networks.GetResult) (*NetworkExternal, error) { + return commonExtract(r.Err, r.Body) +} + +// ExtractCreate decorates a CreateResult struct returned from a networks.Create() +// function with extended attributes. +func ExtractCreate(r networks.CreateResult) (*NetworkExternal, error) { + return commonExtract(r.Err, r.Body) +} + +// ExtractUpdate decorates a UpdateResult struct returned from a +// networks.Update() function with extended attributes. +func ExtractUpdate(r networks.UpdateResult) (*NetworkExternal, error) { + return commonExtract(r.Err, r.Body) +} + +// ExtractList accepts a Page struct, specifically a NetworkPage struct, and +// extracts the elements into a slice of NetworkExternal structs. In other +// words, a generic collection is mapped into a relevant slice. +func ExtractList(page pagination.Page) ([]NetworkExternal, error) { + var resp struct { + Networks []NetworkExternal `mapstructure:"networks" json:"networks"` + } + + err := mapstructure.Decode(page.(networks.NetworkPage).Body, &resp) + + return resp.Networks, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/doc.go new file mode 100644 index 000000000..3ec450a7b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/doc.go @@ -0,0 +1,3 @@ +// Package fwaas provides information and interaction with the Firewall +// as a Service extension for the OpenStack Networking service. +package fwaas diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/errors.go new file mode 100644 index 000000000..dd92bb20d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/errors.go @@ -0,0 +1,11 @@ +package firewalls + +import "fmt" + +func err(str string) error { + return fmt.Errorf("%s", str) +} + +var ( + errPolicyRequired = err("A policy ID is required") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/requests.go new file mode 100644 index 000000000..12d587f38 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/requests.go @@ -0,0 +1,216 @@ +package firewalls + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Shared gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Yes` and `No` enums. +type Shared *bool + +// Convenience vars for AdminStateUp and Shared values. +var ( + iTrue = true + iFalse = false + Up AdminState = &iTrue + Down AdminState = &iFalse + Yes Shared = &iTrue + No Shared = &iFalse +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToFirewallListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the firewall attributes you want to see returned. SortKey allows you to sort +// by a particular firewall attribute. SortDir sets the direction, and is either +// `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + TenantID string `q:"tenant_id"` + Name string `q:"name"` + Description string `q:"description"` + AdminStateUp bool `q:"admin_state_up"` + Shared bool `q:"shared"` + PolicyID string `q:"firewall_policy_id"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToFirewallListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToFirewallListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// firewalls. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +// +// Default policy settings return only those firewalls that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + + if opts != nil { + query, err := opts.ToFirewallListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return FirewallPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToFirewallCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains all the values needed to create a new firewall. +type CreateOpts struct { + // Only required if the caller has an admin role and wants to create a firewall + // for another tenant. + TenantID string + Name string + Description string + AdminStateUp *bool + Shared *bool + PolicyID string +} + +// ToFirewallCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToFirewallCreateMap() (map[string]interface{}, error) { + if opts.PolicyID == "" { + return nil, errPolicyRequired + } + + f := make(map[string]interface{}) + + if opts.TenantID != "" { + f["tenant_id"] = opts.TenantID + } + if opts.Name != "" { + f["name"] = opts.Name + } + if opts.Description != "" { + f["description"] = opts.Description + } + if opts.Shared != nil { + f["shared"] = *opts.Shared + } + if opts.AdminStateUp != nil { + f["admin_state_up"] = *opts.AdminStateUp + } + if opts.PolicyID != "" { + f["firewall_policy_id"] = opts.PolicyID + } + + return map[string]interface{}{"firewall": f}, nil +} + +// Create accepts a CreateOpts struct and uses the values to create a new firewall +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToFirewallCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular firewall based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToFirewallUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts contains the values used when updating a firewall. +type UpdateOpts struct { + // Name of the firewall. + Name string + Description string + AdminStateUp *bool + Shared *bool + PolicyID string +} + +// ToFirewallUpdateMap casts a CreateOpts struct to a map. +func (opts UpdateOpts) ToFirewallUpdateMap() (map[string]interface{}, error) { + f := make(map[string]interface{}) + + if opts.Name != "" { + f["name"] = opts.Name + } + if opts.Description != "" { + f["description"] = opts.Description + } + if opts.Shared != nil { + f["shared"] = *opts.Shared + } + if opts.AdminStateUp != nil { + f["admin_state_up"] = *opts.AdminStateUp + } + if opts.PolicyID != "" { + f["firewall_policy_id"] = opts.PolicyID + } + + return map[string]interface{}{"firewall": f}, nil +} + +// Update allows firewalls to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToFirewallUpdateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Delete will permanently delete a particular firewall based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/results.go new file mode 100644 index 000000000..a8c76eef2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/results.go @@ -0,0 +1,101 @@ +package firewalls + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type Firewall struct { + ID string `json:"id" mapstructure:"id"` + Name string `json:"name" mapstructure:"name"` + Description string `json:"description" mapstructure:"description"` + AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"` + Status string `json:"status" mapstructure:"status"` + PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"` + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a firewall. +func (r commonResult) Extract() (*Firewall, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Firewall *Firewall `json:"firewall"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Firewall, err +} + +// FirewallPage is the page returned by a pager when traversing over a +// collection of firewalls. +type FirewallPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of firewalls has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p FirewallPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"firewalls_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a FirewallPage struct is empty. +func (p FirewallPage) IsEmpty() (bool, error) { + is, err := ExtractFirewalls(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractFirewalls accepts a Page struct, specifically a RouterPage struct, +// and extracts the elements into a slice of Router structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractFirewalls(page pagination.Page) ([]Firewall, error) { + var resp struct { + Firewalls []Firewall `mapstructure:"firewalls" json:"firewalls"` + } + + err := mapstructure.Decode(page.(FirewallPage).Body, &resp) + + return resp.Firewalls, err +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/urls.go new file mode 100644 index 000000000..4dde53005 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls/urls.go @@ -0,0 +1,16 @@ +package firewalls + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "fw" + resourcePath = "firewalls" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/requests.go new file mode 100644 index 000000000..fe07d9abb --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/requests.go @@ -0,0 +1,243 @@ +package policies + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Binary gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Yes` and `No` enums +type Binary *bool + +// Convenience vars for Audited and Shared values. +var ( + iTrue = true + iFalse = false + Yes Binary = &iTrue + No Binary = &iFalse +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToPolicyListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the firewall policy attributes you want to see returned. SortKey allows you +// to sort by a particular firewall policy attribute. SortDir sets the direction, +// and is either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + TenantID string `q:"tenant_id"` + Name string `q:"name"` + Description string `q:"description"` + Shared bool `q:"shared"` + Audited bool `q:"audited"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToPolicyListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToPolicyListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// firewall policies. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +// +// Default policy settings return only those firewall policies that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + + if opts != nil { + query, err := opts.ToPolicyListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return PolicyPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToPolicyCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains all the values needed to create a new firewall policy. +type CreateOpts struct { + // Only required if the caller has an admin role and wants to create a firewall policy + // for another tenant. + TenantID string + Name string + Description string + Shared *bool + Audited *bool + Rules []string +} + +// ToPolicyCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToPolicyCreateMap() (map[string]interface{}, error) { + p := make(map[string]interface{}) + + if opts.TenantID != "" { + p["tenant_id"] = opts.TenantID + } + if opts.Name != "" { + p["name"] = opts.Name + } + if opts.Description != "" { + p["description"] = opts.Description + } + if opts.Shared != nil { + p["shared"] = *opts.Shared + } + if opts.Audited != nil { + p["audited"] = *opts.Audited + } + if opts.Rules != nil { + p["firewall_rules"] = opts.Rules + } + + return map[string]interface{}{"firewall_policy": p}, nil +} + +// Create accepts a CreateOpts struct and uses the values to create a new firewall policy +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToPolicyCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular firewall policy based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToPolicyUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts contains the values used when updating a firewall policy. +type UpdateOpts struct { + // Name of the firewall policy. + Name string + Description string + Shared *bool + Audited *bool + Rules []string +} + +// ToPolicyUpdateMap casts a CreateOpts struct to a map. +func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) { + p := make(map[string]interface{}) + + if opts.Name != "" { + p["name"] = opts.Name + } + if opts.Description != "" { + p["description"] = opts.Description + } + if opts.Shared != nil { + p["shared"] = *opts.Shared + } + if opts.Audited != nil { + p["audited"] = *opts.Audited + } + if opts.Rules != nil { + p["firewall_rules"] = opts.Rules + } + + return map[string]interface{}{"firewall_policy": p}, nil +} + +// Update allows firewall policies to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToPolicyUpdateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Delete will permanently delete a particular firewall policy based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} + +func InsertRule(c *gophercloud.ServiceClient, policyID, ruleID, beforeID, afterID string) error { + type request struct { + RuleId string `json:"firewall_rule_id"` + Before string `json:"insert_before,omitempty"` + After string `json:"insert_after,omitempty"` + } + + reqBody := request{ + RuleId: ruleID, + Before: beforeID, + After: afterID, + } + + // Send request to API + var res commonResult + _, res.Err = c.Put(insertURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res.Err +} + +func RemoveRule(c *gophercloud.ServiceClient, policyID, ruleID string) error { + type request struct { + RuleId string `json:"firewall_rule_id"` + } + + reqBody := request{ + RuleId: ruleID, + } + + // Send request to API + var res commonResult + _, res.Err = c.Put(removeURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res.Err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/results.go new file mode 100644 index 000000000..a9a0c358d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/results.go @@ -0,0 +1,101 @@ +package policies + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type Policy struct { + ID string `json:"id" mapstructure:"id"` + Name string `json:"name" mapstructure:"name"` + Description string `json:"description" mapstructure:"description"` + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + Audited bool `json:"audited" mapstructure:"audited"` + Shared bool `json:"shared" mapstructure:"shared"` + Rules []string `json:"firewall_rules,omitempty" mapstructure:"firewall_rules"` +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a firewall policy. +func (r commonResult) Extract() (*Policy, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Policy *Policy `json:"firewall_policy" mapstructure:"firewall_policy"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Policy, err +} + +// PolicyPage is the page returned by a pager when traversing over a +// collection of firewall policies. +type PolicyPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of firewall policies has +// reached the end of a page and the pager seeks to traverse over a new one. +// In order to do this, it needs to construct the next page's URL. +func (p PolicyPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"firewall_policies_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a PolicyPage struct is empty. +func (p PolicyPage) IsEmpty() (bool, error) { + is, err := ExtractPolicies(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractPolicies accepts a Page struct, specifically a RouterPage struct, +// and extracts the elements into a slice of Router structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractPolicies(page pagination.Page) ([]Policy, error) { + var resp struct { + Policies []Policy `mapstructure:"firewall_policies" json:"firewall_policies"` + } + + err := mapstructure.Decode(page.(PolicyPage).Body, &resp) + + return resp.Policies, err +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/urls.go new file mode 100644 index 000000000..27ea9ae61 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies/urls.go @@ -0,0 +1,26 @@ +package policies + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "fw" + resourcePath = "firewall_policies" + insertPath = "insert_rule" + removePath = "remove_rule" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} + +func insertURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id, insertPath) +} + +func removeURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id, removePath) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/errors.go new file mode 100644 index 000000000..0b29d39fd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/errors.go @@ -0,0 +1,12 @@ +package rules + +import "fmt" + +func err(str string) error { + return fmt.Errorf("%s", str) +} + +var ( + errProtocolRequired = err("A protocol is required (tcp, udp, icmp or any)") + errActionRequired = err("An action is required (allow or deny)") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/requests.go new file mode 100644 index 000000000..57a0e8baf --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/requests.go @@ -0,0 +1,285 @@ +package rules + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Binary gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Yes` and `No` enums +type Binary *bool + +// Convenience vars for Enabled and Shared values. +var ( + iTrue = true + iFalse = false + Yes Binary = &iTrue + No Binary = &iFalse +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToRuleListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the Firewall rule attributes you want to see returned. SortKey allows you to +// sort by a particular firewall rule attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + TenantID string `q:"tenant_id"` + Name string `q:"name"` + Description string `q:"description"` + Protocol string `q:"protocol"` + Action string `q:"action"` + IPVersion int `q:"ip_version"` + SourceIPAddress string `q:"source_ip_address"` + DestinationIPAddress string `q:"destination_ip_address"` + SourcePort string `q:"source_port"` + DestinationPort string `q:"destination_port"` + Enabled bool `q:"enabled"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToRuleListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToRuleListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// firewall rules. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +// +// Default policy settings return only those firewall rules that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + + if opts != nil { + query, err := opts.ToRuleListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return RulePage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToRuleCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains all the values needed to create a new firewall rule. +type CreateOpts struct { + // Mandatory for create + Protocol string + Action string + // Optional + TenantID string + Name string + Description string + IPVersion int + SourceIPAddress string + DestinationIPAddress string + SourcePort string + DestinationPort string + Shared *bool + Enabled *bool +} + +// ToRuleCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) { + if opts.Protocol == "" { + return nil, errProtocolRequired + } + + if opts.Action == "" { + return nil, errActionRequired + } + + r := make(map[string]interface{}) + + r["protocol"] = opts.Protocol + r["action"] = opts.Action + + if opts.TenantID != "" { + r["tenant_id"] = opts.TenantID + } + if opts.Name != "" { + r["name"] = opts.Name + } + if opts.Description != "" { + r["description"] = opts.Description + } + if opts.IPVersion != 0 { + r["ip_version"] = opts.IPVersion + } + if opts.SourceIPAddress != "" { + r["source_ip_address"] = opts.SourceIPAddress + } + if opts.DestinationIPAddress != "" { + r["destination_ip_address"] = opts.DestinationIPAddress + } + if opts.SourcePort != "" { + r["source_port"] = opts.SourcePort + } + if opts.DestinationPort != "" { + r["destination_port"] = opts.DestinationPort + } + if opts.Shared != nil { + r["shared"] = *opts.Shared + } + if opts.Enabled != nil { + r["enabled"] = *opts.Enabled + } + + return map[string]interface{}{"firewall_rule": r}, nil +} + +// Create accepts a CreateOpts struct and uses the values to create a new firewall rule +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToRuleCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular firewall rule based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToRuleUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts contains the values used when updating a firewall rule. +// Optional +type UpdateOpts struct { + Protocol string + Action string + Name string + Description string + IPVersion int + SourceIPAddress *string + DestinationIPAddress *string + SourcePort *string + DestinationPort *string + Shared *bool + Enabled *bool +} + +// ToRuleUpdateMap casts a UpdateOpts struct to a map. +func (opts UpdateOpts) ToRuleUpdateMap() (map[string]interface{}, error) { + r := make(map[string]interface{}) + + if opts.Protocol != "" { + r["protocol"] = opts.Protocol + } + if opts.Action != "" { + r["action"] = opts.Action + } + if opts.Name != "" { + r["name"] = opts.Name + } + if opts.Description != "" { + r["description"] = opts.Description + } + if opts.IPVersion != 0 { + r["ip_version"] = opts.IPVersion + } + if opts.SourceIPAddress != nil { + s := *opts.SourceIPAddress + if s == "" { + r["source_ip_address"] = nil + } else { + r["source_ip_address"] = s + } + } + if opts.DestinationIPAddress != nil { + s := *opts.DestinationIPAddress + if s == "" { + r["destination_ip_address"] = nil + } else { + r["destination_ip_address"] = s + } + } + if opts.SourcePort != nil { + s := *opts.SourcePort + if s == "" { + r["source_port"] = nil + } else { + r["source_port"] = s + } + } + if opts.DestinationPort != nil { + s := *opts.DestinationPort + if s == "" { + r["destination_port"] = nil + } else { + r["destination_port"] = s + } + } + if opts.Shared != nil { + r["shared"] = *opts.Shared + } + if opts.Enabled != nil { + r["enabled"] = *opts.Enabled + } + + return map[string]interface{}{"firewall_rule": r}, nil +} + +// Update allows firewall policies to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToRuleUpdateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// Delete will permanently delete a particular firewall rule based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/results.go new file mode 100644 index 000000000..d772024b3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/results.go @@ -0,0 +1,110 @@ +package rules + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Rule represents a firewall rule +type Rule struct { + ID string `json:"id" mapstructure:"id"` + Name string `json:"name,omitempty" mapstructure:"name"` + Description string `json:"description,omitempty" mapstructure:"description"` + Protocol string `json:"protocol" mapstructure:"protocol"` + Action string `json:"action" mapstructure:"action"` + IPVersion int `json:"ip_version,omitempty" mapstructure:"ip_version"` + SourceIPAddress string `json:"source_ip_address,omitempty" mapstructure:"source_ip_address"` + DestinationIPAddress string `json:"destination_ip_address,omitempty" mapstructure:"destination_ip_address"` + SourcePort string `json:"source_port,omitempty" mapstructure:"source_port"` + DestinationPort string `json:"destination_port,omitempty" mapstructure:"destination_port"` + Shared bool `json:"shared,omitempty" mapstructure:"shared"` + Enabled bool `json:"enabled,omitempty" mapstructure:"enabled"` + PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"` + Position int `json:"position" mapstructure:"position"` + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` +} + +// RulePage is the page returned by a pager when traversing over a +// collection of firewall rules. +type RulePage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of firewall rules has +// reached the end of a page and the pager seeks to traverse over a new one. +// In order to do this, it needs to construct the next page's URL. +func (p RulePage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"firewall_rules_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a RulePage struct is empty. +func (p RulePage) IsEmpty() (bool, error) { + is, err := ExtractRules(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractRules accepts a Page struct, specifically a RouterPage struct, +// and extracts the elements into a slice of Router structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractRules(page pagination.Page) ([]Rule, error) { + var resp struct { + Rules []Rule `mapstructure:"firewall_rules" json:"firewall_rules"` + } + + err := mapstructure.Decode(page.(RulePage).Body, &resp) + + return resp.Rules, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a firewall rule. +func (r commonResult) Extract() (*Rule, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Rule *Rule `json:"firewall_rule" mapstructure:"firewall_rule"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Rule, err +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/urls.go new file mode 100644 index 000000000..20b08791e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules/urls.go @@ -0,0 +1,16 @@ +package rules + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "fw" + resourcePath = "firewall_rules" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/doc.go new file mode 100644 index 000000000..d53345826 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/doc.go @@ -0,0 +1,5 @@ +// Package layer3 provides access to the Layer-3 networking extension for the +// OpenStack Neutron service. This extension allows API users to route packets +// between subnets, forward packets from internal networks to external ones, +// and access instances from external networks through floating IPs. +package layer3 diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go new file mode 100644 index 000000000..29f752a07 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go @@ -0,0 +1,168 @@ +package floatingips + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + ID string `q:"id"` + FloatingNetworkID string `q:"floating_network_id"` + PortID string `q:"port_id"` + FixedIP string `q:"fixed_ip_address"` + FloatingIP string `q:"floating_ip_address"` + TenantID string `q:"tenant_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// floating IP resources. It accepts a ListOpts struct, which allows you to +// filter and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return FloatingIPPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOpts contains all the values needed to create a new floating IP +// resource. The only required fields are FloatingNetworkID and PortID which +// refer to the external network and internal port respectively. +type CreateOpts struct { + FloatingNetworkID string + FloatingIP string + PortID string + FixedIP string + TenantID string +} + +var ( + errFloatingNetworkIDRequired = fmt.Errorf("A NetworkID is required") +) + +// Create accepts a CreateOpts struct and uses the values provided to create a +// new floating IP resource. You can create floating IPs on external networks +// only. If you provide a FloatingNetworkID which refers to a network that is +// not external (i.e. its `router:external' attribute is False), the operation +// will fail and return a 400 error. +// +// If you do not specify a FloatingIP address value, the operation will +// automatically allocate an available address for the new resource. If you do +// choose to specify one, it must fall within the subnet range for the external +// network - otherwise the operation returns a 400 error. If the FloatingIP +// address is already in use, the operation returns a 409 error code. +// +// You can associate the new resource with an internal port by using the PortID +// field. If you specify a PortID that is not valid, the operation will fail and +// return 404 error code. +// +// You must also configure an IP address for the port associated with the PortID +// you have provided - this is what the FixedIP refers to: an IP fixed to a port. +// Because a port might be associated with multiple IP addresses, you can use +// the FixedIP field to associate a particular IP address rather than have the +// API assume for you. If you specify an IP address that is not valid, the +// operation will fail and return a 400 error code. If the PortID and FixedIP +// are already associated with another resource, the operation will fail and +// returns a 409 error code. +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + var res CreateResult + + // Validate + if opts.FloatingNetworkID == "" { + res.Err = errFloatingNetworkIDRequired + return res + } + + // Define structures + type floatingIP struct { + FloatingNetworkID string `json:"floating_network_id"` + FloatingIP string `json:"floating_ip_address,omitempty"` + PortID string `json:"port_id,omitempty"` + FixedIP string `json:"fixed_ip_address,omitempty"` + TenantID string `json:"tenant_id,omitempty"` + } + type request struct { + FloatingIP floatingIP `json:"floatingip"` + } + + // Populate request body + reqBody := request{FloatingIP: floatingIP{ + FloatingNetworkID: opts.FloatingNetworkID, + FloatingIP: opts.FloatingIP, + PortID: opts.PortID, + FixedIP: opts.FixedIP, + TenantID: opts.TenantID, + }} + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular floating IP resource based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains the values used when updating a floating IP resource. The +// only value that can be updated is which internal port the floating IP is +// linked to. To associate the floating IP with a new internal port, provide its +// ID. To disassociate the floating IP from all ports, provide an empty string. +type UpdateOpts struct { + PortID string +} + +// Update allows floating IP resources to be updated. Currently, the only way to +// "update" a floating IP is to associate it with a new internal port, or +// disassociated it from all ports. See UpdateOpts for instructions of how to +// do this. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + type floatingIP struct { + PortID *string `json:"port_id"` + } + + type request struct { + FloatingIP floatingIP `json:"floatingip"` + } + + var portID *string + if opts.PortID == "" { + portID = nil + } else { + portID = &opts.PortID + } + + reqBody := request{FloatingIP: floatingIP{PortID: portID}} + + // Send request to API + var res UpdateResult + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// Delete will permanently delete a particular floating IP resource. Please +// ensure this is what you want - you can also disassociate the IP from existing +// internal ports. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go new file mode 100644 index 000000000..a1c7afe2c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go @@ -0,0 +1,127 @@ +package floatingips + +import ( + "fmt" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// FloatingIP represents a floating IP resource. A floating IP is an external +// IP address that is mapped to an internal port and, optionally, a specific +// IP address on a private network. In other words, it enables access to an +// instance on a private network from an external network. For this reason, +// floating IPs can only be defined on networks where the `router:external' +// attribute (provided by the external network extension) is set to True. +type FloatingIP struct { + // Unique identifier for the floating IP instance. + ID string `json:"id" mapstructure:"id"` + + // UUID of the external network where the floating IP is to be created. + FloatingNetworkID string `json:"floating_network_id" mapstructure:"floating_network_id"` + + // Address of the floating IP on the external network. + FloatingIP string `json:"floating_ip_address" mapstructure:"floating_ip_address"` + + // UUID of the port on an internal network that is associated with the floating IP. + PortID string `json:"port_id" mapstructure:"port_id"` + + // The specific IP address of the internal port which should be associated + // with the floating IP. + FixedIP string `json:"fixed_ip_address" mapstructure:"fixed_ip_address"` + + // Owner of the floating IP. Only admin users can specify a tenant identifier + // other than its own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + + // The condition of the API resource. + Status string `json:"status" mapstructure:"status"` +} + +type commonResult struct { + gophercloud.Result +} + +// Extract a result and extracts a FloatingIP resource. +func (r commonResult) Extract() (*FloatingIP, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + FloatingIP *FloatingIP `json:"floatingip"` + } + + err := mapstructure.Decode(r.Body, &res) + if err != nil { + return nil, fmt.Errorf("Error decoding Neutron floating IP: %v", err) + } + + return res.FloatingIP, nil +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of an update operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// FloatingIPPage is the page returned by a pager when traversing over a +// collection of floating IPs. +type FloatingIPPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of floating IPs has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p FloatingIPPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"floatingips_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a NetworkPage struct is empty. +func (p FloatingIPPage) IsEmpty() (bool, error) { + is, err := ExtractFloatingIPs(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractFloatingIPs accepts a Page struct, specifically a FloatingIPPage struct, +// and extracts the elements into a slice of FloatingIP structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) { + var resp struct { + FloatingIPs []FloatingIP `mapstructure:"floatingips" json:"floatingips"` + } + + err := mapstructure.Decode(page.(FloatingIPPage).Body, &resp) + + return resp.FloatingIPs, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/urls.go new file mode 100644 index 000000000..355f20dc0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/urls.go @@ -0,0 +1,13 @@ +package floatingips + +import "github.com/rackspace/gophercloud" + +const resourcePath = "floatingips" + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go new file mode 100644 index 000000000..8b6e73de9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go @@ -0,0 +1,230 @@ +package routers + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + ID string `q:"id"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + Status string `q:"status"` + TenantID string `q:"tenant_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// routers. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those routers that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return RouterPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOpts contains all the values needed to create a new router. There are +// no required values. +type CreateOpts struct { + Name string + AdminStateUp *bool + TenantID string + GatewayInfo *GatewayInfo +} + +// Create accepts a CreateOpts struct and uses the values to create a new +// logical router. When it is created, the router does not have an internal +// interface - it is not associated to any subnet. +// +// You can optionally specify an external gateway for a router using the +// GatewayInfo struct. The external gateway for the router must be plugged into +// an external network (it is external if its `router:external' field is set to +// true). +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + type router struct { + Name *string `json:"name,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + TenantID *string `json:"tenant_id,omitempty"` + GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"` + } + + type request struct { + Router router `json:"router"` + } + + reqBody := request{Router: router{ + Name: gophercloud.MaybeString(opts.Name), + AdminStateUp: opts.AdminStateUp, + TenantID: gophercloud.MaybeString(opts.TenantID), + }} + + if opts.GatewayInfo != nil { + reqBody.Router.GatewayInfo = opts.GatewayInfo + } + + var res CreateResult + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular router based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains the values used when updating a router. +type UpdateOpts struct { + Name string + AdminStateUp *bool + GatewayInfo *GatewayInfo + Routes []Route +} + +// Update allows routers to be updated. You can update the name, administrative +// state, and the external gateway. For more information about how to set the +// external gateway for a router, see Create. This operation does not enable +// the update of router interfaces. To do this, use the AddInterface and +// RemoveInterface functions. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + type router struct { + Name *string `json:"name,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"` + Routes []Route `json:"routes"` + } + + type request struct { + Router router `json:"router"` + } + + reqBody := request{Router: router{ + Name: gophercloud.MaybeString(opts.Name), + AdminStateUp: opts.AdminStateUp, + }} + + if opts.GatewayInfo != nil { + reqBody.Router.GatewayInfo = opts.GatewayInfo + } + + if opts.Routes != nil { + reqBody.Router.Routes = opts.Routes + } + + // Send request to API + var res UpdateResult + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// Delete will permanently delete a particular router based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} + +var errInvalidInterfaceOpts = errors.New("When adding a router interface you must provide either a subnet ID or a port ID") + +// InterfaceOpts allow you to work with operations that either add or remote +// an internal interface from a router. +type InterfaceOpts struct { + SubnetID string + PortID string +} + +// AddInterface attaches a subnet to an internal router interface. You must +// specify either a SubnetID or PortID in the request body. If you specify both, +// the operation will fail and an error will be returned. +// +// If you specify a SubnetID, the gateway IP address for that particular subnet +// is used to create the router interface. Alternatively, if you specify a +// PortID, the IP address associated with the port is used to create the router +// interface. +// +// If you reference a port that is associated with multiple IP addresses, or +// if the port is associated with zero IP addresses, the operation will fail and +// a 400 Bad Request error will be returned. +// +// If you reference a port already in use, the operation will fail and a 409 +// Conflict error will be returned. +// +// The PortID that is returned after using Extract() on the result of this +// operation can either be the same PortID passed in or, on the other hand, the +// identifier of a new port created by this operation. After the operation +// completes, the device ID of the port is set to the router ID, and the +// device owner attribute is set to `network:router_interface'. +func AddInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult { + var res InterfaceResult + + // Validate + if (opts.SubnetID == "" && opts.PortID == "") || (opts.SubnetID != "" && opts.PortID != "") { + res.Err = errInvalidInterfaceOpts + return res + } + + type request struct { + SubnetID string `json:"subnet_id,omitempty"` + PortID string `json:"port_id,omitempty"` + } + + body := request{SubnetID: opts.SubnetID, PortID: opts.PortID} + + _, res.Err = c.Put(addInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// RemoveInterface removes an internal router interface, which detaches a +// subnet from the router. You must specify either a SubnetID or PortID, since +// these values are used to identify the router interface to remove. +// +// Unlike AddInterface, you can also specify both a SubnetID and PortID. If you +// choose to specify both, the subnet ID must correspond to the subnet ID of +// the first IP address on the port specified by the port ID. Otherwise, the +// operation will fail and return a 409 Conflict error. +// +// If the router, subnet or port which are referenced do not exist or are not +// visible to you, the operation will fail and a 404 Not Found error will be +// returned. After this operation completes, the port connecting the router +// with the subnet is removed from the subnet for the network. +func RemoveInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult { + var res InterfaceResult + + type request struct { + SubnetID string `json:"subnet_id,omitempty"` + PortID string `json:"port_id,omitempty"` + } + + body := request{SubnetID: opts.SubnetID, PortID: opts.PortID} + + _, res.Err = c.Put(removeInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go new file mode 100644 index 000000000..5e297ab26 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go @@ -0,0 +1,168 @@ +package routers + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// GatewayInfo represents the information of an external gateway for any +// particular network router. +type GatewayInfo struct { + NetworkID string `json:"network_id" mapstructure:"network_id"` +} + +type Route struct { + NextHop string `mapstructure:"nexthop" json:"nexthop"` + DestinationCIDR string `mapstructure:"destination" json:"destination"` +} + +// Router represents a Neutron router. A router is a logical entity that +// forwards packets across internal subnets and NATs (network address +// translation) them on external networks through an appropriate gateway. +// +// A router has an interface for each subnet with which it is associated. By +// default, the IP address of such interface is the subnet's gateway IP. Also, +// whenever a router is associated with a subnet, a port for that router +// interface is added to the subnet's network. +type Router struct { + // Indicates whether or not a router is currently operational. + Status string `json:"status" mapstructure:"status"` + + // Information on external gateway for the router. + GatewayInfo GatewayInfo `json:"external_gateway_info" mapstructure:"external_gateway_info"` + + // Administrative state of the router. + AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"` + + // Human readable name for the router. Does not have to be unique. + Name string `json:"name" mapstructure:"name"` + + // Unique identifier for the router. + ID string `json:"id" mapstructure:"id"` + + // Owner of the router. Only admin users can specify a tenant identifier + // other than its own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + + Routes []Route `json:"routes" mapstructure:"routes"` +} + +// RouterPage is the page returned by a pager when traversing over a +// collection of routers. +type RouterPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of routers has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p RouterPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"routers_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a RouterPage struct is empty. +func (p RouterPage) IsEmpty() (bool, error) { + is, err := ExtractRouters(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractRouters accepts a Page struct, specifically a RouterPage struct, +// and extracts the elements into a slice of Router structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractRouters(page pagination.Page) ([]Router, error) { + var resp struct { + Routers []Router `mapstructure:"routers" json:"routers"` + } + + err := mapstructure.Decode(page.(RouterPage).Body, &resp) + + return resp.Routers, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a router. +func (r commonResult) Extract() (*Router, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Router *Router `json:"router"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Router, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// InterfaceInfo represents information about a particular router interface. As +// mentioned above, in order for a router to forward to a subnet, it needs an +// interface. +type InterfaceInfo struct { + // The ID of the subnet which this interface is associated with. + SubnetID string `json:"subnet_id" mapstructure:"subnet_id"` + + // The ID of the port that is a part of the subnet. + PortID string `json:"port_id" mapstructure:"port_id"` + + // The UUID of the interface. + ID string `json:"id" mapstructure:"id"` + + // Owner of the interface. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` +} + +// InterfaceResult represents the result of interface operations, such as +// AddInterface() and RemoveInterface(). +type InterfaceResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts an information struct. +func (r InterfaceResult) Extract() (*InterfaceInfo, error) { + if r.Err != nil { + return nil, r.Err + } + + var res *InterfaceInfo + err := mapstructure.Decode(r.Body, &res) + + return res, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/urls.go new file mode 100644 index 000000000..bc22c2a8a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers/urls.go @@ -0,0 +1,21 @@ +package routers + +import "github.com/rackspace/gophercloud" + +const resourcePath = "routers" + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id) +} + +func addInterfaceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id, "add_router_interface") +} + +func removeInterfaceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(resourcePath, id, "remove_router_interface") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/doc.go new file mode 100644 index 000000000..bc1fc282f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/doc.go @@ -0,0 +1,3 @@ +// Package lbaas provides information and interaction with the Load Balancer +// as a Service extension for the OpenStack Networking service. +package lbaas diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/requests.go new file mode 100644 index 000000000..848938f98 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/requests.go @@ -0,0 +1,123 @@ +package members + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Status string `q:"status"` + Weight int `q:"weight"` + AdminStateUp *bool `q:"admin_state_up"` + TenantID string `q:"tenant_id"` + PoolID string `q:"pool_id"` + Address string `q:"address"` + ProtocolPort int `q:"protocol_port"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// pools. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those pools that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return MemberPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOpts contains all the values needed to create a new pool member. +type CreateOpts struct { + // Only required if the caller has an admin role and wants to create a pool + // for another tenant. + TenantID string + + // Required. The IP address of the member. + Address string + + // Required. The port on which the application is hosted. + ProtocolPort int + + // Required. The pool to which this member will belong. + PoolID string +} + +// Create accepts a CreateOpts struct and uses the values to create a new +// load balancer pool member. +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + type member struct { + TenantID string `json:"tenant_id,omitempty"` + ProtocolPort int `json:"protocol_port"` + Address string `json:"address"` + PoolID string `json:"pool_id"` + } + type request struct { + Member member `json:"member"` + } + + reqBody := request{Member: member{ + Address: opts.Address, + TenantID: opts.TenantID, + ProtocolPort: opts.ProtocolPort, + PoolID: opts.PoolID, + }} + + var res CreateResult + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular pool member based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains the values used when updating a pool member. +type UpdateOpts struct { + // The administrative state of the member, which is up (true) or down (false). + AdminStateUp bool +} + +// Update allows members to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + type member struct { + AdminStateUp bool `json:"admin_state_up"` + } + type request struct { + Member member `json:"member"` + } + + reqBody := request{Member: member{AdminStateUp: opts.AdminStateUp}} + + // Send request to API + var res UpdateResult + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201, 202}, + }) + return res +} + +// Delete will permanently delete a particular member based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/results.go new file mode 100644 index 000000000..3cad339b7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/results.go @@ -0,0 +1,122 @@ +package members + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Member represents the application running on a backend server. +type Member struct { + // The status of the member. Indicates whether the member is operational. + Status string + + // Weight of member. + Weight int + + // The administrative state of the member, which is up (true) or down (false). + AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"` + + // Owner of the member. Only an administrative user can specify a tenant ID + // other than its own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + + // The pool to which the member belongs. + PoolID string `json:"pool_id" mapstructure:"pool_id"` + + // The IP address of the member. + Address string + + // The port on which the application is hosted. + ProtocolPort int `json:"protocol_port" mapstructure:"protocol_port"` + + // The unique ID for the member. + ID string +} + +// MemberPage is the page returned by a pager when traversing over a +// collection of pool members. +type MemberPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of members has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p MemberPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"members_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a MemberPage struct is empty. +func (p MemberPage) IsEmpty() (bool, error) { + is, err := ExtractMembers(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractMembers accepts a Page struct, specifically a MemberPage struct, +// and extracts the elements into a slice of Member structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractMembers(page pagination.Page) ([]Member, error) { + var resp struct { + Members []Member `mapstructure:"members" json:"members"` + } + + err := mapstructure.Decode(page.(MemberPage).Body, &resp) + if err != nil { + return nil, err + } + + return resp.Members, nil +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a router. +func (r commonResult) Extract() (*Member, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Member *Member `json:"member"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Member, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/urls.go new file mode 100644 index 000000000..94b57e4c5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members/urls.go @@ -0,0 +1,16 @@ +package members + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "lb" + resourcePath = "members" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/requests.go new file mode 100644 index 000000000..71b21ef16 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/requests.go @@ -0,0 +1,265 @@ +package monitors + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + ID string `q:"id"` + TenantID string `q:"tenant_id"` + Type string `q:"type"` + Delay int `q:"delay"` + Timeout int `q:"timeout"` + MaxRetries int `q:"max_retries"` + HTTPMethod string `q:"http_method"` + URLPath string `q:"url_path"` + ExpectedCodes string `q:"expected_codes"` + AdminStateUp *bool `q:"admin_state_up"` + Status string `q:"status"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// routers. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those routers that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return MonitorPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Constants that represent approved monitoring types. +const ( + TypePING = "PING" + TypeTCP = "TCP" + TypeHTTP = "HTTP" + TypeHTTPS = "HTTPS" +) + +var ( + errValidTypeRequired = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS") + errDelayRequired = fmt.Errorf("Delay is required") + errTimeoutRequired = fmt.Errorf("Timeout is required") + errMaxRetriesRequired = fmt.Errorf("MaxRetries is required") + errURLPathRequired = fmt.Errorf("URL path is required") + errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required") + errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout") +) + +// CreateOpts contains all the values needed to create a new health monitor. +type CreateOpts struct { + // Required for admins. Indicates the owner of the VIP. + TenantID string + + // Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is + // sent by the load balancer to verify the member state. + Type string + + // Required. The time, in seconds, between sending probes to members. + Delay int + + // Required. Maximum number of seconds for a monitor to wait for a ping reply + // before it times out. The value must be less than the delay value. + Timeout int + + // Required. Number of permissible ping failures before changing the member's + // status to INACTIVE. Must be a number between 1 and 10. + MaxRetries int + + // Required for HTTP(S) types. URI path that will be accessed if monitor type + // is HTTP or HTTPS. + URLPath string + + // Required for HTTP(S) types. The HTTP method used for requests by the + // monitor. If this attribute is not specified, it defaults to "GET". + HTTPMethod string + + // Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S) + // monitor. You can either specify a single status like "200", or a range + // like "200-202". + ExpectedCodes string + + AdminStateUp *bool +} + +// Create is an operation which provisions a new health monitor. There are +// different types of monitor you can provision: PING, TCP or HTTP(S). Below +// are examples of how to create each one. +// +// Here is an example config struct to use when creating a PING or TCP monitor: +// +// CreateOpts{Type: TypePING, Delay: 20, Timeout: 10, MaxRetries: 3} +// CreateOpts{Type: TypeTCP, Delay: 20, Timeout: 10, MaxRetries: 3} +// +// Here is an example config struct to use when creating a HTTP(S) monitor: +// +// CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3, +// HttpMethod: "HEAD", ExpectedCodes: "200"} +// +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + var res CreateResult + + // Validate inputs + allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true} + if opts.Type == "" || allowed[opts.Type] == false { + res.Err = errValidTypeRequired + } + if opts.Delay == 0 { + res.Err = errDelayRequired + } + if opts.Timeout == 0 { + res.Err = errTimeoutRequired + } + if opts.MaxRetries == 0 { + res.Err = errMaxRetriesRequired + } + if opts.Type == TypeHTTP || opts.Type == TypeHTTPS { + if opts.URLPath == "" { + res.Err = errURLPathRequired + } + if opts.ExpectedCodes == "" { + res.Err = errExpectedCodesRequired + } + } + if opts.Delay < opts.Timeout { + res.Err = errDelayMustGETimeout + } + if res.Err != nil { + return res + } + + type monitor struct { + Type string `json:"type"` + Delay int `json:"delay"` + Timeout int `json:"timeout"` + MaxRetries int `json:"max_retries"` + TenantID *string `json:"tenant_id,omitempty"` + URLPath *string `json:"url_path,omitempty"` + ExpectedCodes *string `json:"expected_codes,omitempty"` + HTTPMethod *string `json:"http_method,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + } + + type request struct { + Monitor monitor `json:"health_monitor"` + } + + reqBody := request{Monitor: monitor{ + Type: opts.Type, + Delay: opts.Delay, + Timeout: opts.Timeout, + MaxRetries: opts.MaxRetries, + TenantID: gophercloud.MaybeString(opts.TenantID), + URLPath: gophercloud.MaybeString(opts.URLPath), + ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes), + HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod), + AdminStateUp: opts.AdminStateUp, + }} + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular health monitor based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains all the values needed to update an existing virtual IP. +// Attributes not listed here but appear in CreateOpts are immutable and cannot +// be updated. +type UpdateOpts struct { + // Required. The time, in seconds, between sending probes to members. + Delay int + + // Required. Maximum number of seconds for a monitor to wait for a ping reply + // before it times out. The value must be less than the delay value. + Timeout int + + // Required. Number of permissible ping failures before changing the member's + // status to INACTIVE. Must be a number between 1 and 10. + MaxRetries int + + // Required for HTTP(S) types. URI path that will be accessed if monitor type + // is HTTP or HTTPS. + URLPath string + + // Required for HTTP(S) types. The HTTP method used for requests by the + // monitor. If this attribute is not specified, it defaults to "GET". + HTTPMethod string + + // Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S) + // monitor. You can either specify a single status like "200", or a range + // like "200-202". + ExpectedCodes string + + AdminStateUp *bool +} + +// Update is an operation which modifies the attributes of the specified monitor. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + var res UpdateResult + + if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout { + res.Err = errDelayMustGETimeout + } + + type monitor struct { + Delay int `json:"delay"` + Timeout int `json:"timeout"` + MaxRetries int `json:"max_retries"` + URLPath *string `json:"url_path,omitempty"` + ExpectedCodes *string `json:"expected_codes,omitempty"` + HTTPMethod *string `json:"http_method,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + } + + type request struct { + Monitor monitor `json:"health_monitor"` + } + + reqBody := request{Monitor: monitor{ + Delay: opts.Delay, + Timeout: opts.Timeout, + MaxRetries: opts.MaxRetries, + URLPath: gophercloud.MaybeString(opts.URLPath), + ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes), + HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod), + AdminStateUp: opts.AdminStateUp, + }} + + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + + return res +} + +// Delete will permanently delete a particular monitor based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/results.go new file mode 100644 index 000000000..d595abd54 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/results.go @@ -0,0 +1,147 @@ +package monitors + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Monitor represents a load balancer health monitor. A health monitor is used +// to determine whether or not back-end members of the VIP's pool are usable +// for processing a request. A pool can have several health monitors associated +// with it. There are different types of health monitors supported: +// +// PING: used to ping the members using ICMP. +// TCP: used to connect to the members using TCP. +// HTTP: used to send an HTTP request to the member. +// HTTPS: used to send a secure HTTP request to the member. +// +// When a pool has several monitors associated with it, each member of the pool +// is monitored by all these monitors. If any monitor declares the member as +// unhealthy, then the member status is changed to INACTIVE and the member +// won't participate in its pool's load balancing. In other words, ALL monitors +// must declare the member to be healthy for it to stay ACTIVE. +type Monitor struct { + // The unique ID for the VIP. + ID string + + // Owner of the VIP. Only an administrative user can specify a tenant ID + // other than its own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + + // The type of probe sent by the load balancer to verify the member state, + // which is PING, TCP, HTTP, or HTTPS. + Type string + + // The time, in seconds, between sending probes to members. + Delay int + + // The maximum number of seconds for a monitor to wait for a connection to be + // established before it times out. This value must be less than the delay value. + Timeout int + + // Number of allowed connection failures before changing the status of the + // member to INACTIVE. A valid value is from 1 to 10. + MaxRetries int `json:"max_retries" mapstructure:"max_retries"` + + // The HTTP method that the monitor uses for requests. + HTTPMethod string `json:"http_method" mapstructure:"http_method"` + + // The HTTP path of the request sent by the monitor to test the health of a + // member. Must be a string beginning with a forward slash (/). + URLPath string `json:"url_path" mapstructure:"url_path"` + + // Expected HTTP codes for a passing HTTP(S) monitor. + ExpectedCodes string `json:"expected_codes" mapstructure:"expected_codes"` + + // The administrative state of the health monitor, which is up (true) or down (false). + AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"` + + // The status of the health monitor. Indicates whether the health monitor is + // operational. + Status string +} + +// MonitorPage is the page returned by a pager when traversing over a +// collection of health monitors. +type MonitorPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of monitors has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p MonitorPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"health_monitors_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a PoolPage struct is empty. +func (p MonitorPage) IsEmpty() (bool, error) { + is, err := ExtractMonitors(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractMonitors accepts a Page struct, specifically a MonitorPage struct, +// and extracts the elements into a slice of Monitor structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractMonitors(page pagination.Page) ([]Monitor, error) { + var resp struct { + Monitors []Monitor `mapstructure:"health_monitors" json:"health_monitors"` + } + + err := mapstructure.Decode(page.(MonitorPage).Body, &resp) + + return resp.Monitors, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a monitor. +func (r commonResult) Extract() (*Monitor, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Monitor *Monitor `json:"health_monitor" mapstructure:"health_monitor"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Monitor, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/urls.go new file mode 100644 index 000000000..46e84bbf5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors/urls.go @@ -0,0 +1,16 @@ +package monitors + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "lb" + resourcePath = "health_monitors" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/requests.go new file mode 100644 index 000000000..2bb0acc44 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/requests.go @@ -0,0 +1,181 @@ +package pools + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Status string `q:"status"` + LBMethod string `q:"lb_method"` + Protocol string `q:"protocol"` + SubnetID string `q:"subnet_id"` + TenantID string `q:"tenant_id"` + AdminStateUp *bool `q:"admin_state_up"` + Name string `q:"name"` + ID string `q:"id"` + VIPID string `q:"vip_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// pools. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those pools that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return PoolPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Supported attributes for create/update operations. +const ( + LBMethodRoundRobin = "ROUND_ROBIN" + LBMethodLeastConnections = "LEAST_CONNECTIONS" + + ProtocolTCP = "TCP" + ProtocolHTTP = "HTTP" + ProtocolHTTPS = "HTTPS" +) + +// CreateOpts contains all the values needed to create a new pool. +type CreateOpts struct { + // Only required if the caller has an admin role and wants to create a pool + // for another tenant. + TenantID string + + // Required. Name of the pool. + Name string + + // Required. The protocol used by the pool members, you can use either + // ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS. + Protocol string + + // The network on which the members of the pool will be located. Only members + // that are on this network can be added to the pool. + SubnetID string + + // The algorithm used to distribute load between the members of the pool. The + // current specification supports LBMethodRoundRobin and + // LBMethodLeastConnections as valid values for this attribute. + LBMethod string +} + +// Create accepts a CreateOpts struct and uses the values to create a new +// load balancer pool. +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + type pool struct { + Name string `json:"name"` + TenantID string `json:"tenant_id,omitempty"` + Protocol string `json:"protocol"` + SubnetID string `json:"subnet_id"` + LBMethod string `json:"lb_method"` + } + type request struct { + Pool pool `json:"pool"` + } + + reqBody := request{Pool: pool{ + Name: opts.Name, + TenantID: opts.TenantID, + Protocol: opts.Protocol, + SubnetID: opts.SubnetID, + LBMethod: opts.LBMethod, + }} + + var res CreateResult + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular pool based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains the values used when updating a pool. +type UpdateOpts struct { + // Required. Name of the pool. + Name string + + // The algorithm used to distribute load between the members of the pool. The + // current specification supports LBMethodRoundRobin and + // LBMethodLeastConnections as valid values for this attribute. + LBMethod string +} + +// Update allows pools to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + type pool struct { + Name string `json:"name,"` + LBMethod string `json:"lb_method"` + } + type request struct { + Pool pool `json:"pool"` + } + + reqBody := request{Pool: pool{ + Name: opts.Name, + LBMethod: opts.LBMethod, + }} + + // Send request to API + var res UpdateResult + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Delete will permanently delete a particular pool based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} + +// AssociateMonitor will associate a health monitor with a particular pool. +// Once associated, the health monitor will start monitoring the members of the +// pool and will deactivate these members if they are deemed unhealthy. A +// member can be deactivated (status set to INACTIVE) if any of health monitors +// finds it unhealthy. +func AssociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult { + type hm struct { + ID string `json:"id"` + } + type request struct { + Monitor hm `json:"health_monitor"` + } + + reqBody := request{hm{ID: monitorID}} + + var res AssociateResult + _, res.Err = c.Post(associateURL(c, poolID), reqBody, &res.Body, nil) + return res +} + +// DisassociateMonitor will disassociate a health monitor with a particular +// pool. When dissociation is successful, the health monitor will no longer +// check for the health of the members of the pool. +func DisassociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult { + var res AssociateResult + _, res.Err = c.Delete(disassociateURL(c, poolID, monitorID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/results.go new file mode 100644 index 000000000..07ec85eda --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/results.go @@ -0,0 +1,146 @@ +package pools + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Pool represents a logical set of devices, such as web servers, that you +// group together to receive and process traffic. The load balancing function +// chooses a member of the pool according to the configured load balancing +// method to handle the new requests or connections received on the VIP address. +// There is only one pool per virtual IP. +type Pool struct { + // The status of the pool. Indicates whether the pool is operational. + Status string + + // The load-balancer algorithm, which is round-robin, least-connections, and + // so on. This value, which must be supported, is dependent on the provider. + // Round-robin must be supported. + LBMethod string `json:"lb_method" mapstructure:"lb_method"` + + // The protocol of the pool, which is TCP, HTTP, or HTTPS. + Protocol string + + // Description for the pool. + Description string + + // The IDs of associated monitors which check the health of the pool members. + MonitorIDs []string `json:"health_monitors" mapstructure:"health_monitors"` + + // The network on which the members of the pool will be located. Only members + // that are on this network can be added to the pool. + SubnetID string `json:"subnet_id" mapstructure:"subnet_id"` + + // Owner of the pool. Only an administrative user can specify a tenant ID + // other than its own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` + + // The administrative state of the pool, which is up (true) or down (false). + AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"` + + // Pool name. Does not have to be unique. + Name string + + // List of member IDs that belong to the pool. + MemberIDs []string `json:"members" mapstructure:"members"` + + // The unique ID for the pool. + ID string + + // The ID of the virtual IP associated with this pool + VIPID string `json:"vip_id" mapstructure:"vip_id"` + + // The provider + Provider string +} + +// PoolPage is the page returned by a pager when traversing over a +// collection of pools. +type PoolPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of pools has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p PoolPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"pools_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a PoolPage struct is empty. +func (p PoolPage) IsEmpty() (bool, error) { + is, err := ExtractPools(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractPools accepts a Page struct, specifically a RouterPage struct, +// and extracts the elements into a slice of Router structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractPools(page pagination.Page) ([]Pool, error) { + var resp struct { + Pools []Pool `mapstructure:"pools" json:"pools"` + } + + err := mapstructure.Decode(page.(PoolPage).Body, &resp) + + return resp.Pools, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a router. +func (r commonResult) Extract() (*Pool, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Pool *Pool `json:"pool"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Pool, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// AssociateResult represents the result of an association operation. +type AssociateResult struct { + commonResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/urls.go new file mode 100644 index 000000000..6cd15b002 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools/urls.go @@ -0,0 +1,25 @@ +package pools + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "lb" + resourcePath = "pools" + monitorPath = "health_monitors" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} + +func associateURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id, monitorPath) +} + +func disassociateURL(c *gophercloud.ServiceClient, poolID, monitorID string) string { + return c.ServiceURL(rootPath, resourcePath, poolID, monitorPath, monitorID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go new file mode 100644 index 000000000..6216f873e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go @@ -0,0 +1,256 @@ +package vips + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + ID string `q:"id"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + Status string `q:"status"` + TenantID string `q:"tenant_id"` + SubnetID string `q:"subnet_id"` + Address string `q:"address"` + PortID string `q:"port_id"` + Protocol string `q:"protocol"` + ProtocolPort int `q:"protocol_port"` + ConnectionLimit int `q:"connection_limit"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// routers. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those routers that are owned by the +// tenant who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return VIPPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +var ( + errNameRequired = fmt.Errorf("Name is required") + errSubnetIDRequried = fmt.Errorf("SubnetID is required") + errProtocolRequired = fmt.Errorf("Protocol is required") + errProtocolPortRequired = fmt.Errorf("Protocol port is required") + errPoolIDRequired = fmt.Errorf("PoolID is required") +) + +// CreateOpts contains all the values needed to create a new virtual IP. +type CreateOpts struct { + // Required. Human-readable name for the VIP. Does not have to be unique. + Name string + + // Required. The network on which to allocate the VIP's address. A tenant can + // only create VIPs on networks authorized by policy (e.g. networks that + // belong to them or networks that are shared). + SubnetID string + + // Required. The protocol - can either be TCP, HTTP or HTTPS. + Protocol string + + // Required. The port on which to listen for client traffic. + ProtocolPort int + + // Required. The ID of the pool with which the VIP is associated. + PoolID string + + // Required for admins. Indicates the owner of the VIP. + TenantID string + + // Optional. The IP address of the VIP. + Address string + + // Optional. Human-readable description for the VIP. + Description string + + // Optional. Omit this field to prevent session persistence. + Persistence *SessionPersistence + + // Optional. The maximum number of connections allowed for the VIP. + ConnLimit *int + + // Optional. The administrative state of the VIP. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool +} + +// Create is an operation which provisions a new virtual IP based on the +// configuration defined in the CreateOpts struct. Once the request is +// validated and progress has started on the provisioning process, a +// CreateResult will be returned. +// +// Please note that the PoolID should refer to a pool that is not already +// associated with another vip. If the pool is already used by another vip, +// then the operation will fail with a 409 Conflict error will be returned. +// +// Users with an admin role can create VIPs on behalf of other tenants by +// specifying a TenantID attribute different than their own. +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + var res CreateResult + + // Validate required opts + if opts.Name == "" { + res.Err = errNameRequired + return res + } + if opts.SubnetID == "" { + res.Err = errSubnetIDRequried + return res + } + if opts.Protocol == "" { + res.Err = errProtocolRequired + return res + } + if opts.ProtocolPort == 0 { + res.Err = errProtocolPortRequired + return res + } + if opts.PoolID == "" { + res.Err = errPoolIDRequired + return res + } + + type vip struct { + Name string `json:"name"` + SubnetID string `json:"subnet_id"` + Protocol string `json:"protocol"` + ProtocolPort int `json:"protocol_port"` + PoolID string `json:"pool_id"` + Description *string `json:"description,omitempty"` + TenantID *string `json:"tenant_id,omitempty"` + Address *string `json:"address,omitempty"` + Persistence *SessionPersistence `json:"session_persistence,omitempty"` + ConnLimit *int `json:"connection_limit,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + } + + type request struct { + VirtualIP vip `json:"vip"` + } + + reqBody := request{VirtualIP: vip{ + Name: opts.Name, + SubnetID: opts.SubnetID, + Protocol: opts.Protocol, + ProtocolPort: opts.ProtocolPort, + PoolID: opts.PoolID, + Description: gophercloud.MaybeString(opts.Description), + TenantID: gophercloud.MaybeString(opts.TenantID), + Address: gophercloud.MaybeString(opts.Address), + ConnLimit: opts.ConnLimit, + AdminStateUp: opts.AdminStateUp, + }} + + if opts.Persistence != nil { + reqBody.VirtualIP.Persistence = opts.Persistence + } + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular virtual IP based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// UpdateOpts contains all the values needed to update an existing virtual IP. +// Attributes not listed here but appear in CreateOpts are immutable and cannot +// be updated. +type UpdateOpts struct { + // Human-readable name for the VIP. Does not have to be unique. + Name string + + // Required. The ID of the pool with which the VIP is associated. + PoolID string + + // Optional. Human-readable description for the VIP. + Description string + + // Optional. Omit this field to prevent session persistence. + Persistence *SessionPersistence + + // Optional. The maximum number of connections allowed for the VIP. + ConnLimit *int + + // Optional. The administrative state of the VIP. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool +} + +// Update is an operation which modifies the attributes of the specified VIP. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult { + type vip struct { + Name string `json:"name,omitempty"` + PoolID string `json:"pool_id,omitempty"` + Description *string `json:"description,omitempty"` + Persistence *SessionPersistence `json:"session_persistence,omitempty"` + ConnLimit *int `json:"connection_limit,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + } + + type request struct { + VirtualIP vip `json:"vip"` + } + + reqBody := request{VirtualIP: vip{ + Name: opts.Name, + PoolID: opts.PoolID, + Description: gophercloud.MaybeString(opts.Description), + ConnLimit: opts.ConnLimit, + AdminStateUp: opts.AdminStateUp, + }} + + if opts.Persistence != nil { + reqBody.VirtualIP.Persistence = opts.Persistence + } + + var res UpdateResult + _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + + return res +} + +// Delete will permanently delete a particular virtual IP based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/results.go new file mode 100644 index 000000000..e1092e780 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/results.go @@ -0,0 +1,166 @@ +package vips + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// SessionPersistence represents the session persistence feature of the load +// balancing service. It attempts to force connections or requests in the same +// session to be processed by the same member as long as it is ative. Three +// types of persistence are supported: +// +// SOURCE_IP: With this mode, all connections originating from the same source +// IP address, will be handled by the same member of the pool. +// HTTP_COOKIE: With this persistence mode, the load balancing function will +// create a cookie on the first request from a client. Subsequent +// requests containing the same cookie value will be handled by +// the same member of the pool. +// APP_COOKIE: With this persistence mode, the load balancing function will +// rely on a cookie established by the backend application. All +// requests carrying the same cookie value will be handled by the +// same member of the pool. +type SessionPersistence struct { + // The type of persistence mode + Type string `mapstructure:"type" json:"type"` + + // Name of cookie if persistence mode is set appropriately + CookieName string `mapstructure:"cookie_name" json:"cookie_name,omitempty"` +} + +// VirtualIP is the primary load balancing configuration object that specifies +// the virtual IP address and port on which client traffic is received, as well +// as other details such as the load balancing method to be use, protocol, etc. +// This entity is sometimes known in LB products under the name of a "virtual +// server", a "vserver" or a "listener". +type VirtualIP struct { + // The unique ID for the VIP. + ID string `mapstructure:"id" json:"id"` + + // Owner of the VIP. Only an admin user can specify a tenant ID other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` + + // Human-readable name for the VIP. Does not have to be unique. + Name string `mapstructure:"name" json:"name"` + + // Human-readable description for the VIP. + Description string `mapstructure:"description" json:"description"` + + // The ID of the subnet on which to allocate the VIP address. + SubnetID string `mapstructure:"subnet_id" json:"subnet_id"` + + // The IP address of the VIP. + Address string `mapstructure:"address" json:"address"` + + // The protocol of the VIP address. A valid value is TCP, HTTP, or HTTPS. + Protocol string `mapstructure:"protocol" json:"protocol"` + + // The port on which to listen to client traffic that is associated with the + // VIP address. A valid value is from 0 to 65535. + ProtocolPort int `mapstructure:"protocol_port" json:"protocol_port"` + + // The ID of the pool with which the VIP is associated. + PoolID string `mapstructure:"pool_id" json:"pool_id"` + + // The ID of the port which belongs to the load balancer + PortID string `mapstructure:"port_id" json:"port_id"` + + // Indicates whether connections in the same session will be processed by the + // same pool member or not. + Persistence SessionPersistence `mapstructure:"session_persistence" json:"session_persistence"` + + // The maximum number of connections allowed for the VIP. Default is -1, + // meaning no limit. + ConnLimit int `mapstructure:"connection_limit" json:"connection_limit"` + + // The administrative state of the VIP. A valid value is true (UP) or false (DOWN). + AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"` + + // The status of the VIP. Indicates whether the VIP is operational. + Status string `mapstructure:"status" json:"status"` +} + +// VIPPage is the page returned by a pager when traversing over a +// collection of routers. +type VIPPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of routers has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p VIPPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"vips_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a RouterPage struct is empty. +func (p VIPPage) IsEmpty() (bool, error) { + is, err := ExtractVIPs(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractVIPs accepts a Page struct, specifically a VIPPage struct, +// and extracts the elements into a slice of VirtualIP structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractVIPs(page pagination.Page) ([]VirtualIP, error) { + var resp struct { + VIPs []VirtualIP `mapstructure:"vips" json:"vips"` + } + + err := mapstructure.Decode(page.(VIPPage).Body, &resp) + + return resp.VIPs, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a router. +func (r commonResult) Extract() (*VirtualIP, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + VirtualIP *VirtualIP `mapstructure:"vip" json:"vip"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.VirtualIP, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/urls.go new file mode 100644 index 000000000..2b6f67e71 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips/urls.go @@ -0,0 +1,16 @@ +package vips + +import "github.com/rackspace/gophercloud" + +const ( + rootPath = "lb" + resourcePath = "vips" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/doc.go new file mode 100644 index 000000000..373da44f8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/doc.go @@ -0,0 +1,21 @@ +// Package provider gives access to the provider Neutron plugin, allowing +// network extended attributes. The provider extended attributes for networks +// enable administrative users to specify how network objects map to the +// underlying networking infrastructure. These extended attributes also appear +// when administrative users query networks. +// +// For more information about extended attributes, see the NetworkExtAttrs +// struct. The actual semantics of these attributes depend on the technology +// back end of the particular plug-in. See the plug-in documentation and the +// OpenStack Cloud Administrator Guide to understand which values should be +// specific for each of these attributes when OpenStack Networking is deployed +// with a particular plug-in. The examples shown in this chapter refer to the +// Open vSwitch plug-in. +// +// The default policy settings enable only users with administrative rights to +// specify these parameters in requests and to see their values in responses. By +// default, the provider network extension attributes are completely hidden from +// regular tenants. As a rule of thumb, if these attributes are not visible in a +// GET /networks/ operation, this implies the user submitting the +// request is not authorized to view or manipulate provider network attributes. +package provider diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/results.go new file mode 100644 index 000000000..f07d6285d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/provider/results.go @@ -0,0 +1,124 @@ +package provider + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud/openstack/networking/v2/networks" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +// NetworkExtAttrs represents an extended form of a Network with additional fields. +type NetworkExtAttrs struct { + // UUID for the network + ID string `mapstructure:"id" json:"id"` + + // Human-readable name for the network. Might not be unique. + Name string `mapstructure:"name" json:"name"` + + // The administrative state of network. If false (down), the network does not forward packets. + AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"` + + // Indicates whether network is currently operational. Possible values include + // `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values. + Status string `mapstructure:"status" json:"status"` + + // Subnets associated with this network. + Subnets []string `mapstructure:"subnets" json:"subnets"` + + // Owner of network. Only admin users can specify a tenant_id other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` + + // Specifies whether the network resource can be accessed by any tenant or not. + Shared bool `mapstructure:"shared" json:"shared"` + + // Specifies the nature of the physical network mapped to this network + // resource. Examples are flat, vlan, or gre. + NetworkType string `json:"provider:network_type" mapstructure:"provider:network_type"` + + // Identifies the physical network on top of which this network object is + // being implemented. The OpenStack Networking API does not expose any facility + // for retrieving the list of available physical networks. As an example, in + // the Open vSwitch plug-in this is a symbolic name which is then mapped to + // specific bridges on each compute host through the Open vSwitch plug-in + // configuration file. + PhysicalNetwork string `json:"provider:physical_network" mapstructure:"provider:physical_network"` + + // Identifies an isolated segment on the physical network; the nature of the + // segment depends on the segmentation model defined by network_type. For + // instance, if network_type is vlan, then this is a vlan identifier; + // otherwise, if network_type is gre, then this will be a gre key. + SegmentationID string `json:"provider:segmentation_id" mapstructure:"provider:segmentation_id"` +} + +// ExtractGet decorates a GetResult struct returned from a networks.Get() +// function with extended attributes. +func ExtractGet(r networks.GetResult) (*NetworkExtAttrs, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *NetworkExtAttrs `json:"network"` + } + + err := mapstructure.WeakDecode(r.Body, &res) + + return res.Network, err +} + +// ExtractCreate decorates a CreateResult struct returned from a networks.Create() +// function with extended attributes. +func ExtractCreate(r networks.CreateResult) (*NetworkExtAttrs, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *NetworkExtAttrs `json:"network"` + } + + err := mapstructure.WeakDecode(r.Body, &res) + + return res.Network, err +} + +// ExtractUpdate decorates a UpdateResult struct returned from a +// networks.Update() function with extended attributes. +func ExtractUpdate(r networks.UpdateResult) (*NetworkExtAttrs, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *NetworkExtAttrs `json:"network"` + } + + err := mapstructure.WeakDecode(r.Body, &res) + + return res.Network, err +} + +// ExtractList accepts a Page struct, specifically a NetworkPage struct, and +// extracts the elements into a slice of NetworkExtAttrs structs. In other +// words, a generic collection is mapped into a relevant slice. +func ExtractList(page pagination.Page) ([]NetworkExtAttrs, error) { + var resp struct { + Networks []NetworkExtAttrs `mapstructure:"networks" json:"networks"` + } + + err := mapstructure.WeakDecode(page.(networks.NetworkPage).Body, &resp) + + return resp.Networks, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/doc.go new file mode 100644 index 000000000..31f744ccd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/doc.go @@ -0,0 +1,32 @@ +// Package security contains functionality to work with security group and +// security group rules Neutron resources. +// +// Security groups and security group rules allows administrators and tenants +// the ability to specify the type of traffic and direction (ingress/egress) +// that is allowed to pass through a port. A security group is a container for +// security group rules. +// +// When a port is created in Networking it is associated with a security group. +// If a security group is not specified the port is associated with a 'default' +// security group. By default, this group drops all ingress traffic and allows +// all egress. Rules can be added to this group in order to change the behaviour. +// +// The basic characteristics of Neutron Security Groups are: +// +// For ingress traffic (to an instance) +// - Only traffic matched with security group rules are allowed. +// - When there is no rule defined, all traffic is dropped. +// +// For egress traffic (from an instance) +// - Only traffic matched with security group rules are allowed. +// - When there is no rule defined, all egress traffic are dropped. +// - When a new security group is created, rules to allow all egress traffic +// is automatically added. +// +// "default security group" is defined for each tenant. +// - For the default security group a rule which allows intercommunication +// among hosts associated with the default security group is defined by default. +// - As a result, all egress traffic and intercommunication in the default +// group are allowed and all ingress from outside of the default group is +// dropped by default (in the default security group). +package security diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go new file mode 100644 index 000000000..2712ac162 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go @@ -0,0 +1,131 @@ +package groups + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the floating IP attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + ID string `q:"id"` + Name string `q:"name"` + TenantID string `q:"tenant_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// security groups. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return SecGroupPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +var ( + errNameRequired = fmt.Errorf("Name is required") +) + +// CreateOpts contains all the values needed to create a new security group. +type CreateOpts struct { + // Required. Human-readable name for the VIP. Does not have to be unique. + Name string + + // Required for admins. Indicates the owner of the VIP. + TenantID string + + // Optional. Describes the security group. + Description string +} + +// Create is an operation which provisions a new security group with default +// security group rules for the IPv4 and IPv6 ether types. +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + var res CreateResult + + // Validate required opts + if opts.Name == "" { + res.Err = errNameRequired + return res + } + + type secgroup struct { + Name string `json:"name"` + TenantID string `json:"tenant_id,omitempty"` + Description string `json:"description,omitempty"` + } + + type request struct { + SecGroup secgroup `json:"security_group"` + } + + reqBody := request{SecGroup: secgroup{ + Name: opts.Name, + TenantID: opts.TenantID, + Description: opts.Description, + }} + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular security group based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// Delete will permanently delete a particular security group based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} + +// IDFromName is a convenience function that returns a security group's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + securityGroupCount := 0 + securityGroupID := "" + if name == "" { + return "", fmt.Errorf("A security group name must be provided.") + } + pager := List(client, ListOpts{}) + pager.EachPage(func(page pagination.Page) (bool, error) { + securityGroupList, err := ExtractGroups(page) + if err != nil { + return false, err + } + + for _, s := range securityGroupList { + if s.Name == name { + securityGroupCount++ + securityGroupID = s.ID + } + } + return true, nil + }) + + switch securityGroupCount { + case 0: + return "", fmt.Errorf("Unable to find security group: %s", name) + case 1: + return securityGroupID, nil + default: + return "", fmt.Errorf("Found %d security groups matching %s", securityGroupCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/results.go new file mode 100644 index 000000000..49db261c2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/results.go @@ -0,0 +1,108 @@ +package groups + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules" + "github.com/rackspace/gophercloud/pagination" +) + +// SecGroup represents a container for security group rules. +type SecGroup struct { + // The UUID for the security group. + ID string + + // Human-readable name for the security group. Might not be unique. Cannot be + // named "default" as that is automatically created for a tenant. + Name string + + // The security group description. + Description string + + // A slice of security group rules that dictate the permitted behaviour for + // traffic entering and leaving the group. + Rules []rules.SecGroupRule `json:"security_group_rules" mapstructure:"security_group_rules"` + + // Owner of the security group. Only admin users can specify a TenantID + // other than their own. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` +} + +// SecGroupPage is the page returned by a pager when traversing over a +// collection of security groups. +type SecGroupPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of security groups has +// reached the end of a page and the pager seeks to traverse over a new one. In +// order to do this, it needs to construct the next page's URL. +func (p SecGroupPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"security_groups_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a SecGroupPage struct is empty. +func (p SecGroupPage) IsEmpty() (bool, error) { + is, err := ExtractGroups(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractGroups accepts a Page struct, specifically a SecGroupPage struct, +// and extracts the elements into a slice of SecGroup structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractGroups(page pagination.Page) ([]SecGroup, error) { + var resp struct { + SecGroups []SecGroup `mapstructure:"security_groups" json:"security_groups"` + } + + err := mapstructure.Decode(page.(SecGroupPage).Body, &resp) + + return resp.SecGroups, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a security group. +func (r commonResult) Extract() (*SecGroup, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + SecGroup *SecGroup `mapstructure:"security_group" json:"security_group"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.SecGroup, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/urls.go new file mode 100644 index 000000000..84f7324f0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups/urls.go @@ -0,0 +1,13 @@ +package groups + +import "github.com/rackspace/gophercloud" + +const rootPath = "security-groups" + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go new file mode 100644 index 000000000..e06934a09 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go @@ -0,0 +1,174 @@ +package rules + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the security group attributes you want to see returned. SortKey allows you to +// sort by a particular network attribute. SortDir sets the direction, and is +// either `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Direction string `q:"direction"` + EtherType string `q:"ethertype"` + ID string `q:"id"` + PortRangeMax int `q:"port_range_max"` + PortRangeMin int `q:"port_range_min"` + Protocol string `q:"protocol"` + RemoteGroupID string `q:"remote_group_id"` + RemoteIPPrefix string `q:"remote_ip_prefix"` + SecGroupID string `q:"security_group_id"` + TenantID string `q:"tenant_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// List returns a Pager which allows you to iterate over a collection of +// security group rules. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { + q, err := gophercloud.BuildQueryString(&opts) + if err != nil { + return pagination.Pager{Err: err} + } + u := rootURL(c) + q.String() + return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page { + return SecGroupRulePage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Errors +var ( + errValidDirectionRequired = fmt.Errorf("A valid Direction is required") + errValidEtherTypeRequired = fmt.Errorf("A valid EtherType is required") + errSecGroupIDRequired = fmt.Errorf("A valid SecGroupID is required") + errValidProtocolRequired = fmt.Errorf("A valid Protocol is required") +) + +// Constants useful for CreateOpts +const ( + DirIngress = "ingress" + DirEgress = "egress" + Ether4 = "IPv4" + Ether6 = "IPv6" + ProtocolTCP = "tcp" + ProtocolUDP = "udp" + ProtocolICMP = "icmp" +) + +// CreateOpts contains all the values needed to create a new security group rule. +type CreateOpts struct { + // Required. Must be either "ingress" or "egress": the direction in which the + // security group rule is applied. + Direction string + + // Required. Must be "IPv4" or "IPv6", and addresses represented in CIDR must + // match the ingress or egress rules. + EtherType string + + // Required. The security group ID to associate with this security group rule. + SecGroupID string + + // Optional. The maximum port number in the range that is matched by the + // security group rule. The PortRangeMin attribute constrains the PortRangeMax + // attribute. If the protocol is ICMP, this value must be an ICMP type. + PortRangeMax int + + // Optional. The minimum port number in the range that is matched by the + // security group rule. If the protocol is TCP or UDP, this value must be + // less than or equal to the value of the PortRangeMax attribute. If the + // protocol is ICMP, this value must be an ICMP type. + PortRangeMin int + + // Optional. The protocol that is matched by the security group rule. Valid + // values are "tcp", "udp", "icmp" or an empty string. + Protocol string + + // Optional. The remote group ID to be associated with this security group + // rule. You can specify either RemoteGroupID or RemoteIPPrefix. + RemoteGroupID string + + // Optional. The remote IP prefix to be associated with this security group + // rule. You can specify either RemoteGroupID or RemoteIPPrefix. This + // attribute matches the specified IP prefix as the source IP address of the + // IP packet. + RemoteIPPrefix string + + // Required for admins. Indicates the owner of the VIP. + TenantID string +} + +// Create is an operation which adds a new security group rule and associates it +// with an existing security group (whose ID is specified in CreateOpts). +func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { + var res CreateResult + + // Validate required opts + if opts.Direction != DirIngress && opts.Direction != DirEgress { + res.Err = errValidDirectionRequired + return res + } + if opts.EtherType != Ether4 && opts.EtherType != Ether6 { + res.Err = errValidEtherTypeRequired + return res + } + if opts.SecGroupID == "" { + res.Err = errSecGroupIDRequired + return res + } + if opts.Protocol != "" && opts.Protocol != ProtocolTCP && opts.Protocol != ProtocolUDP && opts.Protocol != ProtocolICMP { + res.Err = errValidProtocolRequired + return res + } + + type secrule struct { + Direction string `json:"direction"` + EtherType string `json:"ethertype"` + SecGroupID string `json:"security_group_id"` + PortRangeMax int `json:"port_range_max,omitempty"` + PortRangeMin int `json:"port_range_min,omitempty"` + Protocol string `json:"protocol,omitempty"` + RemoteGroupID string `json:"remote_group_id,omitempty"` + RemoteIPPrefix string `json:"remote_ip_prefix,omitempty"` + TenantID string `json:"tenant_id,omitempty"` + } + + type request struct { + SecRule secrule `json:"security_group_rule"` + } + + reqBody := request{SecRule: secrule{ + Direction: opts.Direction, + EtherType: opts.EtherType, + SecGroupID: opts.SecGroupID, + PortRangeMax: opts.PortRangeMax, + PortRangeMin: opts.PortRangeMin, + Protocol: opts.Protocol, + RemoteGroupID: opts.RemoteGroupID, + RemoteIPPrefix: opts.RemoteIPPrefix, + TenantID: opts.TenantID, + }} + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get retrieves a particular security group rule based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil) + return res +} + +// Delete will permanently delete a particular security group rule based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/results.go new file mode 100644 index 000000000..6e1385768 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/results.go @@ -0,0 +1,133 @@ +package rules + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// SecGroupRule represents a rule to dictate the behaviour of incoming or +// outgoing traffic for a particular security group. +type SecGroupRule struct { + // The UUID for this security group rule. + ID string + + // The direction in which the security group rule is applied. The only values + // allowed are "ingress" or "egress". For a compute instance, an ingress + // security group rule is applied to incoming (ingress) traffic for that + // instance. An egress rule is applied to traffic leaving the instance. + Direction string + + // Must be IPv4 or IPv6, and addresses represented in CIDR must match the + // ingress or egress rules. + EtherType string `json:"ethertype" mapstructure:"ethertype"` + + // The security group ID to associate with this security group rule. + SecGroupID string `json:"security_group_id" mapstructure:"security_group_id"` + + // The minimum port number in the range that is matched by the security group + // rule. If the protocol is TCP or UDP, this value must be less than or equal + // to the value of the PortRangeMax attribute. If the protocol is ICMP, this + // value must be an ICMP type. + PortRangeMin int `json:"port_range_min" mapstructure:"port_range_min"` + + // The maximum port number in the range that is matched by the security group + // rule. The PortRangeMin attribute constrains the PortRangeMax attribute. If + // the protocol is ICMP, this value must be an ICMP type. + PortRangeMax int `json:"port_range_max" mapstructure:"port_range_max"` + + // The protocol that is matched by the security group rule. Valid values are + // "tcp", "udp", "icmp" or an empty string. + Protocol string + + // The remote group ID to be associated with this security group rule. You + // can specify either RemoteGroupID or RemoteIPPrefix. + RemoteGroupID string `json:"remote_group_id" mapstructure:"remote_group_id"` + + // The remote IP prefix to be associated with this security group rule. You + // can specify either RemoteGroupID or RemoteIPPrefix . This attribute + // matches the specified IP prefix as the source IP address of the IP packet. + RemoteIPPrefix string `json:"remote_ip_prefix" mapstructure:"remote_ip_prefix"` + + // The owner of this security group rule. + TenantID string `json:"tenant_id" mapstructure:"tenant_id"` +} + +// SecGroupRulePage is the page returned by a pager when traversing over a +// collection of security group rules. +type SecGroupRulePage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of security group rules has +// reached the end of a page and the pager seeks to traverse over a new one. In +// order to do this, it needs to construct the next page's URL. +func (p SecGroupRulePage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"security_group_rules_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a SecGroupRulePage struct is empty. +func (p SecGroupRulePage) IsEmpty() (bool, error) { + is, err := ExtractRules(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractRules accepts a Page struct, specifically a SecGroupRulePage struct, +// and extracts the elements into a slice of SecGroupRule structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractRules(page pagination.Page) ([]SecGroupRule, error) { + var resp struct { + SecGroupRules []SecGroupRule `mapstructure:"security_group_rules" json:"security_group_rules"` + } + + err := mapstructure.Decode(page.(SecGroupRulePage).Body, &resp) + + return resp.SecGroupRules, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a security rule. +func (r commonResult) Extract() (*SecGroupRule, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + SecGroupRule *SecGroupRule `mapstructure:"security_group_rule" json:"security_group_rule"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.SecGroupRule, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/urls.go new file mode 100644 index 000000000..8e2b2bb28 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules/urls.go @@ -0,0 +1,13 @@ +package rules + +import "github.com/rackspace/gophercloud" + +const rootPath = "security-group-rules" + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/doc.go new file mode 100644 index 000000000..c87a7ce27 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/doc.go @@ -0,0 +1,9 @@ +// Package networks contains functionality for working with Neutron network +// resources. A network is an isolated virtual layer-2 broadcast domain that is +// typically reserved for the tenant who created it (unless you configure the +// network to be shared). Tenants can create multiple networks until the +// thresholds per-tenant quota is reached. +// +// In the v2.0 Networking API, the network is the main entity. Ports and subnets +// are always associated with a network. +package networks diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/errors.go new file mode 100644 index 000000000..83c4a6a86 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/errors.go @@ -0,0 +1 @@ +package networks diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/requests.go new file mode 100644 index 000000000..25ab7a8b6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/requests.go @@ -0,0 +1,226 @@ +package networks + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +type networkOpts struct { + AdminStateUp *bool + Name string + Shared *bool + TenantID string +} + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToNetworkListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the network attributes you want to see returned. SortKey allows you to sort +// by a particular network attribute. SortDir sets the direction, and is either +// `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Status string `q:"status"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + TenantID string `q:"tenant_id"` + Shared *bool `q:"shared"` + ID string `q:"id"` + Marker string `q:"marker"` + Limit int `q:"limit"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToNetworkListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToNetworkListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// networks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToNetworkListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return NetworkPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get retrieves a specific network based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToNetworkCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts networkOpts + +// ToNetworkCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) { + n := make(map[string]interface{}) + + if opts.AdminStateUp != nil { + n["admin_state_up"] = &opts.AdminStateUp + } + if opts.Name != "" { + n["name"] = opts.Name + } + if opts.Shared != nil { + n["shared"] = &opts.Shared + } + if opts.TenantID != "" { + n["tenant_id"] = opts.TenantID + } + + return map[string]interface{}{"network": n}, nil +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. This operation does not actually require a request body, i.e. the +// CreateOpts struct argument can be empty. +// +// The tenant ID that is contained in the URI is the tenant that creates the +// network. An admin user, however, has the option of specifying another tenant +// ID in the CreateOpts struct. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToNetworkCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToNetworkUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the common options struct used in this package's Update +// operation. +type UpdateOpts networkOpts + +// ToNetworkUpdateMap casts a UpdateOpts struct to a map. +func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) { + n := make(map[string]interface{}) + + if opts.AdminStateUp != nil { + n["admin_state_up"] = &opts.AdminStateUp + } + if opts.Name != "" { + n["name"] = opts.Name + } + if opts.Shared != nil { + n["shared"] = &opts.Shared + } + + return map[string]interface{}{"network": n}, nil +} + +// Update accepts a UpdateOpts struct and updates an existing network using the +// values provided. For more information, see the Create function. +func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToNetworkUpdateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Put(updateURL(c, networkID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + + return res +} + +// Delete accepts a unique ID and deletes the network associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, networkID), nil) + return res +} + +// IDFromName is a convenience function that returns a network's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + networkCount := 0 + networkID := "" + if name == "" { + return "", fmt.Errorf("A network name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + networkList, err := ExtractNetworks(page) + if err != nil { + return false, err + } + + for _, n := range networkList { + if n.Name == name { + networkCount++ + networkID = n.ID + } + } + return true, nil + }) + + switch networkCount { + case 0: + return "", fmt.Errorf("Unable to find network: %s", name) + case 1: + return networkID, nil + default: + return "", fmt.Errorf("Found %d networks matching %s", networkCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/results.go new file mode 100644 index 000000000..3ecedde9a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/results.go @@ -0,0 +1,116 @@ +package networks + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a network resource. +func (r commonResult) Extract() (*Network, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *Network `json:"network"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Network, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Network represents, well, a network. +type Network struct { + // UUID for the network + ID string `mapstructure:"id" json:"id"` + + // Human-readable name for the network. Might not be unique. + Name string `mapstructure:"name" json:"name"` + + // The administrative state of network. If false (down), the network does not forward packets. + AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"` + + // Indicates whether network is currently operational. Possible values include + // `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values. + Status string `mapstructure:"status" json:"status"` + + // Subnets associated with this network. + Subnets []string `mapstructure:"subnets" json:"subnets"` + + // Owner of network. Only admin users can specify a tenant_id other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` + + // Specifies whether the network resource can be accessed by any tenant or not. + Shared bool `mapstructure:"shared" json:"shared"` +} + +// NetworkPage is the page returned by a pager when traversing over a +// collection of networks. +type NetworkPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of networks has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p NetworkPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"networks_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a NetworkPage struct is empty. +func (p NetworkPage) IsEmpty() (bool, error) { + is, err := ExtractNetworks(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct, +// and extracts the elements into a slice of Network structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractNetworks(page pagination.Page) ([]Network, error) { + var resp struct { + Networks []Network `mapstructure:"networks" json:"networks"` + } + + err := mapstructure.Decode(page.(NetworkPage).Body, &resp) + + return resp.Networks, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/urls.go new file mode 100644 index 000000000..a9eecc529 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/networks/urls.go @@ -0,0 +1,31 @@ +package networks + +import "github.com/rackspace/gophercloud" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("networks", id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("networks") +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go new file mode 100644 index 000000000..f16a4bb01 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go @@ -0,0 +1,8 @@ +// Package ports contains functionality for working with Neutron port resources. +// A port represents a virtual switch port on a logical network switch. Virtual +// instances attach their interfaces into ports. The logical port also defines +// the MAC address and the IP address(es) to be assigned to the interfaces +// plugged into them. When IP addresses are associated to a port, this also +// implies the port is associated with a subnet, as the IP address was taken +// from the allocation pool for a specific subnet. +package ports diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go new file mode 100644 index 000000000..111d977e7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go @@ -0,0 +1,11 @@ +package ports + +import "fmt" + +func err(str string) error { + return fmt.Errorf("%s", str) +} + +var ( + errNetworkIDRequired = err("A Network ID is required") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go new file mode 100644 index 000000000..2caf1cace --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go @@ -0,0 +1,260 @@ +package ports + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToPortListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the port attributes you want to see returned. SortKey allows you to sort +// by a particular port attribute. SortDir sets the direction, and is either +// `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Status string `q:"status"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + NetworkID string `q:"network_id"` + TenantID string `q:"tenant_id"` + DeviceOwner string `q:"device_owner"` + MACAddress string `q:"mac_address"` + ID string `q:"id"` + DeviceID string `q:"device_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToPortListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToPortListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// ports. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those ports that are owned by the tenant +// who submits the request, unless the request is submitted by a user with +// administrative rights. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToPortListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return PortPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get retrieves a specific port based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToPortCreateMap() (map[string]interface{}, error) +} + +// CreateOpts represents the attributes used when creating a new port. +type CreateOpts struct { + NetworkID string + Name string + AdminStateUp *bool + MACAddress string + FixedIPs interface{} + DeviceID string + DeviceOwner string + TenantID string + SecurityGroups []string +} + +// ToPortCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) { + p := make(map[string]interface{}) + + if opts.NetworkID == "" { + return nil, errNetworkIDRequired + } + p["network_id"] = opts.NetworkID + + if opts.DeviceID != "" { + p["device_id"] = opts.DeviceID + } + if opts.DeviceOwner != "" { + p["device_owner"] = opts.DeviceOwner + } + if opts.FixedIPs != nil { + p["fixed_ips"] = opts.FixedIPs + } + if opts.SecurityGroups != nil { + p["security_groups"] = opts.SecurityGroups + } + if opts.TenantID != "" { + p["tenant_id"] = opts.TenantID + } + if opts.AdminStateUp != nil { + p["admin_state_up"] = &opts.AdminStateUp + } + if opts.Name != "" { + p["name"] = opts.Name + } + if opts.MACAddress != "" { + p["mac_address"] = opts.MACAddress + } + + return map[string]interface{}{"port": p}, nil +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. You must remember to provide a NetworkID value. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToPortCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToPortUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts represents the attributes used when updating an existing port. +type UpdateOpts struct { + Name string + AdminStateUp *bool + FixedIPs interface{} + DeviceID string + DeviceOwner string + SecurityGroups []string +} + +// ToPortUpdateMap casts an UpdateOpts struct to a map. +func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) { + p := make(map[string]interface{}) + + if opts.DeviceID != "" { + p["device_id"] = opts.DeviceID + } + if opts.DeviceOwner != "" { + p["device_owner"] = opts.DeviceOwner + } + if opts.FixedIPs != nil { + p["fixed_ips"] = opts.FixedIPs + } + if opts.SecurityGroups != nil { + p["security_groups"] = opts.SecurityGroups + } + if opts.AdminStateUp != nil { + p["admin_state_up"] = &opts.AdminStateUp + } + if opts.Name != "" { + p["name"] = opts.Name + } + + return map[string]interface{}{"port": p}, nil +} + +// Update accepts a UpdateOpts struct and updates an existing port using the +// values provided. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToPortUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + return res +} + +// Delete accepts a unique ID and deletes the port associated with it. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, id), nil) + return res +} + +// IDFromName is a convenience function that returns a port's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + portCount := 0 + portID := "" + if name == "" { + return "", fmt.Errorf("A port name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + portList, err := ExtractPorts(page) + if err != nil { + return false, err + } + + for _, p := range portList { + if p.Name == name { + portCount++ + portID = p.ID + } + } + return true, nil + }) + + switch portCount { + case 0: + return "", fmt.Errorf("Unable to find port: %s", name) + case 1: + return portID, nil + default: + return "", fmt.Errorf("Found %d ports matching %s", portCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go new file mode 100644 index 000000000..2511ff53b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go @@ -0,0 +1,126 @@ +package ports + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a port resource. +func (r commonResult) Extract() (*Port, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Port *Port `json:"port"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Port, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// IP is a sub-struct that represents an individual IP. +type IP struct { + SubnetID string `mapstructure:"subnet_id" json:"subnet_id"` + IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"` +} + +// Port represents a Neutron port. See package documentation for a top-level +// description of what this is. +type Port struct { + // UUID for the port. + ID string `mapstructure:"id" json:"id"` + // Network that this port is associated with. + NetworkID string `mapstructure:"network_id" json:"network_id"` + // Human-readable name for the port. Might not be unique. + Name string `mapstructure:"name" json:"name"` + // Administrative state of port. If false (down), port does not forward packets. + AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"` + // Indicates whether network is currently operational. Possible values include + // `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values. + Status string `mapstructure:"status" json:"status"` + // Mac address to use on this port. + MACAddress string `mapstructure:"mac_address" json:"mac_address"` + // Specifies IP addresses for the port thus associating the port itself with + // the subnets where the IP addresses are picked from + FixedIPs []IP `mapstructure:"fixed_ips" json:"fixed_ips"` + // Owner of network. Only admin users can specify a tenant_id other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` + // Identifies the entity (e.g.: dhcp agent) using this port. + DeviceOwner string `mapstructure:"device_owner" json:"device_owner"` + // Specifies the IDs of any security groups associated with a port. + SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"` + // Identifies the device (e.g., virtual server) using this port. + DeviceID string `mapstructure:"device_id" json:"device_id"` +} + +// PortPage is the page returned by a pager when traversing over a collection +// of network ports. +type PortPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of ports has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p PortPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"ports_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a PortPage struct is empty. +func (p PortPage) IsEmpty() (bool, error) { + is, err := ExtractPorts(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractPorts accepts a Page struct, specifically a PortPage struct, +// and extracts the elements into a slice of Port structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractPorts(page pagination.Page) ([]Port, error) { + var resp struct { + Ports []Port `mapstructure:"ports" json:"ports"` + } + + err := mapstructure.Decode(page.(PortPage).Body, &resp) + + return resp.Ports, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go new file mode 100644 index 000000000..6d0572f1f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go @@ -0,0 +1,31 @@ +package ports + +import "github.com/rackspace/gophercloud" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("ports", id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("ports") +} + +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/doc.go new file mode 100644 index 000000000..43e8296c7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/doc.go @@ -0,0 +1,10 @@ +// Package subnets contains functionality for working with Neutron subnet +// resources. A subnet represents an IP address block that can be used to +// assign IP addresses to virtual instances. Each subnet must have a CIDR and +// must be associated with a network. IPs can either be selected from the whole +// subnet CIDR or from allocation pools specified by the user. +// +// A subnet can also have a gateway, a list of DNS name servers, and host routes. +// This information is pushed to instances whose interfaces are associated with +// the subnet. +package subnets diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/errors.go new file mode 100644 index 000000000..0db0a6e60 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/errors.go @@ -0,0 +1,13 @@ +package subnets + +import "fmt" + +func err(str string) error { + return fmt.Errorf("%s", str) +} + +var ( + errNetworkIDRequired = err("A network ID is required") + errCIDRRequired = err("A valid CIDR is required") + errInvalidIPType = err("An IP type must either be 4 or 6") +) diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/requests.go new file mode 100644 index 000000000..6cde048ed --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/requests.go @@ -0,0 +1,271 @@ +package subnets + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AdminState gives users a solid type to work with for create and update +// operations. It is recommended that users use the `Up` and `Down` enums. +type AdminState *bool + +// Convenience vars for AdminStateUp values. +var ( + iTrue = true + iFalse = false + + Up AdminState = &iTrue + Down AdminState = &iFalse +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToSubnetListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the subnet attributes you want to see returned. SortKey allows you to sort +// by a particular subnet attribute. SortDir sets the direction, and is either +// `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Name string `q:"name"` + EnableDHCP *bool `q:"enable_dhcp"` + NetworkID string `q:"network_id"` + TenantID string `q:"tenant_id"` + IPVersion int `q:"ip_version"` + GatewayIP string `q:"gateway_ip"` + CIDR string `q:"cidr"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToSubnetListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToSubnetListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// subnets. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those subnets that are owned by the tenant +// who submits the request, unless the request is submitted by a user with +// administrative rights. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToSubnetListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return SubnetPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get retrieves a specific subnet based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// Valid IP types +const ( + IPv4 = 4 + IPv6 = 6 +) + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToSubnetCreateMap() (map[string]interface{}, error) +} + +// CreateOpts represents the attributes used when creating a new subnet. +type CreateOpts struct { + // Required + NetworkID string + CIDR string + // Optional + Name string + TenantID string + AllocationPools []AllocationPool + GatewayIP string + IPVersion int + EnableDHCP *bool + DNSNameservers []string + HostRoutes []HostRoute +} + +// ToSubnetCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.NetworkID == "" { + return nil, errNetworkIDRequired + } + if opts.CIDR == "" { + return nil, errCIDRRequired + } + if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 { + return nil, errInvalidIPType + } + + s["network_id"] = opts.NetworkID + s["cidr"] = opts.CIDR + + if opts.EnableDHCP != nil { + s["enable_dhcp"] = &opts.EnableDHCP + } + if opts.Name != "" { + s["name"] = opts.Name + } + if opts.GatewayIP != "" { + s["gateway_ip"] = opts.GatewayIP + } + if opts.TenantID != "" { + s["tenant_id"] = opts.TenantID + } + if opts.IPVersion != 0 { + s["ip_version"] = opts.IPVersion + } + if len(opts.AllocationPools) != 0 { + s["allocation_pools"] = opts.AllocationPools + } + if len(opts.DNSNameservers) != 0 { + s["dns_nameservers"] = opts.DNSNameservers + } + if len(opts.HostRoutes) != 0 { + s["host_routes"] = opts.HostRoutes + } + + return map[string]interface{}{"subnet": s}, nil +} + +// Create accepts a CreateOpts struct and creates a new subnet using the values +// provided. You must remember to provide a valid NetworkID, CIDR and IP version. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToSubnetCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) + return res +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToSubnetUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts represents the attributes used when updating an existing subnet. +type UpdateOpts struct { + Name string + GatewayIP string + DNSNameservers []string + HostRoutes []HostRoute + EnableDHCP *bool +} + +// ToSubnetUpdateMap casts an UpdateOpts struct to a map. +func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.EnableDHCP != nil { + s["enable_dhcp"] = &opts.EnableDHCP + } + if opts.Name != "" { + s["name"] = opts.Name + } + if opts.GatewayIP != "" { + s["gateway_ip"] = opts.GatewayIP + } + if opts.DNSNameservers != nil { + s["dns_nameservers"] = opts.DNSNameservers + } + if opts.HostRoutes != nil { + s["host_routes"] = opts.HostRoutes + } + + return map[string]interface{}{"subnet": s}, nil +} + +// Update accepts a UpdateOpts struct and updates an existing subnet using the +// values provided. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToSubnetUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + + return res +} + +// Delete accepts a unique ID and deletes the subnet associated with it. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, id), nil) + return res +} + +// IDFromName is a convenience function that returns a subnet's ID given its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + subnetCount := 0 + subnetID := "" + if name == "" { + return "", fmt.Errorf("A subnet name must be provided.") + } + pager := List(client, nil) + pager.EachPage(func(page pagination.Page) (bool, error) { + subnetList, err := ExtractSubnets(page) + if err != nil { + return false, err + } + + for _, s := range subnetList { + if s.Name == name { + subnetCount++ + subnetID = s.ID + } + } + return true, nil + }) + + switch subnetCount { + case 0: + return "", fmt.Errorf("Unable to find subnet: %s", name) + case 1: + return subnetID, nil + default: + return "", fmt.Errorf("Found %d subnets matching %s", subnetCount, name) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/results.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/results.go new file mode 100644 index 000000000..77b956a17 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/results.go @@ -0,0 +1,132 @@ +package subnets + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a subnet resource. +func (r commonResult) Extract() (*Subnet, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Subnet *Subnet `json:"subnet"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Subnet, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// AllocationPool represents a sub-range of cidr available for dynamic +// allocation to ports, e.g. {Start: "10.0.0.2", End: "10.0.0.254"} +type AllocationPool struct { + Start string `json:"start"` + End string `json:"end"` +} + +// HostRoute represents a route that should be used by devices with IPs from +// a subnet (not including local subnet route). +type HostRoute struct { + DestinationCIDR string `mapstructure:"destination" json:"destination"` + NextHop string `mapstructure:"nexthop" json:"nexthop"` +} + +// Subnet represents a subnet. See package documentation for a top-level +// description of what this is. +type Subnet struct { + // UUID representing the subnet + ID string `mapstructure:"id" json:"id"` + // UUID of the parent network + NetworkID string `mapstructure:"network_id" json:"network_id"` + // Human-readable name for the subnet. Might not be unique. + Name string `mapstructure:"name" json:"name"` + // IP version, either `4' or `6' + IPVersion int `mapstructure:"ip_version" json:"ip_version"` + // CIDR representing IP range for this subnet, based on IP version + CIDR string `mapstructure:"cidr" json:"cidr"` + // Default gateway used by devices in this subnet + GatewayIP string `mapstructure:"gateway_ip" json:"gateway_ip"` + // DNS name servers used by hosts in this subnet. + DNSNameservers []string `mapstructure:"dns_nameservers" json:"dns_nameservers"` + // Sub-ranges of CIDR available for dynamic allocation to ports. See AllocationPool. + AllocationPools []AllocationPool `mapstructure:"allocation_pools" json:"allocation_pools"` + // Routes that should be used by devices with IPs from this subnet (not including local subnet route). + HostRoutes []HostRoute `mapstructure:"host_routes" json:"host_routes"` + // Specifies whether DHCP is enabled for this subnet or not. + EnableDHCP bool `mapstructure:"enable_dhcp" json:"enable_dhcp"` + // Owner of network. Only admin users can specify a tenant_id other than its own. + TenantID string `mapstructure:"tenant_id" json:"tenant_id"` +} + +// SubnetPage is the page returned by a pager when traversing over a collection +// of subnets. +type SubnetPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of subnets has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (p SubnetPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"subnets_links"` + } + + var r resp + err := mapstructure.Decode(p.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// IsEmpty checks whether a SubnetPage struct is empty. +func (p SubnetPage) IsEmpty() (bool, error) { + is, err := ExtractSubnets(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct, +// and extracts the elements into a slice of Subnet structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractSubnets(page pagination.Page) ([]Subnet, error) { + var resp struct { + Subnets []Subnet `mapstructure:"subnets" json:"subnets"` + } + + err := mapstructure.Decode(page.(SubnetPage).Body, &resp) + + return resp.Subnets, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/urls.go new file mode 100644 index 000000000..0d0236894 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/networking/v2/subnets/urls.go @@ -0,0 +1,31 @@ +package subnets + +import "github.com/rackspace/gophercloud" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("subnets", id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("subnets") +} + +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go new file mode 100644 index 000000000..f5f894a9e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go @@ -0,0 +1,8 @@ +// Package accounts contains functionality for working with Object Storage +// account resources. An account is the top-level resource the object storage +// hierarchy: containers belong to accounts, objects belong to containers. +// +// Another way of thinking of an account is like a namespace for all your +// resources. It is synonymous with a project or tenant in other OpenStack +// services. +package accounts diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go new file mode 100644 index 000000000..f22b68700 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go @@ -0,0 +1,38 @@ +// +build fixtures + +package accounts + +import ( + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleGetAccountSuccessfully creates an HTTP handler at `/` on the test handler mux that +// responds with a `Get` response. +func HandleGetAccountSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "HEAD") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Set("X-Account-Container-Count", "2") + w.Header().Set("X-Account-Bytes-Used", "14") + w.Header().Set("X-Account-Meta-Subject", "books") + + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleUpdateAccountSuccessfully creates an HTTP handler at `/` on the test handler mux that +// responds with a `Update` response. +func HandleUpdateAccountSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "X-Account-Meta-Gophercloud-Test", "accounts") + + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go new file mode 100644 index 000000000..66c46a978 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go @@ -0,0 +1,107 @@ +package accounts + +import "github.com/rackspace/gophercloud" + +// GetOptsBuilder allows extensions to add additional headers to the Get +// request. +type GetOptsBuilder interface { + ToAccountGetMap() (map[string]string, error) +} + +// GetOpts is a structure that contains parameters for getting an account's +// metadata. +type GetOpts struct { + Newest bool `h:"X-Newest"` +} + +// ToAccountGetMap formats a GetOpts into a map[string]string of headers. +func (opts GetOpts) ToAccountGetMap() (map[string]string, error) { + return gophercloud.BuildHeaders(opts) +} + +// Get is a function that retrieves an account's metadata. To extract just the +// custom metadata, call the ExtractMetadata method on the GetResult. To extract +// all the headers that are returned (including the metadata), call the +// ExtractHeader method on the GetResult. +func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) GetResult { + var res GetResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToAccountGetMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("HEAD", getURL(c), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// UpdateOptsBuilder allows extensions to add additional headers to the Update +// request. +type UpdateOptsBuilder interface { + ToAccountUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that contains parameters for updating, creating, or +// deleting an account's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContentType string `h:"Content-Type"` + DetectContentType bool `h:"X-Detect-Content-Type"` + TempURLKey string `h:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `h:"X-Account-Meta-Temp-URL-Key-2"` +} + +// ToAccountUpdateMap formats an UpdateOpts into a map[string]string of headers. +func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) { + headers, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + headers["X-Account-Meta-"+k] = v + } + return headers, err +} + +// Update is a function that creates, updates, or deletes an account's metadata. +// To extract the headers returned, call the Extract method on the UpdateResult. +func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + h := make(map[string]string) + + if opts != nil { + headers, err := opts.ToAccountUpdateMap() + if err != nil { + res.Err = err + return res + } + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("POST", updateURL(c), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201, 202, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go new file mode 100644 index 000000000..6ab1a2306 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go @@ -0,0 +1,102 @@ +package accounts + +import ( + "strings" + "time" + + "github.com/rackspace/gophercloud" +) + +// UpdateResult is returned from a call to the Update function. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// UpdateHeader represents the headers returned in the response from an Update request. +type UpdateHeader struct { + ContentLength string `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (ur UpdateResult) Extract() (UpdateHeader, error) { + var uh UpdateHeader + if ur.Err != nil { + return uh, ur.Err + } + + if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil { + return uh, err + } + + if date, ok := ur.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, ur.Header["Date"][0]) + if err != nil { + return uh, err + } + uh.Date = t + } + + return uh, nil +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"` + ContainerCount int `mapstructure:"X-Account-Container-Count"` + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + ObjectCount int64 `mapstructure:"X-Account-Object-Count"` + TransID string `mapstructure:"X-Trans-Id"` + TempURLKey string `mapstructure:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `mapstructure:"X-Account-Meta-Temp-URL-Key-2"` +} + +// GetResult is returned from a call to the Get function. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (gr GetResult) Extract() (GetHeader, error) { + var gh GetHeader + if gr.Err != nil { + return gh, gr.Err + } + + if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil { + return gh, err + } + + if date, ok := gr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, gr.Header["Date"][0]) + if err != nil { + return gh, err + } + gh.Date = t + } + + return gh, nil +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metatdata associated with the account. +func (gr GetResult) ExtractMetadata() (map[string]string, error) { + if gr.Err != nil { + return nil, gr.Err + } + + metadata := make(map[string]string) + for k, v := range gr.Header { + if strings.HasPrefix(k, "X-Account-Meta-") { + key := strings.TrimPrefix(k, "X-Account-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go new file mode 100644 index 000000000..9952fe434 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go @@ -0,0 +1,11 @@ +package accounts + +import "github.com/rackspace/gophercloud" + +func getURL(c *gophercloud.ServiceClient) string { + return c.Endpoint +} + +func updateURL(c *gophercloud.ServiceClient) string { + return getURL(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go new file mode 100644 index 000000000..5fed5537f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go @@ -0,0 +1,8 @@ +// Package containers contains functionality for working with Object Storage +// container resources. A container serves as a logical namespace for objects +// that are placed inside it - an object with the same name in two different +// containers represents two different objects. +// +// In addition to containing objects, you can also use the container to control +// access to objects by using an access control list (ACL). +package containers diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go new file mode 100644 index 000000000..e60735248 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go @@ -0,0 +1,143 @@ +// +build fixtures + +package containers + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// ExpectedListInfo is the result expected from a call to `List` when full +// info is requested. +var ExpectedListInfo = []Container{ + Container{ + Count: 0, + Bytes: 0, + Name: "janeausten", + }, + Container{ + Count: 1, + Bytes: 14, + Name: "marktwain", + }, +} + +// ExpectedListNames is the result expected from a call to `List` when just +// container names are requested. +var ExpectedListNames = []string{"janeausten", "marktwain"} + +// HandleListContainerInfoSuccessfully creates an HTTP handler at `/` on the test handler mux that +// responds with a `List` response when full info is requested. +func HandleListContainerInfoSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, `[ + { + "count": 0, + "bytes": 0, + "name": "janeausten" + }, + { + "count": 1, + "bytes": 14, + "name": "marktwain" + } + ]`) + case "janeausten": + fmt.Fprintf(w, `[ + { + "count": 1, + "bytes": 14, + "name": "marktwain" + } + ]`) + case "marktwain": + fmt.Fprintf(w, `[]`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// HandleListContainerNamesSuccessfully creates an HTTP handler at `/` on the test handler mux that +// responds with a `ListNames` response when only container names are requested. +func HandleListContainerNamesSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "text/plain") + + w.Header().Set("Content-Type", "text/plain") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, "janeausten\nmarktwain\n") + case "janeausten": + fmt.Fprintf(w, "marktwain\n") + case "marktwain": + fmt.Fprintf(w, ``) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// HandleCreateContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `Create` response. +func HandleCreateContainerSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Add("X-Container-Meta-Foo", "bar") + w.Header().Add("X-Trans-Id", "1234567") + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleDeleteContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `Delete` response. +func HandleDeleteContainerSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleUpdateContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `Update` response. +func HandleUpdateContainerSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleGetContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `Get` response. +func HandleGetContainerSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "HEAD") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go new file mode 100644 index 000000000..50ff9f48f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go @@ -0,0 +1,205 @@ +package containers + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToContainerListParams() (bool, string, error) +} + +// ListOpts is a structure that holds options for listing containers. +type ListOpts struct { + Full bool + Limit int `q:"limit"` + Marker string `q:"marker"` + EndMarker string `q:"end_marker"` + Format string `q:"format"` + Prefix string `q:"prefix"` + Delimiter string `q:"delimiter"` +} + +// ToContainerListParams formats a ListOpts into a query string and boolean +// representing whether to list complete information for each container. +func (opts ListOpts) ToContainerListParams() (bool, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return false, "", err + } + return opts.Full, q.String(), nil +} + +// List is a function that retrieves containers associated with the account as +// well as account metadata. It returns a pager which can be iterated with the +// EachPage function. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"} + + url := listURL(c) + if opts != nil { + full, query, err := opts.ToContainerListParams() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + + if full { + headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"} + } + } + + createPage := func(r pagination.PageResult) pagination.Page { + p := ContainerPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + } + + pager := pagination.NewPager(c, url, createPage) + pager.Headers = headers + return pager +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToContainerCreateMap() (map[string]string, error) +} + +// CreateOpts is a structure that holds parameters for creating a container. +type CreateOpts struct { + Metadata map[string]string + ContainerRead string `h:"X-Container-Read"` + ContainerSyncTo string `h:"X-Container-Sync-To"` + ContainerSyncKey string `h:"X-Container-Sync-Key"` + ContainerWrite string `h:"X-Container-Write"` + ContentType string `h:"Content-Type"` + DetectContentType bool `h:"X-Detect-Content-Type"` + IfNoneMatch string `h:"If-None-Match"` + VersionsLocation string `h:"X-Versions-Location"` +} + +// ToContainerCreateMap formats a CreateOpts into a map of headers. +func (opts CreateOpts) ToContainerCreateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Container-Meta-"+k] = v + } + return h, nil +} + +// Create is a function that creates a new container. +func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) CreateResult { + var res CreateResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToContainerCreateMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("PUT", createURL(c, containerName), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201, 202, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// Delete is a function that deletes a container. +func Delete(c *gophercloud.ServiceClient, containerName string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, containerName), nil) + return res +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToContainerUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that holds parameters for updating, creating, or +// deleting a container's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContainerRead string `h:"X-Container-Read"` + ContainerSyncTo string `h:"X-Container-Sync-To"` + ContainerSyncKey string `h:"X-Container-Sync-Key"` + ContainerWrite string `h:"X-Container-Write"` + ContentType string `h:"Content-Type"` + DetectContentType bool `h:"X-Detect-Content-Type"` + RemoveVersionsLocation string `h:"X-Remove-Versions-Location"` + VersionsLocation string `h:"X-Versions-Location"` +} + +// ToContainerUpdateMap formats a CreateOpts into a map of headers. +func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Container-Meta-"+k] = v + } + return h, nil +} + +// Update is a function that creates, updates, or deletes a container's +// metadata. +func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToContainerUpdateMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("POST", updateURL(c, containerName), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201, 202, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// Get is a function that retrieves the metadata of a container. To extract just +// the custom metadata, pass the GetResult response to the ExtractMetadata +// function. +func Get(c *gophercloud.ServiceClient, containerName string) GetResult { + var res GetResult + resp, err := c.Request("HEAD", getURL(c, containerName), gophercloud.RequestOpts{ + OkCodes: []int{200, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go new file mode 100644 index 000000000..e682b8dcc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go @@ -0,0 +1,270 @@ +package containers + +import ( + "fmt" + "strings" + "time" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Container represents a container resource. +type Container struct { + // The total number of bytes stored in the container. + Bytes int `json:"bytes" mapstructure:"bytes"` + + // The total number of objects stored in the container. + Count int `json:"count" mapstructure:"count"` + + // The name of the container. + Name string `json:"name" mapstructure:"name"` +} + +// ContainerPage is the page returned by a pager when traversing over a +// collection of containers. +type ContainerPage struct { + pagination.MarkerPageBase +} + +// IsEmpty returns true if a ListResult contains no container names. +func (r ContainerPage) IsEmpty() (bool, error) { + names, err := ExtractNames(r) + if err != nil { + return true, err + } + return len(names) == 0, nil +} + +// LastMarker returns the last container name in a ListResult. +func (r ContainerPage) LastMarker() (string, error) { + names, err := ExtractNames(r) + if err != nil { + return "", err + } + if len(names) == 0 { + return "", nil + } + return names[len(names)-1], nil +} + +// ExtractInfo is a function that takes a ListResult and returns the containers' information. +func ExtractInfo(page pagination.Page) ([]Container, error) { + untyped := page.(ContainerPage).Body.([]interface{}) + results := make([]Container, len(untyped)) + for index, each := range untyped { + container := each.(map[string]interface{}) + err := mapstructure.Decode(container, &results[index]) + if err != nil { + return results, err + } + } + return results, nil +} + +// ExtractNames is a function that takes a ListResult and returns the containers' names. +func ExtractNames(page pagination.Page) ([]string, error) { + casted := page.(ContainerPage) + ct := casted.Header.Get("Content-Type") + + switch { + case strings.HasPrefix(ct, "application/json"): + parsed, err := ExtractInfo(page) + if err != nil { + return nil, err + } + + names := make([]string, 0, len(parsed)) + for _, container := range parsed { + names = append(names, container.Name) + } + return names, nil + case strings.HasPrefix(ct, "text/plain"): + names := make([]string, 0, 50) + + body := string(page.(ContainerPage).Body.([]uint8)) + for _, name := range strings.Split(body, "\n") { + if len(name) > 0 { + names = append(names, name) + } + } + + return names, nil + default: + return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct) + } +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + AcceptRanges string `mapstructure:"Accept-Ranges"` + BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"` + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + ObjectCount int64 `mapstructure:"X-Container-Object-Count"` + Read string `mapstructure:"X-Container-Read"` + TransID string `mapstructure:"X-Trans-Id"` + VersionsLocation string `mapstructure:"X-Versions-Location"` + Write string `mapstructure:"X-Container-Write"` +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (gr GetResult) Extract() (GetHeader, error) { + var gh GetHeader + if gr.Err != nil { + return gh, gr.Err + } + + if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil { + return gh, err + } + + if date, ok := gr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, gr.Header["Date"][0]) + if err != nil { + return gh, err + } + gh.Date = t + } + + return gh, nil +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metadata associated with the container. +func (gr GetResult) ExtractMetadata() (map[string]string, error) { + if gr.Err != nil { + return nil, gr.Err + } + metadata := make(map[string]string) + for k, v := range gr.Header { + if strings.HasPrefix(k, "X-Container-Meta-") { + key := strings.TrimPrefix(k, "X-Container-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} + +// CreateHeader represents the headers returned in the response from a Create request. +type CreateHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// CreateResult represents the result of a create operation. To extract the +// the headers from the HTTP response, you can invoke the 'ExtractHeader' +// method on the result struct. +type CreateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Create. To obtain +// a map of headers, call the ExtractHeader method on the CreateResult. +func (cr CreateResult) Extract() (CreateHeader, error) { + var ch CreateHeader + if cr.Err != nil { + return ch, cr.Err + } + + if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil { + return ch, err + } + + if date, ok := cr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["Date"][0]) + if err != nil { + return ch, err + } + ch.Date = t + } + + return ch, nil +} + +// UpdateHeader represents the headers returned in the response from a Update request. +type UpdateHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// UpdateResult represents the result of an update operation. To extract the +// the headers from the HTTP response, you can invoke the 'ExtractHeader' +// method on the result struct. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Update. To obtain +// a map of headers, call the ExtractHeader method on the UpdateResult. +func (ur UpdateResult) Extract() (UpdateHeader, error) { + var uh UpdateHeader + if ur.Err != nil { + return uh, ur.Err + } + + if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil { + return uh, err + } + + if date, ok := ur.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, ur.Header["Date"][0]) + if err != nil { + return uh, err + } + uh.Date = t + } + + return uh, nil +} + +// DeleteHeader represents the headers returned in the response from a Delete request. +type DeleteHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// DeleteResult represents the result of a delete operation. To extract the +// the headers from the HTTP response, you can invoke the 'ExtractHeader' +// method on the result struct. +type DeleteResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Delete. To obtain +// a map of headers, call the ExtractHeader method on the DeleteResult. +func (dr DeleteResult) Extract() (DeleteHeader, error) { + var dh DeleteHeader + if dr.Err != nil { + return dh, dr.Err + } + + if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil { + return dh, err + } + + if date, ok := dr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, dr.Header["Date"][0]) + if err != nil { + return dh, err + } + dh.Date = t + } + + return dh, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go new file mode 100644 index 000000000..f864f846e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go @@ -0,0 +1,23 @@ +package containers + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient) string { + return c.Endpoint +} + +func createURL(c *gophercloud.ServiceClient, container string) string { + return c.ServiceURL(container) +} + +func getURL(c *gophercloud.ServiceClient, container string) string { + return createURL(c, container) +} + +func deleteURL(c *gophercloud.ServiceClient, container string) string { + return createURL(c, container) +} + +func updateURL(c *gophercloud.ServiceClient, container string) string { + return createURL(c, container) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go new file mode 100644 index 000000000..30a9adde1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go @@ -0,0 +1,5 @@ +// Package objects contains functionality for working with Object Storage +// object resources. An object is a resource that represents and contains data +// - such as documents, images, and so on. You can also store custom metadata +// with an object. +package objects diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go new file mode 100644 index 000000000..7a6e6e1ee --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go @@ -0,0 +1,195 @@ +// +build fixtures + +package objects + +import ( + "crypto/md5" + "fmt" + "io" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that +// responds with a `Download` response. +func HandleDownloadObjectSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Successful download with Gophercloud") + }) +} + +// ExpectedListInfo is the result expected from a call to `List` when full +// info is requested. +var ExpectedListInfo = []Object{ + Object{ + Hash: "451e372e48e0f6b1114fa0724aa79fa1", + LastModified: "2009-11-10 23:00:00 +0000 UTC", + Bytes: 14, + Name: "goodbye", + ContentType: "application/octet-stream", + }, + Object{ + Hash: "451e372e48e0f6b1114fa0724aa79fa1", + LastModified: "2009-11-10 23:00:00 +0000 UTC", + Bytes: 14, + Name: "hello", + ContentType: "application/octet-stream", + }, +} + +// ExpectedListNames is the result expected from a call to `List` when just +// object names are requested. +var ExpectedListNames = []string{"hello", "goodbye"} + +// HandleListObjectsInfoSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `List` response when full info is requested. +func HandleListObjectsInfoSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, `[ + { + "hash": "451e372e48e0f6b1114fa0724aa79fa1", + "last_modified": "2009-11-10 23:00:00 +0000 UTC", + "bytes": 14, + "name": "goodbye", + "content_type": "application/octet-stream" + }, + { + "hash": "451e372e48e0f6b1114fa0724aa79fa1", + "last_modified": "2009-11-10 23:00:00 +0000 UTC", + "bytes": 14, + "name": "hello", + "content_type": "application/octet-stream" + } + ]`) + case "hello": + fmt.Fprintf(w, `[]`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// HandleListObjectNamesSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that +// responds with a `List` response when only object names are requested. +func HandleListObjectNamesSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "text/plain") + + w.Header().Set("Content-Type", "text/plain") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, "hello\ngoodbye\n") + case "goodbye": + fmt.Fprintf(w, "") + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// HandleCreateTextObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux +// that responds with a `Create` response. A Content-Type of "text/plain" is expected. +func HandleCreateTextObjectSuccessfully(t *testing.T, content string) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "text/plain") + th.TestHeader(t, r, "Accept", "application/json") + + hash := md5.New() + io.WriteString(hash, content) + localChecksum := hash.Sum(nil) + + w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum)) + w.WriteHeader(http.StatusCreated) + }) +} + +// HandleCreateTypelessObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler +// mux that responds with a `Create` response. No Content-Type header may be present in the request, so that server- +// side content-type detection will be triggered properly. +func HandleCreateTypelessObjectSuccessfully(t *testing.T, content string) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + if contentType, present := r.Header["Content-Type"]; present { + t.Errorf("Expected Content-Type header to be omitted, but was %#v", contentType) + } + + hash := md5.New() + io.WriteString(hash, content) + localChecksum := hash.Sum(nil) + + w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum)) + w.WriteHeader(http.StatusCreated) + }) +} + +// HandleCopyObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that +// responds with a `Copy` response. +func HandleCopyObjectSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "COPY") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "Destination", "/newTestContainer/newTestObject") + w.WriteHeader(http.StatusCreated) + }) +} + +// HandleDeleteObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that +// responds with a `Delete` response. +func HandleDeleteObjectSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} + +// HandleUpdateObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that +// responds with a `Update` response. +func HandleUpdateObjectSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "X-Object-Meta-Gophercloud-Test", "objects") + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleGetObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that +// responds with a `Get` response. +func HandleGetObjectSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "HEAD") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.Header().Add("X-Object-Meta-Gophercloud-Test", "objects") + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go new file mode 100644 index 000000000..f85add0b9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go @@ -0,0 +1,501 @@ +package objects + +import ( + "bufio" + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "fmt" + "io" + "io/ioutil" + "strings" + "time" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToObjectListParams() (bool, string, error) +} + +// ListOpts is a structure that holds parameters for listing objects. +type ListOpts struct { + // Full is a true/false value that represents the amount of object information + // returned. If Full is set to true, then the content-type, number of bytes, hash + // date last modified, and name are returned. If set to false or not set, then + // only the object names are returned. + Full bool + Limit int `q:"limit"` + Marker string `q:"marker"` + EndMarker string `q:"end_marker"` + Format string `q:"format"` + Prefix string `q:"prefix"` + Delimiter string `q:"delimiter"` + Path string `q:"path"` +} + +// ToObjectListParams formats a ListOpts into a query string and boolean +// representing whether to list complete information for each object. +func (opts ListOpts) ToObjectListParams() (bool, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return false, "", err + } + return opts.Full, q.String(), nil +} + +// List is a function that retrieves all objects in a container. It also returns the details +// for the container. To extract only the object information or names, pass the ListResult +// response to the ExtractInfo or ExtractNames function, respectively. +func List(c *gophercloud.ServiceClient, containerName string, opts ListOptsBuilder) pagination.Pager { + headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"} + + url := listURL(c, containerName) + if opts != nil { + full, query, err := opts.ToObjectListParams() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + + if full { + headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"} + } + } + + createPage := func(r pagination.PageResult) pagination.Page { + p := ObjectPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + } + + pager := pagination.NewPager(c, url, createPage) + pager.Headers = headers + return pager +} + +// DownloadOptsBuilder allows extensions to add additional parameters to the +// Download request. +type DownloadOptsBuilder interface { + ToObjectDownloadParams() (map[string]string, string, error) +} + +// DownloadOpts is a structure that holds parameters for downloading an object. +type DownloadOpts struct { + IfMatch string `h:"If-Match"` + IfModifiedSince time.Time `h:"If-Modified-Since"` + IfNoneMatch string `h:"If-None-Match"` + IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"` + Range string `h:"Range"` + Expires string `q:"expires"` + MultipartManifest string `q:"multipart-manifest"` + Signature string `q:"signature"` +} + +// ToObjectDownloadParams formats a DownloadOpts into a query string and map of +// headers. +func (opts DownloadOpts) ToObjectDownloadParams() (map[string]string, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return nil, "", err + } + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, q.String(), err + } + return h, q.String(), nil +} + +// Download is a function that retrieves the content and metadata for an object. +// To extract just the content, pass the DownloadResult response to the +// ExtractContent function. +func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult { + var res DownloadResult + + url := downloadURL(c, containerName, objectName) + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, query, err := opts.ToObjectDownloadParams() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + + url += query + } + + resp, err := c.Request("GET", url, gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{200, 304}, + }) + if resp != nil { + res.Header = resp.Header + res.Body = resp.Body + } + res.Err = err + + return res +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToObjectCreateParams() (map[string]string, string, error) +} + +// CreateOpts is a structure that holds parameters for creating an object. +type CreateOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentLength int64 `h:"Content-Length"` + ContentType string `h:"Content-Type"` + CopyFrom string `h:"X-Copy-From"` + DeleteAfter int `h:"X-Delete-After"` + DeleteAt int `h:"X-Delete-At"` + DetectContentType string `h:"X-Detect-Content-Type"` + ETag string `h:"ETag"` + IfNoneMatch string `h:"If-None-Match"` + ObjectManifest string `h:"X-Object-Manifest"` + TransferEncoding string `h:"Transfer-Encoding"` + Expires string `q:"expires"` + MultipartManifest string `q:"multipart-manifest"` + Signature string `q:"signature"` +} + +// ToObjectCreateParams formats a CreateOpts into a query string and map of +// headers. +func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return nil, "", err + } + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, q.String(), err + } + + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + + return h, q.String(), nil +} + +// Create is a function that creates a new object or replaces an existing object. If the returned response's ETag +// header fails to match the local checksum, the failed request will automatically be retried up to a maximum of 3 times. +func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.ReadSeeker, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + url := createURL(c, containerName, objectName) + h := make(map[string]string) + + if opts != nil { + headers, query, err := opts.ToObjectCreateParams() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + + url += query + } + + hash := md5.New() + bufioReader := bufio.NewReader(io.TeeReader(content, hash)) + io.Copy(ioutil.Discard, bufioReader) + localChecksum := hash.Sum(nil) + + h["ETag"] = fmt.Sprintf("%x", localChecksum) + + _, err := content.Seek(0, 0) + if err != nil { + res.Err = err + return res + } + + ropts := gophercloud.RequestOpts{ + RawBody: content, + MoreHeaders: h, + } + + resp, err := c.Request("PUT", url, ropts) + if err != nil { + res.Err = err + return res + } + if resp != nil { + res.Header = resp.Header + if resp.Header.Get("ETag") == fmt.Sprintf("%x", localChecksum) { + res.Err = err + return res + } + res.Err = fmt.Errorf("Local checksum does not match API ETag header") + } + + return res +} + +// CopyOptsBuilder allows extensions to add additional parameters to the +// Copy request. +type CopyOptsBuilder interface { + ToObjectCopyMap() (map[string]string, error) +} + +// CopyOpts is a structure that holds parameters for copying one object to +// another. +type CopyOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentType string `h:"Content-Type"` + Destination string `h:"Destination,required"` +} + +// ToObjectCopyMap formats a CopyOpts into a map of headers. +func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) { + if opts.Destination == "" { + return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.") + } + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + return h, nil +} + +// Copy is a function that copies one object to another. +func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult { + var res CopyResult + h := c.AuthenticatedHeaders() + + headers, err := opts.ToObjectCopyMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + + url := copyURL(c, containerName, objectName) + resp, err := c.Request("COPY", url, gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// DeleteOptsBuilder allows extensions to add additional parameters to the +// Delete request. +type DeleteOptsBuilder interface { + ToObjectDeleteQuery() (string, error) +} + +// DeleteOpts is a structure that holds parameters for deleting an object. +type DeleteOpts struct { + MultipartManifest string `q:"multipart-manifest"` +} + +// ToObjectDeleteQuery formats a DeleteOpts into a query string. +func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// Delete is a function that deletes an object. +func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult { + var res DeleteResult + url := deleteURL(c, containerName, objectName) + + if opts != nil { + query, err := opts.ToObjectDeleteQuery() + if err != nil { + res.Err = err + return res + } + url += query + } + + resp, err := c.Delete(url, nil) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// GetOptsBuilder allows extensions to add additional parameters to the +// Get request. +type GetOptsBuilder interface { + ToObjectGetQuery() (string, error) +} + +// GetOpts is a structure that holds parameters for getting an object's metadata. +type GetOpts struct { + Expires string `q:"expires"` + Signature string `q:"signature"` +} + +// ToObjectGetQuery formats a GetOpts into a query string. +func (opts GetOpts) ToObjectGetQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// Get is a function that retrieves the metadata of an object. To extract just the custom +// metadata, pass the GetResult response to the ExtractMetadata function. +func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult { + var res GetResult + url := getURL(c, containerName, objectName) + + if opts != nil { + query, err := opts.ToObjectGetQuery() + if err != nil { + res.Err = err + return res + } + url += query + } + + resp, err := c.Request("HEAD", url, gophercloud.RequestOpts{ + OkCodes: []int{200, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToObjectUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an +// object's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentType string `h:"Content-Type"` + DeleteAfter int `h:"X-Delete-After"` + DeleteAt int `h:"X-Delete-At"` + DetectContentType bool `h:"X-Detect-Content-Type"` +} + +// ToObjectUpdateMap formats a UpdateOpts into a map of headers. +func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + return h, nil +} + +// Update is a function that creates, updates, or deletes an object's metadata. +func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToObjectUpdateMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + url := updateURL(c, containerName, objectName) + resp, err := c.Request("POST", url, gophercloud.RequestOpts{ + MoreHeaders: h, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// HTTPMethod represents an HTTP method string (e.g. "GET"). +type HTTPMethod string + +var ( + // GET represents an HTTP "GET" method. + GET HTTPMethod = "GET" + // POST represents an HTTP "POST" method. + POST HTTPMethod = "POST" +) + +// CreateTempURLOpts are options for creating a temporary URL for an object. +type CreateTempURLOpts struct { + // (REQUIRED) Method is the HTTP method to allow for users of the temp URL. Valid values + // are "GET" and "POST". + Method HTTPMethod + // (REQUIRED) TTL is the number of seconds the temp URL should be active. + TTL int + // (Optional) Split is the string on which to split the object URL. Since only + // the object path is used in the hash, the object URL needs to be parsed. If + // empty, the default OpenStack URL split point will be used ("/v1/"). + Split string +} + +// CreateTempURL is a function for creating a temporary URL for an object. It +// allows users to have "GET" or "POST" access to a particular tenant's object +// for a limited amount of time. +func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName string, opts CreateTempURLOpts) (string, error) { + if opts.Split == "" { + opts.Split = "/v1/" + } + duration := time.Duration(opts.TTL) * time.Second + expiry := time.Now().Add(duration).Unix() + getHeader, err := accounts.Get(c, nil).Extract() + if err != nil { + return "", err + } + secretKey := []byte(getHeader.TempURLKey) + url := getURL(c, containerName, objectName) + splitPath := strings.Split(url, opts.Split) + baseURL, objectPath := splitPath[0], splitPath[1] + objectPath = opts.Split + objectPath + body := fmt.Sprintf("%s\n%d\n%s", opts.Method, expiry, objectPath) + hash := hmac.New(sha1.New, secretKey) + hash.Write([]byte(body)) + hexsum := fmt.Sprintf("%x", hash.Sum(nil)) + return fmt.Sprintf("%s%s?temp_url_sig=%s&temp_url_expires=%d", baseURL, objectPath, hexsum, expiry), nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go new file mode 100644 index 000000000..ecb2c5458 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go @@ -0,0 +1,438 @@ +package objects + +import ( + "fmt" + "io" + "io/ioutil" + "strconv" + "strings" + "time" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Object is a structure that holds information related to a storage object. +type Object struct { + // Bytes is the total number of bytes that comprise the object. + Bytes int64 `json:"bytes" mapstructure:"bytes"` + + // ContentType is the content type of the object. + ContentType string `json:"content_type" mapstructure:"content_type"` + + // Hash represents the MD5 checksum value of the object's content. + Hash string `json:"hash" mapstructure:"hash"` + + // LastModified is the RFC3339Milli time the object was last modified, represented + // as a string. For any given object (obj), this value may be parsed to a time.Time: + // lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified) + LastModified string `json:"last_modified" mapstructure:"last_modified"` + + // Name is the unique name for the object. + Name string `json:"name" mapstructure:"name"` +} + +// ObjectPage is a single page of objects that is returned from a call to the +// List function. +type ObjectPage struct { + pagination.MarkerPageBase +} + +// IsEmpty returns true if a ListResult contains no object names. +func (r ObjectPage) IsEmpty() (bool, error) { + names, err := ExtractNames(r) + if err != nil { + return true, err + } + return len(names) == 0, nil +} + +// LastMarker returns the last object name in a ListResult. +func (r ObjectPage) LastMarker() (string, error) { + names, err := ExtractNames(r) + if err != nil { + return "", err + } + if len(names) == 0 { + return "", nil + } + return names[len(names)-1], nil +} + +// ExtractInfo is a function that takes a page of objects and returns their full information. +func ExtractInfo(page pagination.Page) ([]Object, error) { + untyped := page.(ObjectPage).Body.([]interface{}) + results := make([]Object, len(untyped)) + for index, each := range untyped { + object := each.(map[string]interface{}) + err := mapstructure.Decode(object, &results[index]) + if err != nil { + return results, err + } + } + return results, nil +} + +// ExtractNames is a function that takes a page of objects and returns only their names. +func ExtractNames(page pagination.Page) ([]string, error) { + casted := page.(ObjectPage) + ct := casted.Header.Get("Content-Type") + switch { + case strings.HasPrefix(ct, "application/json"): + parsed, err := ExtractInfo(page) + if err != nil { + return nil, err + } + + names := make([]string, 0, len(parsed)) + for _, object := range parsed { + names = append(names, object.Name) + } + + return names, nil + case strings.HasPrefix(ct, "text/plain"): + names := make([]string, 0, 50) + + body := string(page.(ObjectPage).Body.([]uint8)) + for _, name := range strings.Split(body, "\n") { + if len(name) > 0 { + names = append(names, name) + } + } + + return names, nil + case strings.HasPrefix(ct, "text/html"): + return []string{}, nil + default: + return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct) + } +} + +// DownloadHeader represents the headers returned in the response from a Download request. +type DownloadHeader struct { + AcceptRanges string `mapstructure:"Accept-Ranges"` + ContentDisposition string `mapstructure:"Content-Disposition"` + ContentEncoding string `mapstructure:"Content-Encoding"` + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + DeleteAt time.Time `mapstructure:"-"` + ETag string `mapstructure:"Etag"` + LastModified time.Time `mapstructure:"-"` + ObjectManifest string `mapstructure:"X-Object-Manifest"` + StaticLargeObject bool `mapstructure:"X-Static-Large-Object"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// DownloadResult is a *http.Response that is returned from a call to the Download function. +type DownloadResult struct { + gophercloud.HeaderResult + Body io.ReadCloser +} + +// Extract will return a struct of headers returned from a call to Download. To obtain +// a map of headers, call the ExtractHeader method on the DownloadResult. +func (dr DownloadResult) Extract() (DownloadHeader, error) { + var dh DownloadHeader + if dr.Err != nil { + return dh, dr.Err + } + + if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil { + return dh, err + } + + if date, ok := dr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, date[0]) + if err != nil { + return dh, err + } + dh.Date = t + } + + if date, ok := dr.Header["Last-Modified"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, date[0]) + if err != nil { + return dh, err + } + dh.LastModified = t + } + + if date, ok := dr.Header["X-Delete-At"]; ok && len(date) > 0 { + unix, err := strconv.ParseInt(date[0], 10, 64) + if err != nil { + return dh, err + } + dh.DeleteAt = time.Unix(unix, 0) + } + + return dh, nil +} + +// ExtractContent is a function that takes a DownloadResult's io.Reader body +// and reads all available data into a slice of bytes. Please be aware that due +// the nature of io.Reader is forward-only - meaning that it can only be read +// once and not rewound. You can recreate a reader from the output of this +// function by using bytes.NewReader(downloadBytes) +func (dr DownloadResult) ExtractContent() ([]byte, error) { + if dr.Err != nil { + return nil, dr.Err + } + body, err := ioutil.ReadAll(dr.Body) + if err != nil { + return nil, err + } + dr.Body.Close() + return body, nil +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + ContentDisposition string `mapstructure:"Content-Disposition"` + ContentEncoding string `mapstructure:"Content-Encoding"` + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + DeleteAt time.Time `mapstructure:"-"` + ETag string `mapstructure:"Etag"` + LastModified time.Time `mapstructure:"-"` + ObjectManifest string `mapstructure:"X-Object-Manifest"` + StaticLargeObject bool `mapstructure:"X-Static-Large-Object"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// GetResult is a *http.Response that is returned from a call to the Get function. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (gr GetResult) Extract() (GetHeader, error) { + var gh GetHeader + if gr.Err != nil { + return gh, gr.Err + } + + if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil { + return gh, err + } + + if date, ok := gr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, gr.Header["Date"][0]) + if err != nil { + return gh, err + } + gh.Date = t + } + + if date, ok := gr.Header["Last-Modified"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, gr.Header["Last-Modified"][0]) + if err != nil { + return gh, err + } + gh.LastModified = t + } + + if date, ok := gr.Header["X-Delete-At"]; ok && len(date) > 0 { + unix, err := strconv.ParseInt(date[0], 10, 64) + if err != nil { + return gh, err + } + gh.DeleteAt = time.Unix(unix, 0) + } + + return gh, nil +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metadata associated with the object. +func (gr GetResult) ExtractMetadata() (map[string]string, error) { + if gr.Err != nil { + return nil, gr.Err + } + metadata := make(map[string]string) + for k, v := range gr.Header { + if strings.HasPrefix(k, "X-Object-Meta-") { + key := strings.TrimPrefix(k, "X-Object-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} + +// CreateHeader represents the headers returned in the response from a Create request. +type CreateHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + ETag string `mapstructure:"Etag"` + LastModified time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Create. To obtain +// a map of headers, call the ExtractHeader method on the CreateResult. +func (cr CreateResult) Extract() (CreateHeader, error) { + var ch CreateHeader + if cr.Err != nil { + return ch, cr.Err + } + + if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil { + return ch, err + } + + if date, ok := cr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["Date"][0]) + if err != nil { + return ch, err + } + ch.Date = t + } + + if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0]) + if err != nil { + return ch, err + } + ch.LastModified = t + } + + return ch, nil +} + +// UpdateHeader represents the headers returned in the response from a Update request. +type UpdateHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Update. To obtain +// a map of headers, call the ExtractHeader method on the UpdateResult. +func (ur UpdateResult) Extract() (UpdateHeader, error) { + var uh UpdateHeader + if ur.Err != nil { + return uh, ur.Err + } + + if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil { + return uh, err + } + + if date, ok := ur.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, ur.Header["Date"][0]) + if err != nil { + return uh, err + } + uh.Date = t + } + + return uh, nil +} + +// DeleteHeader represents the headers returned in the response from a Delete request. +type DeleteHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Delete. To obtain +// a map of headers, call the ExtractHeader method on the DeleteResult. +func (dr DeleteResult) Extract() (DeleteHeader, error) { + var dh DeleteHeader + if dr.Err != nil { + return dh, dr.Err + } + + if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil { + return dh, err + } + + if date, ok := dr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, dr.Header["Date"][0]) + if err != nil { + return dh, err + } + dh.Date = t + } + + return dh, nil +} + +// CopyHeader represents the headers returned in the response from a Copy request. +type CopyHeader struct { + ContentLength int64 `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + CopiedFrom string `mapstructure:"X-Copied-From"` + CopiedFromLastModified time.Time `mapstructure:"-"` + Date time.Time `mapstructure:"-"` + ETag string `mapstructure:"Etag"` + LastModified time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// CopyResult represents the result of a copy operation. +type CopyResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Copy. To obtain +// a map of headers, call the ExtractHeader method on the CopyResult. +func (cr CopyResult) Extract() (CopyHeader, error) { + var ch CopyHeader + if cr.Err != nil { + return ch, cr.Err + } + + if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil { + return ch, err + } + + if date, ok := cr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["Date"][0]) + if err != nil { + return ch, err + } + ch.Date = t + } + + if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0]) + if err != nil { + return ch, err + } + ch.LastModified = t + } + + if date, ok := cr.Header["X-Copied-From-Last-Modified"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, cr.Header["X-Copied-From-Last-Modified"][0]) + if err != nil { + return ch, err + } + ch.CopiedFromLastModified = t + } + + return ch, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go new file mode 100644 index 000000000..d2ec62cff --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go @@ -0,0 +1,33 @@ +package objects + +import ( + "github.com/rackspace/gophercloud" +) + +func listURL(c *gophercloud.ServiceClient, container string) string { + return c.ServiceURL(container) +} + +func copyURL(c *gophercloud.ServiceClient, container, object string) string { + return c.ServiceURL(container, object) +} + +func createURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func getURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func deleteURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func downloadURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func updateURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/doc.go new file mode 100644 index 000000000..f2db622d1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/doc.go @@ -0,0 +1,4 @@ +// Package apiversions provides information and interaction with the different +// API versions for the OpenStack Heat service. This functionality is not +// restricted to this particular version. +package apiversions diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/requests.go new file mode 100644 index 000000000..f6454c860 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/requests.go @@ -0,0 +1,13 @@ +package apiversions + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// ListVersions lists all the Neutron API versions available to end-users +func ListVersions(c *gophercloud.ServiceClient) pagination.Pager { + return pagination.NewPager(c, apiVersionsURL(c), func(r pagination.PageResult) pagination.Page { + return APIVersionPage{pagination.SinglePageBase(r)} + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/results.go new file mode 100644 index 000000000..0700ab0af --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/results.go @@ -0,0 +1,42 @@ +package apiversions + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// APIVersion represents an API version for Neutron. It contains the status of +// the API, and its unique ID. +type APIVersion struct { + Status string `mapstructure:"status"` + ID string `mapstructure:"id"` + Links []gophercloud.Link `mapstructure:"links"` +} + +// APIVersionPage is the page returned by a pager when traversing over a +// collection of API versions. +type APIVersionPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an APIVersionPage struct is empty. +func (r APIVersionPage) IsEmpty() (bool, error) { + is, err := ExtractAPIVersions(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractAPIVersions takes a collection page, extracts all of the elements, +// and returns them a slice of APIVersion structs. It is effectively a cast. +func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) { + var resp struct { + Versions []APIVersion `mapstructure:"versions"` + } + + err := mapstructure.Decode(page.(APIVersionPage).Body, &resp) + + return resp.Versions, err +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/urls.go new file mode 100644 index 000000000..55d6e0e7a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/apiversions/urls.go @@ -0,0 +1,7 @@ +package apiversions + +import "github.com/rackspace/gophercloud" + +func apiVersionsURL(c *gophercloud.ServiceClient) string { + return c.Endpoint +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/doc.go new file mode 100644 index 000000000..183e8dfa7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/doc.go @@ -0,0 +1,2 @@ +// Package buildinfo provides build information about heat deployments. +package buildinfo diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/fixtures.go new file mode 100644 index 000000000..20ea09b44 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/fixtures.go @@ -0,0 +1,45 @@ +package buildinfo + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// GetExpected represents the expected object from a Get request. +var GetExpected = &BuildInfo{ + API: Revision{ + Revision: "2.4.5", + }, + Engine: Revision{ + Revision: "1.2.1", + }, +} + +// GetOutput represents the response body from a Get request. +const GetOutput = ` +{ + "api": { + "revision": "2.4.5" + }, + "engine": { + "revision": "1.2.1" + } +}` + +// HandleGetSuccessfully creates an HTTP handler at `/build_info` +// on the test handler mux that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/build_info", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/requests.go new file mode 100644 index 000000000..9e03e5cc8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/requests.go @@ -0,0 +1,10 @@ +package buildinfo + +import "github.com/rackspace/gophercloud" + +// Get retreives data for the given stack template. +func Get(c *gophercloud.ServiceClient) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/results.go new file mode 100644 index 000000000..683a434a0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/results.go @@ -0,0 +1,37 @@ +package buildinfo + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" +) + +// Revision represents the API/Engine revision of a Heat deployment. +type Revision struct { + Revision string `mapstructure:"revision"` +} + +// BuildInfo represents the build information for a Heat deployment. +type BuildInfo struct { + API Revision `mapstructure:"api"` + Engine Revision `mapstructure:"engine"` +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a BuildInfo object and is called after a +// Get operation. +func (r GetResult) Extract() (*BuildInfo, error) { + if r.Err != nil { + return nil, r.Err + } + + var res BuildInfo + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/urls.go new file mode 100644 index 000000000..2c873d023 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo/urls.go @@ -0,0 +1,7 @@ +package buildinfo + +import "github.com/rackspace/gophercloud" + +func getURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("build_info") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/doc.go new file mode 100644 index 000000000..51cdd9747 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/doc.go @@ -0,0 +1,4 @@ +// Package stackevents provides operations for finding, listing, and retrieving +// stack events. Stack events are events that take place on stacks such as +// updating and abandoning. +package stackevents diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/fixtures.go new file mode 100644 index 000000000..235787a51 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/fixtures.go @@ -0,0 +1,446 @@ +package stackevents + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/rackspace/gophercloud" + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// FindExpected represents the expected object from a Find request. +var FindExpected = []Event{ + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_IN_PROGRESS", + PhysicalResourceID: "", + ID: "06feb26f-9298-4a9b-8749-9d770e5d577a", + }, + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_COMPLETE", + PhysicalResourceID: "49181cd6-169a-4130-9455-31185bbfc5bf", + ID: "93940999-7d40-44ae-8de4-19624e7b8d18", + }, +} + +// FindOutput represents the response body from a Find request. +const FindOutput = ` +{ + "events": [ + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:11", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_IN_PROGRESS", + "physical_resource_id": null, + "id": "06feb26f-9298-4a9b-8749-9d770e5d577a" + }, + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:27", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_COMPLETE", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "id": "93940999-7d40-44ae-8de4-19624e7b8d18" + } + ] +}` + +// HandleFindSuccessfully creates an HTTP handler at `/stacks/postman_stack/events` +// on the test handler mux that responds with a `Find` response. +func HandleFindSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/postman_stack/events", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// ListExpected represents the expected object from a List request. +var ListExpected = []Event{ + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_IN_PROGRESS", + PhysicalResourceID: "", + ID: "06feb26f-9298-4a9b-8749-9d770e5d577a", + }, + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_COMPLETE", + PhysicalResourceID: "49181cd6-169a-4130-9455-31185bbfc5bf", + ID: "93940999-7d40-44ae-8de4-19624e7b8d18", + }, +} + +// ListOutput represents the response body from a List request. +const ListOutput = ` +{ + "events": [ + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:11", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_IN_PROGRESS", + "physical_resource_id": null, + "id": "06feb26f-9298-4a9b-8749-9d770e5d577a" + }, + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:27", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_COMPLETE", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "id": "93940999-7d40-44ae-8de4-19624e7b8d18" + } + ] +}` + +// HandleListSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/events` +// on the test handler mux that responds with a `List` response. +func HandleListSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/events", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, output) + case "93940999-7d40-44ae-8de4-19624e7b8d18": + fmt.Fprintf(w, `{"events":[]}`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// ListResourceEventsExpected represents the expected object from a ListResourceEvents request. +var ListResourceEventsExpected = []Event{ + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_IN_PROGRESS", + PhysicalResourceID: "", + ID: "06feb26f-9298-4a9b-8749-9d770e5d577a", + }, + Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_COMPLETE", + PhysicalResourceID: "49181cd6-169a-4130-9455-31185bbfc5bf", + ID: "93940999-7d40-44ae-8de4-19624e7b8d18", + }, +} + +// ListResourceEventsOutput represents the response body from a ListResourceEvents request. +const ListResourceEventsOutput = ` +{ + "events": [ + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:11", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_IN_PROGRESS", + "physical_resource_id": null, + "id": "06feb26f-9298-4a9b-8749-9d770e5d577a" + }, + { + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:27", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_COMPLETE", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "id": "93940999-7d40-44ae-8de4-19624e7b8d18" + } + ] +}` + +// HandleListResourceEventsSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources/my_resource/events` +// on the test handler mux that responds with a `ListResourceEvents` response. +func HandleListResourceEventsSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources/my_resource/events", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, output) + case "93940999-7d40-44ae-8de4-19624e7b8d18": + fmt.Fprintf(w, `{"events":[]}`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// GetExpected represents the expected object from a Get request. +var GetExpected = &Event{ + ResourceName: "hello_world", + Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "resource", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalResourceID: "hello_world", + ResourceStatusReason: "state changed", + ResourceStatus: "CREATE_COMPLETE", + PhysicalResourceID: "49181cd6-169a-4130-9455-31185bbfc5bf", + ID: "93940999-7d40-44ae-8de4-19624e7b8d18", +} + +// GetOutput represents the response body from a Get request. +const GetOutput = ` +{ + "event":{ + "resource_name": "hello_world", + "event_time": "2015-02-05T21:33:27", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "resource" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "resource_status": "CREATE_COMPLETE", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "id": "93940999-7d40-44ae-8de4-19624e7b8d18" + } +}` + +// HandleGetSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources/my_resource/events/93940999-7d40-44ae-8de4-19624e7b8d18` +// on the test handler mux that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources/my_resource/events/93940999-7d40-44ae-8de4-19624e7b8d18", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/requests.go new file mode 100644 index 000000000..70c6b97e8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/requests.go @@ -0,0 +1,203 @@ +package stackevents + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Find retrieves stack events for the given stack name. +func Find(c *gophercloud.ServiceClient, stackName string) FindResult { + var res FindResult + + _, res.Err = c.Request("GET", findURL(c, stackName), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + }) + return res +} + +// SortDir is a type for specifying in which direction to sort a list of events. +type SortDir string + +// SortKey is a type for specifying by which key to sort a list of events. +type SortKey string + +// ResourceStatus is a type for specifying by which resource status to filter a +// list of events. +type ResourceStatus string + +// ResourceAction is a type for specifying by which resource action to filter a +// list of events. +type ResourceAction string + +var ( + // ResourceStatusInProgress is used to filter a List request by the 'IN_PROGRESS' status. + ResourceStatusInProgress ResourceStatus = "IN_PROGRESS" + // ResourceStatusComplete is used to filter a List request by the 'COMPLETE' status. + ResourceStatusComplete ResourceStatus = "COMPLETE" + // ResourceStatusFailed is used to filter a List request by the 'FAILED' status. + ResourceStatusFailed ResourceStatus = "FAILED" + + // ResourceActionCreate is used to filter a List request by the 'CREATE' action. + ResourceActionCreate ResourceAction = "CREATE" + // ResourceActionDelete is used to filter a List request by the 'DELETE' action. + ResourceActionDelete ResourceAction = "DELETE" + // ResourceActionUpdate is used to filter a List request by the 'UPDATE' action. + ResourceActionUpdate ResourceAction = "UPDATE" + // ResourceActionRollback is used to filter a List request by the 'ROLLBACK' action. + ResourceActionRollback ResourceAction = "ROLLBACK" + // ResourceActionSuspend is used to filter a List request by the 'SUSPEND' action. + ResourceActionSuspend ResourceAction = "SUSPEND" + // ResourceActionResume is used to filter a List request by the 'RESUME' action. + ResourceActionResume ResourceAction = "RESUME" + // ResourceActionAbandon is used to filter a List request by the 'ABANDON' action. + ResourceActionAbandon ResourceAction = "ABANDON" + + // SortAsc is used to sort a list of stacks in ascending order. + SortAsc SortDir = "asc" + // SortDesc is used to sort a list of stacks in descending order. + SortDesc SortDir = "desc" + + // SortName is used to sort a list of stacks by name. + SortName SortKey = "name" + // SortResourceType is used to sort a list of stacks by resource type. + SortResourceType SortKey = "resource_type" + // SortCreatedAt is used to sort a list of stacks by date created. + SortCreatedAt SortKey = "created_at" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToStackEventListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Marker and Limit are used for pagination. +type ListOpts struct { + // The stack resource ID with which to start the listing. + Marker string `q:"marker"` + // Integer value for the limit of values to return. + Limit int `q:"limit"` + // Filters the event list by the specified ResourceAction. You can use this + // filter multiple times to filter by multiple resource actions: CREATE, DELETE, + // UPDATE, ROLLBACK, SUSPEND, RESUME or ADOPT. + ResourceActions []ResourceAction `q:"resource_action"` + // Filters the event list by the specified resource_status. You can use this + // filter multiple times to filter by multiple resource statuses: IN_PROGRESS, + // COMPLETE or FAILED. + ResourceStatuses []ResourceStatus `q:"resource_status"` + // Filters the event list by the specified resource_name. You can use this + // filter multiple times to filter by multiple resource names. + ResourceNames []string `q:"resource_name"` + // Filters the event list by the specified resource_type. You can use this + // filter multiple times to filter by multiple resource types: OS::Nova::Server, + // OS::Cinder::Volume, and so on. + ResourceTypes []string `q:"resource_type"` + // Sorts the event list by: resource_type or created_at. + SortKey SortKey `q:"sort_keys"` + // The sort direction of the event list. Which is asc (ascending) or desc (descending). + SortDir SortDir `q:"sort_dir"` +} + +// ToStackEventListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToStackEventListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List makes a request against the API to list resources for the given stack. +func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager { + url := listURL(client, stackName, stackID) + + if opts != nil { + query, err := opts.ToStackEventListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPageFn := func(r pagination.PageResult) pagination.Page { + p := EventPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + } + + return pagination.NewPager(client, url, createPageFn) +} + +// ListResourceEventsOptsBuilder allows extensions to add additional parameters to the +// ListResourceEvents request. +type ListResourceEventsOptsBuilder interface { + ToResourceEventListQuery() (string, error) +} + +// ListResourceEventsOpts allows the filtering and sorting of paginated resource events through +// the API. Marker and Limit are used for pagination. +type ListResourceEventsOpts struct { + // The stack resource ID with which to start the listing. + Marker string `q:"marker"` + // Integer value for the limit of values to return. + Limit int `q:"limit"` + // Filters the event list by the specified ResourceAction. You can use this + // filter multiple times to filter by multiple resource actions: CREATE, DELETE, + // UPDATE, ROLLBACK, SUSPEND, RESUME or ADOPT. + ResourceActions []string `q:"resource_action"` + // Filters the event list by the specified resource_status. You can use this + // filter multiple times to filter by multiple resource statuses: IN_PROGRESS, + // COMPLETE or FAILED. + ResourceStatuses []string `q:"resource_status"` + // Filters the event list by the specified resource_name. You can use this + // filter multiple times to filter by multiple resource names. + ResourceNames []string `q:"resource_name"` + // Filters the event list by the specified resource_type. You can use this + // filter multiple times to filter by multiple resource types: OS::Nova::Server, + // OS::Cinder::Volume, and so on. + ResourceTypes []string `q:"resource_type"` + // Sorts the event list by: resource_type or created_at. + SortKey SortKey `q:"sort_keys"` + // The sort direction of the event list. Which is asc (ascending) or desc (descending). + SortDir SortDir `q:"sort_dir"` +} + +// ToResourceEventListQuery formats a ListResourceEventsOpts into a query string. +func (opts ListResourceEventsOpts) ToResourceEventListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListResourceEvents makes a request against the API to list resources for the given stack. +func ListResourceEvents(client *gophercloud.ServiceClient, stackName, stackID, resourceName string, opts ListResourceEventsOptsBuilder) pagination.Pager { + url := listResourceEventsURL(client, stackName, stackID, resourceName) + + if opts != nil { + query, err := opts.ToResourceEventListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPageFn := func(r pagination.PageResult) pagination.Page { + p := EventPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + } + + return pagination.NewPager(client, url, createPageFn) +} + +// Get retreives data for the given stack resource. +func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, stackName, stackID, resourceName, eventID), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/results.go new file mode 100644 index 000000000..cf9e24098 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/results.go @@ -0,0 +1,172 @@ +package stackevents + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Event represents a stack event. +type Event struct { + // The name of the resource for which the event occurred. + ResourceName string `mapstructure:"resource_name"` + // The time the event occurred. + Time time.Time `mapstructure:"-"` + // The URLs to the event. + Links []gophercloud.Link `mapstructure:"links"` + // The logical ID of the stack resource. + LogicalResourceID string `mapstructure:"logical_resource_id"` + // The reason of the status of the event. + ResourceStatusReason string `mapstructure:"resource_status_reason"` + // The status of the event. + ResourceStatus string `mapstructure:"resource_status"` + // The physical ID of the stack resource. + PhysicalResourceID string `mapstructure:"physical_resource_id"` + // The event ID. + ID string `mapstructure:"id"` + // Properties of the stack resource. + ResourceProperties map[string]interface{} `mapstructure:"resource_properties"` +} + +// FindResult represents the result of a Find operation. +type FindResult struct { + gophercloud.Result +} + +// Extract returns a slice of Event objects and is called after a +// Find operation. +func (r FindResult) Extract() ([]Event, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Res []Event `mapstructure:"events"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + events := r.Body.(map[string]interface{})["events"].([]interface{}) + + for i, eventRaw := range events { + event := eventRaw.(map[string]interface{}) + if date, ok := event["event_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res[i].Time = t + } + } + + return res.Res, nil +} + +// EventPage abstracts the raw results of making a List() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the +// data provided through the ExtractResources call. +type EventPage struct { + pagination.MarkerPageBase +} + +// IsEmpty returns true if a page contains no Server results. +func (r EventPage) IsEmpty() (bool, error) { + events, err := ExtractEvents(r) + if err != nil { + return true, err + } + return len(events) == 0, nil +} + +// LastMarker returns the last stack ID in a ListResult. +func (r EventPage) LastMarker() (string, error) { + events, err := ExtractEvents(r) + if err != nil { + return "", err + } + if len(events) == 0 { + return "", nil + } + return events[len(events)-1].ID, nil +} + +// ExtractEvents interprets the results of a single page from a List() call, producing a slice of Event entities. +func ExtractEvents(page pagination.Page) ([]Event, error) { + casted := page.(EventPage).Body + + var res struct { + Res []Event `mapstructure:"events"` + } + + if err := mapstructure.Decode(casted, &res); err != nil { + return nil, err + } + + var events []interface{} + switch casted.(type) { + case map[string]interface{}: + events = casted.(map[string]interface{})["events"].([]interface{}) + case map[string][]interface{}: + events = casted.(map[string][]interface{})["events"] + default: + return res.Res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, eventRaw := range events { + event := eventRaw.(map[string]interface{}) + if date, ok := event["event_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res[i].Time = t + } + } + + return res.Res, nil +} + +// ExtractResourceEvents interprets the results of a single page from a +// ListResourceEvents() call, producing a slice of Event entities. +func ExtractResourceEvents(page pagination.Page) ([]Event, error) { + return ExtractEvents(page) +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract returns a pointer to an Event object and is called after a +// Get operation. +func (r GetResult) Extract() (*Event, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Res *Event `mapstructure:"event"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + event := r.Body.(map[string]interface{})["event"].(map[string]interface{}) + + if date, ok := event["event_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res.Time = t + } + + return res.Res, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/urls.go new file mode 100644 index 000000000..8b5eceb17 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents/urls.go @@ -0,0 +1,19 @@ +package stackevents + +import "github.com/rackspace/gophercloud" + +func findURL(c *gophercloud.ServiceClient, stackName string) string { + return c.ServiceURL("stacks", stackName, "events") +} + +func listURL(c *gophercloud.ServiceClient, stackName, stackID string) string { + return c.ServiceURL("stacks", stackName, stackID, "events") +} + +func listResourceEventsURL(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) string { + return c.ServiceURL("stacks", stackName, stackID, "resources", resourceName, "events") +} + +func getURL(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) string { + return c.ServiceURL("stacks", stackName, stackID, "resources", resourceName, "events", eventID) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/doc.go new file mode 100644 index 000000000..e4f8b08dc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/doc.go @@ -0,0 +1,5 @@ +// Package stackresources provides operations for working with stack resources. +// A resource is a template artifact that represents some component of your +// desired architecture (a Cloud Server, a group of scaled Cloud Servers, a load +// balancer, some configuration management system, and so forth). +package stackresources diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/fixtures.go new file mode 100644 index 000000000..952dc54d1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/fixtures.go @@ -0,0 +1,439 @@ +package stackresources + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/rackspace/gophercloud" + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// FindExpected represents the expected object from a Find request. +var FindExpected = []Resource{ + Resource{ + Name: "hello_world", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalID: "hello_world", + StatusReason: "state changed", + UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), + CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC), + RequiredBy: []interface{}{}, + Status: "CREATE_IN_PROGRESS", + PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf", + Type: "OS::Nova::Server", + Attributes: map[string]interface{}{"SXSW": "atx"}, + Description: "Some resource", + }, +} + +// FindOutput represents the response body from a Find request. +const FindOutput = ` +{ + "resources": [ + { + "description": "Some resource", + "attributes": {"SXSW": "atx"}, + "resource_name": "hello_world", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "updated_time": "2015-02-05T21:33:11", + "creation_time": "2015-02-05T21:33:10", + "required_by": [], + "resource_status": "CREATE_IN_PROGRESS", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "resource_type": "OS::Nova::Server" + } + ] +}` + +// HandleFindSuccessfully creates an HTTP handler at `/stacks/hello_world/resources` +// on the test handler mux that responds with a `Find` response. +func HandleFindSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/hello_world/resources", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// ListExpected represents the expected object from a List request. +var ListExpected = []Resource{ + Resource{ + Name: "hello_world", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + Rel: "stack", + }, + }, + LogicalID: "hello_world", + StatusReason: "state changed", + UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), + CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC), + RequiredBy: []interface{}{}, + Status: "CREATE_IN_PROGRESS", + PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf", + Type: "OS::Nova::Server", + Attributes: map[string]interface{}{"SXSW": "atx"}, + Description: "Some resource", + }, +} + +// ListOutput represents the response body from a List request. +const ListOutput = `{ + "resources": [ + { + "resource_name": "hello_world", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", + "rel": "stack" + } + ], + "logical_resource_id": "hello_world", + "resource_status_reason": "state changed", + "updated_time": "2015-02-05T21:33:11", + "required_by": [], + "resource_status": "CREATE_IN_PROGRESS", + "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", + "creation_time": "2015-02-05T21:33:10", + "resource_type": "OS::Nova::Server", + "attributes": {"SXSW": "atx"}, + "description": "Some resource" + } +] +}` + +// HandleListSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources` +// on the test handler mux that responds with a `List` response. +func HandleListSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, output) + case "49181cd6-169a-4130-9455-31185bbfc5bf": + fmt.Fprintf(w, `{"resources":[]}`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// GetExpected represents the expected object from a Get request. +var GetExpected = &Resource{ + Name: "wordpress_instance", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", + Rel: "self", + }, + gophercloud.Link{ + Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e", + Rel: "stack", + }, + }, + LogicalID: "wordpress_instance", + Attributes: map[string]interface{}{"SXSW": "atx"}, + StatusReason: "state changed", + UpdatedTime: time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC), + RequiredBy: []interface{}{}, + Status: "CREATE_COMPLETE", + PhysicalID: "00e3a2fe-c65d-403c-9483-4db9930dd194", + Type: "OS::Nova::Server", +} + +// GetOutput represents the response body from a Get request. +const GetOutput = ` +{ + "resource": { + "description": "Some resource", + "attributes": {"SXSW": "atx"}, + "resource_name": "wordpress_instance", + "description": "", + "links": [ + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", + "rel": "self" + }, + { + "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e", + "rel": "stack" + } + ], + "logical_resource_id": "wordpress_instance", + "resource_status": "CREATE_COMPLETE", + "updated_time": "2014-12-10T18:34:35", + "required_by": [], + "resource_status_reason": "state changed", + "physical_resource_id": "00e3a2fe-c65d-403c-9483-4db9930dd194", + "resource_type": "OS::Nova::Server" + } +}` + +// HandleGetSuccessfully creates an HTTP handler at `/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance` +// on the test handler mux that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// MetadataExpected represents the expected object from a Metadata request. +var MetadataExpected = map[string]string{ + "number": "7", + "animal": "auk", +} + +// MetadataOutput represents the response body from a Metadata request. +const MetadataOutput = ` +{ + "metadata": { + "number": "7", + "animal": "auk" + } +}` + +// HandleMetadataSuccessfully creates an HTTP handler at `/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance/metadata` +// on the test handler mux that responds with a `Metadata` response. +func HandleMetadataSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance/metadata", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// ListTypesExpected represents the expected object from a ListTypes request. +var ListTypesExpected = ResourceTypes{ + "OS::Nova::Server", + "OS::Heat::RandomString", + "OS::Swift::Container", + "OS::Trove::Instance", + "OS::Nova::FloatingIPAssociation", + "OS::Cinder::VolumeAttachment", + "OS::Nova::FloatingIP", + "OS::Nova::KeyPair", +} + +// same as above, but sorted +var SortedListTypesExpected = ResourceTypes{ + "OS::Cinder::VolumeAttachment", + "OS::Heat::RandomString", + "OS::Nova::FloatingIP", + "OS::Nova::FloatingIPAssociation", + "OS::Nova::KeyPair", + "OS::Nova::Server", + "OS::Swift::Container", + "OS::Trove::Instance", +} + +// ListTypesOutput represents the response body from a ListTypes request. +const ListTypesOutput = ` +{ + "resource_types": [ + "OS::Nova::Server", + "OS::Heat::RandomString", + "OS::Swift::Container", + "OS::Trove::Instance", + "OS::Nova::FloatingIPAssociation", + "OS::Cinder::VolumeAttachment", + "OS::Nova::FloatingIP", + "OS::Nova::KeyPair" + ] +}` + +// HandleListTypesSuccessfully creates an HTTP handler at `/resource_types` +// on the test handler mux that responds with a `ListTypes` response. +func HandleListTypesSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/resource_types", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// GetSchemaExpected represents the expected object from a Schema request. +var GetSchemaExpected = &TypeSchema{ + Attributes: map[string]interface{}{ + "an_attribute": map[string]interface{}{ + "description": "An attribute description .", + }, + }, + Properties: map[string]interface{}{ + "a_property": map[string]interface{}{ + "update_allowed": false, + "required": true, + "type": "string", + "description": "A resource description.", + }, + }, + ResourceType: "OS::Heat::AResourceName", + SupportStatus: map[string]interface{}{ + "message": "A status message", + "status": "SUPPORTED", + "version": "2014.1", + }, +} + +// GetSchemaOutput represents the response body from a Schema request. +const GetSchemaOutput = ` +{ + "attributes": { + "an_attribute": { + "description": "An attribute description ." + } + }, + "properties": { + "a_property": { + "update_allowed": false, + "required": true, + "type": "string", + "description": "A resource description." + } + }, + "resource_type": "OS::Heat::AResourceName", + "support_status": { + "message": "A status message", + "status": "SUPPORTED", + "version": "2014.1" + } +}` + +// HandleGetSchemaSuccessfully creates an HTTP handler at `/resource_types/OS::Heat::AResourceName` +// on the test handler mux that responds with a `Schema` response. +func HandleGetSchemaSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/resource_types/OS::Heat::AResourceName", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// GetTemplateExpected represents the expected object from a Template request. +var GetTemplateExpected = "{\n \"HeatTemplateFormatVersion\": \"2012-12-12\",\n \"Outputs\": {\n \"private_key\": {\n \"Description\": \"The private key if it has been saved.\",\n \"Value\": \"{\\\"Fn::GetAtt\\\": [\\\"KeyPair\\\", \\\"private_key\\\"]}\"\n },\n \"public_key\": {\n \"Description\": \"The public key.\",\n \"Value\": \"{\\\"Fn::GetAtt\\\": [\\\"KeyPair\\\", \\\"public_key\\\"]}\"\n }\n },\n \"Parameters\": {\n \"name\": {\n \"Description\": \"The name of the key pair.\",\n \"Type\": \"String\"\n },\n \"public_key\": {\n \"Description\": \"The optional public key. This allows users to supply the public key from a pre-existing key pair. If not supplied, a new key pair will be generated.\",\n \"Type\": \"String\"\n },\n \"save_private_key\": {\n \"AllowedValues\": [\n \"True\",\n \"true\",\n \"False\",\n \"false\"\n ],\n \"Default\": false,\n \"Description\": \"True if the system should remember a generated private key; False otherwise.\",\n \"Type\": \"String\"\n }\n },\n \"Resources\": {\n \"KeyPair\": {\n \"Properties\": {\n \"name\": {\n \"Ref\": \"name\"\n },\n \"public_key\": {\n \"Ref\": \"public_key\"\n },\n \"save_private_key\": {\n \"Ref\": \"save_private_key\"\n }\n },\n \"Type\": \"OS::Nova::KeyPair\"\n }\n }\n}" + +// GetTemplateOutput represents the response body from a Template request. +const GetTemplateOutput = ` +{ + "HeatTemplateFormatVersion": "2012-12-12", + "Outputs": { + "private_key": { + "Description": "The private key if it has been saved.", + "Value": "{\"Fn::GetAtt\": [\"KeyPair\", \"private_key\"]}" + }, + "public_key": { + "Description": "The public key.", + "Value": "{\"Fn::GetAtt\": [\"KeyPair\", \"public_key\"]}" + } + }, + "Parameters": { + "name": { + "Description": "The name of the key pair.", + "Type": "String" + }, + "public_key": { + "Description": "The optional public key. This allows users to supply the public key from a pre-existing key pair. If not supplied, a new key pair will be generated.", + "Type": "String" + }, + "save_private_key": { + "AllowedValues": [ + "True", + "true", + "False", + "false" + ], + "Default": false, + "Description": "True if the system should remember a generated private key; False otherwise.", + "Type": "String" + } + }, + "Resources": { + "KeyPair": { + "Properties": { + "name": { + "Ref": "name" + }, + "public_key": { + "Ref": "public_key" + }, + "save_private_key": { + "Ref": "save_private_key" + } + }, + "Type": "OS::Nova::KeyPair" + } + } +}` + +// HandleGetTemplateSuccessfully creates an HTTP handler at `/resource_types/OS::Heat::AResourceName/template` +// on the test handler mux that responds with a `Template` response. +func HandleGetTemplateSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/resource_types/OS::Heat::AResourceName/template", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/requests.go new file mode 100644 index 000000000..fcb8d8a2f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/requests.go @@ -0,0 +1,113 @@ +package stackresources + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Find retrieves stack resources for the given stack name. +func Find(c *gophercloud.ServiceClient, stackName string) FindResult { + var res FindResult + + // Send request to API + _, res.Err = c.Request("GET", findURL(c, stackName), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + }) + return res +} + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToStackResourceListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Marker and Limit are used for pagination. +type ListOpts struct { + // Include resources from nest stacks up to Depth levels of recursion. + Depth int `q:"nested_depth"` +} + +// ToStackResourceListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToStackResourceListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List makes a request against the API to list resources for the given stack. +func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager { + url := listURL(client, stackName, stackID) + + if opts != nil { + query, err := opts.ToStackResourceListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPageFn := func(r pagination.PageResult) pagination.Page { + return ResourcePage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, url, createPageFn) +} + +// Get retreives data for the given stack resource. +func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) GetResult { + var res GetResult + + // Send request to API + _, res.Err = c.Get(getURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Metadata retreives the metadata for the given stack resource. +func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) MetadataResult { + var res MetadataResult + + // Send request to API + _, res.Err = c.Get(metadataURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// ListTypes makes a request against the API to list resource types. +func ListTypes(client *gophercloud.ServiceClient) pagination.Pager { + url := listTypesURL(client) + + createPageFn := func(r pagination.PageResult) pagination.Page { + return ResourceTypePage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, url, createPageFn) +} + +// Schema retreives the schema for the given resource type. +func Schema(c *gophercloud.ServiceClient, resourceType string) SchemaResult { + var res SchemaResult + + // Send request to API + _, res.Err = c.Get(schemaURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Template retreives the template representation for the given resource type. +func Template(c *gophercloud.ServiceClient, resourceType string) TemplateResult { + var res TemplateResult + + // Send request to API + _, res.Err = c.Get(templateURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/results.go new file mode 100644 index 000000000..6ddc7660d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/results.go @@ -0,0 +1,284 @@ +package stackresources + +import ( + "encoding/json" + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Resource represents a stack resource. +type Resource struct { + Attributes map[string]interface{} `mapstructure:"attributes"` + CreationTime time.Time `mapstructure:"-"` + Description string `mapstructure:"description"` + Links []gophercloud.Link `mapstructure:"links"` + LogicalID string `mapstructure:"logical_resource_id"` + Name string `mapstructure:"resource_name"` + PhysicalID string `mapstructure:"physical_resource_id"` + RequiredBy []interface{} `mapstructure:"required_by"` + Status string `mapstructure:"resource_status"` + StatusReason string `mapstructure:"resource_status_reason"` + Type string `mapstructure:"resource_type"` + UpdatedTime time.Time `mapstructure:"-"` +} + +// FindResult represents the result of a Find operation. +type FindResult struct { + gophercloud.Result +} + +// Extract returns a slice of Resource objects and is called after a +// Find operation. +func (r FindResult) Extract() ([]Resource, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Res []Resource `mapstructure:"resources"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + resources := r.Body.(map[string]interface{})["resources"].([]interface{}) + + for i, resourceRaw := range resources { + resource := resourceRaw.(map[string]interface{}) + if date, ok := resource["updated_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res[i].UpdatedTime = t + } + if date, ok := resource["creation_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res[i].CreationTime = t + } + } + + return res.Res, nil +} + +// ResourcePage abstracts the raw results of making a List() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the +// data provided through the ExtractResources call. +type ResourcePage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a page contains no Server results. +func (r ResourcePage) IsEmpty() (bool, error) { + resources, err := ExtractResources(r) + if err != nil { + return true, err + } + return len(resources) == 0, nil +} + +// ExtractResources interprets the results of a single page from a List() call, producing a slice of Resource entities. +func ExtractResources(page pagination.Page) ([]Resource, error) { + casted := page.(ResourcePage).Body + + var response struct { + Resources []Resource `mapstructure:"resources"` + } + if err := mapstructure.Decode(casted, &response); err != nil { + return nil, err + } + var resources []interface{} + switch casted.(type) { + case map[string]interface{}: + resources = casted.(map[string]interface{})["resources"].([]interface{}) + case map[string][]interface{}: + resources = casted.(map[string][]interface{})["resources"] + default: + return response.Resources, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, resourceRaw := range resources { + resource := resourceRaw.(map[string]interface{}) + if date, ok := resource["updated_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + response.Resources[i].UpdatedTime = t + } + if date, ok := resource["creation_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + response.Resources[i].CreationTime = t + } + } + + return response.Resources, nil +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a Resource object and is called after a +// Get operation. +func (r GetResult) Extract() (*Resource, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Res *Resource `mapstructure:"resource"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + resource := r.Body.(map[string]interface{})["resource"].(map[string]interface{}) + + if date, ok := resource["updated_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res.UpdatedTime = t + } + if date, ok := resource["creation_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Res.CreationTime = t + } + + return res.Res, nil +} + +// MetadataResult represents the result of a Metadata operation. +type MetadataResult struct { + gophercloud.Result +} + +// Extract returns a map object and is called after a +// Metadata operation. +func (r MetadataResult) Extract() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Meta map[string]string `mapstructure:"metadata"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return res.Meta, nil +} + +// ResourceTypePage abstracts the raw results of making a ListTypes() request against the API. +// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the +// data provided through the ExtractResourceTypes call. +type ResourceTypePage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ResourceTypePage contains no resource types. +func (r ResourceTypePage) IsEmpty() (bool, error) { + rts, err := ExtractResourceTypes(r) + if err != nil { + return true, err + } + return len(rts) == 0, nil +} + +// ResourceTypes represents the type that holds the result of ExtractResourceTypes. +// We define methods on this type to sort it before output +type ResourceTypes []string + +func (r ResourceTypes) Len() int { + return len(r) +} + +func (r ResourceTypes) Swap(i, j int) { + r[i], r[j] = r[j], r[i] +} + +func (r ResourceTypes) Less(i, j int) bool { + return r[i] < r[j] +} + +// ExtractResourceTypes extracts and returns resource types. +func ExtractResourceTypes(page pagination.Page) (ResourceTypes, error) { + casted := page.(ResourceTypePage).Body + + var response struct { + ResourceTypes ResourceTypes `mapstructure:"resource_types"` + } + + if err := mapstructure.Decode(casted, &response); err != nil { + return nil, err + } + return response.ResourceTypes, nil +} + +// TypeSchema represents a stack resource schema. +type TypeSchema struct { + Attributes map[string]interface{} `mapstructure:"attributes"` + Properties map[string]interface{} `mapstrucutre:"properties"` + ResourceType string `mapstructure:"resource_type"` + SupportStatus map[string]interface{} `mapstructure:"support_status"` +} + +// SchemaResult represents the result of a Schema operation. +type SchemaResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a TypeSchema object and is called after a +// Schema operation. +func (r SchemaResult) Extract() (*TypeSchema, error) { + if r.Err != nil { + return nil, r.Err + } + + var res TypeSchema + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return &res, nil +} + +// TemplateResult represents the result of a Template operation. +type TemplateResult struct { + gophercloud.Result +} + +// Extract returns the template and is called after a +// Template operation. +func (r TemplateResult) Extract() ([]byte, error) { + if r.Err != nil { + return nil, r.Err + } + template, err := json.MarshalIndent(r.Body, "", " ") + if err != nil { + return nil, err + } + return template, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/urls.go new file mode 100644 index 000000000..ef078d9c9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources/urls.go @@ -0,0 +1,31 @@ +package stackresources + +import "github.com/rackspace/gophercloud" + +func findURL(c *gophercloud.ServiceClient, stackName string) string { + return c.ServiceURL("stacks", stackName, "resources") +} + +func listURL(c *gophercloud.ServiceClient, stackName, stackID string) string { + return c.ServiceURL("stacks", stackName, stackID, "resources") +} + +func getURL(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) string { + return c.ServiceURL("stacks", stackName, stackID, "resources", resourceName) +} + +func metadataURL(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) string { + return c.ServiceURL("stacks", stackName, stackID, "resources", resourceName, "metadata") +} + +func listTypesURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("resource_types") +} + +func schemaURL(c *gophercloud.ServiceClient, typeName string) string { + return c.ServiceURL("resource_types", typeName) +} + +func templateURL(c *gophercloud.ServiceClient, typeName string) string { + return c.ServiceURL("resource_types", typeName, "template") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/doc.go new file mode 100644 index 000000000..19231b513 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/doc.go @@ -0,0 +1,8 @@ +// Package stacks provides operation for working with Heat stacks. A stack is a +// group of resources (servers, load balancers, databases, and so forth) +// combined to fulfill a useful purpose. Based on a template, Heat orchestration +// engine creates an instantiated set of resources (a stack) to run the +// application framework or component specified (in the template). A stack is a +// running instance of a template. The result of creating a stack is a deployment +// of the application framework or component. +package stacks diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/environment.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/environment.go new file mode 100644 index 000000000..abaff2057 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/environment.go @@ -0,0 +1,137 @@ +package stacks + +import ( + "fmt" + "strings" +) + +// Environment is a structure that represents stack environments +type Environment struct { + TE +} + +// EnvironmentSections is a map containing allowed sections in a stack environment file +var EnvironmentSections = map[string]bool{ + "parameters": true, + "parameter_defaults": true, + "resource_registry": true, +} + +// Validate validates the contents of the Environment +func (e *Environment) Validate() error { + if e.Parsed == nil { + if err := e.Parse(); err != nil { + return err + } + } + for key := range e.Parsed { + if _, ok := EnvironmentSections[key]; !ok { + return fmt.Errorf("Environment has wrong section: %s", key) + } + } + return nil +} + +// Parse environment file to resolve the URL's of the resources. This is done by +// reading from the `Resource Registry` section, which is why the function is +// named GetRRFileContents. +func (e *Environment) getRRFileContents(ignoreIf igFunc) error { + // initialize environment if empty + if e.Files == nil { + e.Files = make(map[string]string) + } + if e.fileMaps == nil { + e.fileMaps = make(map[string]string) + } + + // get the resource registry + rr := e.Parsed["resource_registry"] + + // search the resource registry for URLs + switch rr.(type) { + // process further only if the resource registry is a map + case map[string]interface{}, map[interface{}]interface{}: + rrMap, err := toStringKeys(rr) + if err != nil { + return err + } + // the resource registry might contain a base URL for the resource. If + // such a field is present, use it. Otherwise, use the default base URL. + var baseURL string + if val, ok := rrMap["base_url"]; ok { + baseURL = val.(string) + } else { + baseURL = e.baseURL + } + + // The contents of the resource may be located in a remote file, which + // will be a template. Instantiate a temporary template to manage the + // contents. + tempTemplate := new(Template) + tempTemplate.baseURL = baseURL + tempTemplate.client = e.client + + // Fetch the contents of remote resource URL's + if err = tempTemplate.getFileContents(rr, ignoreIf, false); err != nil { + return err + } + // check the `resources` section (if it exists) for more URL's. Note that + // the previous call to GetFileContents was (deliberately) not recursive + // as we want more control over where to look for URL's + if val, ok := rrMap["resources"]; ok { + switch val.(type) { + // process further only if the contents are a map + case map[string]interface{}, map[interface{}]interface{}: + resourcesMap, err := toStringKeys(val) + if err != nil { + return err + } + for _, v := range resourcesMap { + switch v.(type) { + case map[string]interface{}, map[interface{}]interface{}: + resourceMap, err := toStringKeys(v) + if err != nil { + return err + } + var resourceBaseURL string + // if base_url for the resource type is defined, use it + if val, ok := resourceMap["base_url"]; ok { + resourceBaseURL = val.(string) + } else { + resourceBaseURL = baseURL + } + tempTemplate.baseURL = resourceBaseURL + if err := tempTemplate.getFileContents(v, ignoreIf, false); err != nil { + return err + } + } + } + } + } + // if the resource registry contained any URL's, store them. This can + // then be passed as parameter to api calls to Heat api. + e.Files = tempTemplate.Files + return nil + default: + return nil + } +} + +// function to choose keys whose values are other environment files +func ignoreIfEnvironment(key string, value interface{}) bool { + // base_url and hooks refer to components which cannot have urls + if key == "base_url" || key == "hooks" { + return true + } + // if value is not string, it cannot be a URL + valueString, ok := value.(string) + if !ok { + return true + } + // if value contains `::`, it must be a reference to another resource type + // e.g. OS::Nova::Server : Rackspace::Cloud::Server + if strings.Contains(valueString, "::") { + return true + } + return false +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/fixtures.go new file mode 100644 index 000000000..83f5dec8d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/fixtures.go @@ -0,0 +1,604 @@ +package stacks + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/rackspace/gophercloud" + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// CreateExpected represents the expected object from a Create request. +var CreateExpected = &CreatedStack{ + ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://168.28.170.117:8004/v1/98606384f58drad0bhdb7d02779549ac/stacks/stackcreated/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Rel: "self", + }, + }, +} + +// CreateOutput represents the response body from a Create request. +const CreateOutput = ` +{ + "stack": { + "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "links": [ + { + "href": "http://168.28.170.117:8004/v1/98606384f58drad0bhdb7d02779549ac/stacks/stackcreated/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "rel": "self" + } + ] + } +}` + +// HandleCreateSuccessfully creates an HTTP handler at `/stacks` on the test handler mux +// that responds with a `Create` response. +func HandleCreateSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, output) + }) +} + +// ListExpected represents the expected object from a List request. +var ListExpected = []ListedStack{ + ListedStack{ + Description: "Simple template to test heat commands", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Rel: "self", + }, + }, + StatusReason: "Stack CREATE completed successfully", + Name: "postman_stack", + CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC), + Status: "CREATE_COMPLETE", + ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Tags: []string{"rackspace", "atx"}, + }, + ListedStack{ + Description: "Simple template to test heat commands", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/gophercloud-test-stack-2/db6977b2-27aa-4775-9ae7-6213212d4ada", + Rel: "self", + }, + }, + StatusReason: "Stack successfully updated", + Name: "gophercloud-test-stack-2", + CreationTime: time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC), + UpdatedTime: time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC), + Status: "UPDATE_COMPLETE", + ID: "db6977b2-27aa-4775-9ae7-6213212d4ada", + Tags: []string{"sfo", "satx"}, + }, +} + +// FullListOutput represents the response body from a List request without a marker. +const FullListOutput = ` +{ + "stacks": [ + { + "description": "Simple template to test heat commands", + "links": [ + { + "href": "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "rel": "self" + } + ], + "stack_status_reason": "Stack CREATE completed successfully", + "stack_name": "postman_stack", + "creation_time": "2015-02-03T20:07:39", + "updated_time": null, + "stack_status": "CREATE_COMPLETE", + "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "tags": ["rackspace", "atx"] + }, + { + "description": "Simple template to test heat commands", + "links": [ + { + "href": "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/gophercloud-test-stack-2/db6977b2-27aa-4775-9ae7-6213212d4ada", + "rel": "self" + } + ], + "stack_status_reason": "Stack successfully updated", + "stack_name": "gophercloud-test-stack-2", + "creation_time": "2014-12-11T17:39:16", + "updated_time": "2014-12-11T17:40:37", + "stack_status": "UPDATE_COMPLETE", + "id": "db6977b2-27aa-4775-9ae7-6213212d4ada", + "tags": ["sfo", "satx"] + } + ] +} +` + +// HandleListSuccessfully creates an HTTP handler at `/stacks` on the test handler mux +// that responds with a `List` response. +func HandleListSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, output) + case "db6977b2-27aa-4775-9ae7-6213212d4ada": + fmt.Fprintf(w, `[]`) + default: + t.Fatalf("Unexpected marker: [%s]", marker) + } + }) +} + +// GetExpected represents the expected object from a Get request. +var GetExpected = &RetrievedStack{ + DisableRollback: true, + Description: "Simple template to test heat commands", + Parameters: map[string]string{ + "flavor": "m1.tiny", + "OS::stack_name": "postman_stack", + "OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + }, + StatusReason: "Stack CREATE completed successfully", + Name: "postman_stack", + Outputs: []map[string]interface{}{}, + CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Rel: "self", + }, + }, + Capabilities: []interface{}{}, + NotificationTopics: []interface{}{}, + Status: "CREATE_COMPLETE", + ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + TemplateDescription: "Simple template to test heat commands", + Tags: []string{"rackspace", "atx"}, +} + +// GetOutput represents the response body from a Get request. +const GetOutput = ` +{ + "stack": { + "disable_rollback": true, + "description": "Simple template to test heat commands", + "parameters": { + "flavor": "m1.tiny", + "OS::stack_name": "postman_stack", + "OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87" + }, + "stack_status_reason": "Stack CREATE completed successfully", + "stack_name": "postman_stack", + "outputs": [], + "creation_time": "2015-02-03T20:07:39", + "links": [ + { + "href": "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "rel": "self" + } + ], + "capabilities": [], + "notification_topics": [], + "timeout_mins": null, + "stack_status": "CREATE_COMPLETE", + "updated_time": null, + "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "template_description": "Simple template to test heat commands", + "tags": ["rackspace", "atx"] + } +} +` + +// HandleGetSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87` +// on the test handler mux that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// HandleUpdateSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87` +// on the test handler mux that responds with an `Update` response. +func HandleUpdateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/stacks/gophercloud-test-stack-2/db6977b2-27aa-4775-9ae7-6213212d4ada", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} + +// HandleDeleteSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87` +// on the test handler mux that responds with a `Delete` response. +func HandleDeleteSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/stacks/gophercloud-test-stack-2/db6977b2-27aa-4775-9ae7-6213212d4ada", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} + +// GetExpected represents the expected object from a Get request. +var PreviewExpected = &PreviewedStack{ + DisableRollback: true, + Description: "Simple template to test heat commands", + Parameters: map[string]string{ + "flavor": "m1.tiny", + "OS::stack_name": "postman_stack", + "OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + }, + Name: "postman_stack", + CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC), + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Rel: "self", + }, + }, + Capabilities: []interface{}{}, + NotificationTopics: []interface{}{}, + ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + TemplateDescription: "Simple template to test heat commands", +} + +// HandlePreviewSuccessfully creates an HTTP handler at `/stacks/preview` +// on the test handler mux that responds with a `Preview` response. +func HandlePreviewSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/preview", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// AbandonExpected represents the expected object from an Abandon request. +var AbandonExpected = &AbandonedStack{ + Status: "COMPLETE", + Name: "postman_stack", + Template: map[string]interface{}{ + "heat_template_version": "2013-05-23", + "description": "Simple template to test heat commands", + "parameters": map[string]interface{}{ + "flavor": map[string]interface{}{ + "default": "m1.tiny", + "type": "string", + }, + }, + "resources": map[string]interface{}{ + "hello_world": map[string]interface{}{ + "type": "OS::Nova::Server", + "properties": map[string]interface{}{ + "key_name": "heat_key", + "flavor": map[string]interface{}{ + "get_param": "flavor", + }, + "image": "ad091b52-742f-469e-8f3c-fd81cadf0743", + "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n", + }, + }, + }, + }, + Action: "CREATE", + ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + Resources: map[string]interface{}{ + "hello_world": map[string]interface{}{ + "status": "COMPLETE", + "name": "hello_world", + "resource_id": "8a310d36-46fc-436f-8be4-37a696b8ac63", + "action": "CREATE", + "type": "OS::Nova::Server", + }, + }, + Files: map[string]string{ + "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml": "heat_template_version: 2014-10-16\nparameters:\n flavor:\n type: string\n description: Flavor for the server to be created\n default: 4353\n hidden: true\nresources:\n test_server:\n type: \"OS::Nova::Server\"\n properties:\n name: test-server\n flavor: 2 GB General Purpose v1\n image: Debian 7 (Wheezy) (PVHVM)\n", + }, + StackUserProjectID: "897686", + ProjectID: "897686", + Environment: map[string]interface{}{ + "encrypted_param_names": make([]map[string]interface{}, 0), + "parameter_defaults": make(map[string]interface{}), + "parameters": make(map[string]interface{}), + "resource_registry": map[string]interface{}{ + "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml": "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml", + "resources": make(map[string]interface{}), + }, + }, +} + +// AbandonOutput represents the response body from an Abandon request. +const AbandonOutput = ` +{ + "status": "COMPLETE", + "name": "postman_stack", + "template": { + "heat_template_version": "2013-05-23", + "description": "Simple template to test heat commands", + "parameters": { + "flavor": { + "default": "m1.tiny", + "type": "string" + } + }, + "resources": { + "hello_world": { + "type": "OS::Nova::Server", + "properties": { + "key_name": "heat_key", + "flavor": { + "get_param": "flavor" + }, + "image": "ad091b52-742f-469e-8f3c-fd81cadf0743", + "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n" + } + } + } + }, + "action": "CREATE", + "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87", + "resources": { + "hello_world": { + "status": "COMPLETE", + "name": "hello_world", + "resource_id": "8a310d36-46fc-436f-8be4-37a696b8ac63", + "action": "CREATE", + "type": "OS::Nova::Server" + } + }, + "files": { + "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml": "heat_template_version: 2014-10-16\nparameters:\n flavor:\n type: string\n description: Flavor for the server to be created\n default: 4353\n hidden: true\nresources:\n test_server:\n type: \"OS::Nova::Server\"\n properties:\n name: test-server\n flavor: 2 GB General Purpose v1\n image: Debian 7 (Wheezy) (PVHVM)\n" +}, + "environment": { + "encrypted_param_names": [], + "parameter_defaults": {}, + "parameters": {}, + "resource_registry": { + "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml": "file:///Users/prat8228/go/src/github.com/rackspace/rack/my_nova.yaml", + "resources": {} + } + }, + "stack_user_project_id": "897686", + "project_id": "897686" +}` + +// HandleAbandonSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87/abandon` +// on the test handler mux that responds with an `Abandon` response. +func HandleAbandonSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c8/abandon", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// ValidJSONTemplate is a valid OpenStack Heat template in JSON format +const ValidJSONTemplate = ` +{ + "heat_template_version": "2014-10-16", + "parameters": { + "flavor": { + "default": 4353, + "description": "Flavor for the server to be created", + "hidden": true, + "type": "string" + } + }, + "resources": { + "test_server": { + "properties": { + "flavor": "2 GB General Purpose v1", + "image": "Debian 7 (Wheezy) (PVHVM)", + "name": "test-server" + }, + "type": "OS::Nova::Server" + } + } +} +` + +// ValidJSONTemplateParsed is the expected parsed version of ValidJSONTemplate +var ValidJSONTemplateParsed = map[string]interface{}{ + "heat_template_version": "2014-10-16", + "parameters": map[string]interface{}{ + "flavor": map[string]interface{}{ + "default": 4353, + "description": "Flavor for the server to be created", + "hidden": true, + "type": "string", + }, + }, + "resources": map[string]interface{}{ + "test_server": map[string]interface{}{ + "properties": map[string]interface{}{ + "flavor": "2 GB General Purpose v1", + "image": "Debian 7 (Wheezy) (PVHVM)", + "name": "test-server", + }, + "type": "OS::Nova::Server", + }, + }, +} + +// ValidYAMLTemplate is a valid OpenStack Heat template in YAML format +const ValidYAMLTemplate = ` +heat_template_version: 2014-10-16 +parameters: + flavor: + type: string + description: Flavor for the server to be created + default: 4353 + hidden: true +resources: + test_server: + type: "OS::Nova::Server" + properties: + name: test-server + flavor: 2 GB General Purpose v1 + image: Debian 7 (Wheezy) (PVHVM) +` + +// InvalidTemplateNoVersion is an invalid template as it has no `version` section +const InvalidTemplateNoVersion = ` +parameters: + flavor: + type: string + description: Flavor for the server to be created + default: 4353 + hidden: true +resources: + test_server: + type: "OS::Nova::Server" + properties: + name: test-server + flavor: 2 GB General Purpose v1 + image: Debian 7 (Wheezy) (PVHVM) +` + +// ValidJSONEnvironment is a valid environment for a stack in JSON format +const ValidJSONEnvironment = ` +{ + "parameters": { + "user_key": "userkey" + }, + "resource_registry": { + "My::WP::Server": "file:///home/shardy/git/heat-templates/hot/F18/WordPress_Native.yaml", + "OS::Quantum*": "OS::Neutron*", + "AWS::CloudWatch::Alarm": "file:///etc/heat/templates/AWS_CloudWatch_Alarm.yaml", + "OS::Metering::Alarm": "OS::Ceilometer::Alarm", + "AWS::RDS::DBInstance": "file:///etc/heat/templates/AWS_RDS_DBInstance.yaml", + "resources": { + "my_db_server": { + "OS::DBInstance": "file:///home/mine/all_my_cool_templates/db.yaml" + }, + "my_server": { + "OS::DBInstance": "file:///home/mine/all_my_cool_templates/db.yaml", + "hooks": "pre-create" + }, + "nested_stack": { + "nested_resource": { + "hooks": "pre-update" + }, + "another_resource": { + "hooks": [ + "pre-create", + "pre-update" + ] + } + } + } + } +} +` + +// ValidJSONEnvironmentParsed is the expected parsed version of ValidJSONEnvironment +var ValidJSONEnvironmentParsed = map[string]interface{}{ + "parameters": map[string]interface{}{ + "user_key": "userkey", + }, + "resource_registry": map[string]interface{}{ + "My::WP::Server": "file:///home/shardy/git/heat-templates/hot/F18/WordPress_Native.yaml", + "OS::Quantum*": "OS::Neutron*", + "AWS::CloudWatch::Alarm": "file:///etc/heat/templates/AWS_CloudWatch_Alarm.yaml", + "OS::Metering::Alarm": "OS::Ceilometer::Alarm", + "AWS::RDS::DBInstance": "file:///etc/heat/templates/AWS_RDS_DBInstance.yaml", + "resources": map[string]interface{}{ + "my_db_server": map[string]interface{}{ + "OS::DBInstance": "file:///home/mine/all_my_cool_templates/db.yaml", + }, + "my_server": map[string]interface{}{ + "OS::DBInstance": "file:///home/mine/all_my_cool_templates/db.yaml", + "hooks": "pre-create", + }, + "nested_stack": map[string]interface{}{ + "nested_resource": map[string]interface{}{ + "hooks": "pre-update", + }, + "another_resource": map[string]interface{}{ + "hooks": []interface{}{ + "pre-create", + "pre-update", + }, + }, + }, + }, + }, +} + +// ValidYAMLEnvironment is a valid environment for a stack in YAML format +const ValidYAMLEnvironment = ` +parameters: + user_key: userkey +resource_registry: + My::WP::Server: file:///home/shardy/git/heat-templates/hot/F18/WordPress_Native.yaml + # allow older templates with Quantum in them. + "OS::Quantum*": "OS::Neutron*" + # Choose your implementation of AWS::CloudWatch::Alarm + "AWS::CloudWatch::Alarm": "file:///etc/heat/templates/AWS_CloudWatch_Alarm.yaml" + #"AWS::CloudWatch::Alarm": "OS::Heat::CWLiteAlarm" + "OS::Metering::Alarm": "OS::Ceilometer::Alarm" + "AWS::RDS::DBInstance": "file:///etc/heat/templates/AWS_RDS_DBInstance.yaml" + resources: + my_db_server: + "OS::DBInstance": file:///home/mine/all_my_cool_templates/db.yaml + my_server: + "OS::DBInstance": file:///home/mine/all_my_cool_templates/db.yaml + hooks: pre-create + nested_stack: + nested_resource: + hooks: pre-update + another_resource: + hooks: [pre-create, pre-update] +` + +// InvalidEnvironment is an invalid environment as it has an extra section called `resources` +const InvalidEnvironment = ` +parameters: + flavor: + type: string + description: Flavor for the server to be created + default: 4353 + hidden: true +resources: + test_server: + type: "OS::Nova::Server" + properties: + name: test-server + flavor: 2 GB General Purpose v1 + image: Debian 7 (Wheezy) (PVHVM) +parameter_defaults: + KeyName: heat_key +` diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/requests.go new file mode 100644 index 000000000..1fc484d67 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/requests.go @@ -0,0 +1,682 @@ +package stacks + +import ( + "errors" + "strings" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Rollback is used to specify whether or not a stack can be rolled back. +type Rollback *bool + +var ( + disable = true + // Disable is used to specify that a stack cannot be rolled back. + Disable Rollback = &disable + enable = false + // Enable is used to specify that a stack can be rolled back. + Enable Rollback = &enable +) + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToStackCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // (REQUIRED) The name of the stack. It must start with an alphabetic character. + Name string + // (REQUIRED) A structure that contains either the template file or url. Call the + // associated methods to extract the information relevant to send in a create request. + TemplateOpts *Template + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, TemplateURL will be ignored + // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate. + // This value is ignored if Template is supplied inline. + TemplateURL string + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, Template will be ignored + // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value + // is a stringified version of the JSON/YAML template. Since the template will likely + // be located in a file, one way to set this variable is by using ioutil.ReadFile: + // import "io/ioutil" + // var opts stacks.CreateOpts + // b, err := ioutil.ReadFile("path/to/you/template/file.json") + // if err != nil { + // // handle error... + // } + // opts.Template = string(b) + Template string + // (OPTIONAL) Enables or disables deletion of all stack resources when a stack + // creation fails. Default is true, meaning all resources are not deleted when + // stack creation fails. + DisableRollback Rollback + // (OPTIONAL) A structure that contains details for the environment of the stack. + EnvironmentOpts *Environment + // (DEPRECATED): Please use EnvironmentOpts to provide Environment data + // (OPTIONAL) A stringified JSON environment for the stack. + Environment string + // (DEPRECATED): Files is automatically determined + // by parsing the template and environment passed as TemplateOpts and + // EnvironmentOpts respectively. + // (OPTIONAL) A map that maps file names to file contents. It can also be used + // to pass provider template contents. Example: + // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}` + Files map[string]interface{} + // (OPTIONAL) User-defined parameters to pass to the template. + Parameters map[string]string + // (OPTIONAL) The timeout for stack creation in minutes. + Timeout int + // (OPTIONAL) A list of tags to assosciate with the Stack + Tags []string +} + +// ToStackCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.Name == "" { + return s, errors.New("Required field 'Name' not provided.") + } + s["stack_name"] = opts.Name + Files := make(map[string]string) + if opts.TemplateOpts == nil { + if opts.Template != "" { + s["template"] = opts.Template + } else if opts.TemplateURL != "" { + s["template_url"] = opts.TemplateURL + } else { + return s, errors.New("Either Template or TemplateURL must be provided.") + } + } else { + if err := opts.TemplateOpts.Parse(); err != nil { + return nil, err + } + + if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { + return nil, err + } + opts.TemplateOpts.fixFileRefs() + s["template"] = string(opts.TemplateOpts.Bin) + + for k, v := range opts.TemplateOpts.Files { + Files[k] = v + } + } + if opts.DisableRollback != nil { + s["disable_rollback"] = &opts.DisableRollback + } + + if opts.EnvironmentOpts != nil { + if err := opts.EnvironmentOpts.Parse(); err != nil { + return nil, err + } + if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { + return nil, err + } + opts.EnvironmentOpts.fixFileRefs() + for k, v := range opts.EnvironmentOpts.Files { + Files[k] = v + } + s["environment"] = string(opts.EnvironmentOpts.Bin) + } else if opts.Environment != "" { + s["environment"] = opts.Environment + } + + if opts.Files != nil { + s["files"] = opts.Files + } else { + s["files"] = Files + } + + if opts.DisableRollback != nil { + s["disable_rollback"] = &opts.DisableRollback + } + + if opts.Parameters != nil { + s["parameters"] = opts.Parameters + } + + if opts.Timeout != 0 { + s["timeout_mins"] = opts.Timeout + } + + if opts.Tags != nil { + s["tags"] = strings.Join(opts.Tags, ",") + } + return s, nil +} + +// Create accepts a CreateOpts struct and creates a new stack using the values +// provided. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToStackCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) + return res +} + +// AdoptOptsBuilder is the interface options structs have to satisfy in order +// to be used in the Adopt function in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type AdoptOptsBuilder interface { + ToStackAdoptMap() (map[string]interface{}, error) +} + +// AdoptOpts is the common options struct used in this package's Adopt +// operation. +type AdoptOpts struct { + // (REQUIRED) Existing resources data represented as a string to add to the + // new stack. Data returned by Abandon could be provided as AdoptsStackData. + AdoptStackData string + // (REQUIRED) The name of the stack. It must start with an alphabetic character. + Name string + // (REQUIRED) The timeout for stack creation in minutes. + Timeout int + // (REQUIRED) A structure that contains either the template file or url. Call the + // associated methods to extract the information relevant to send in a create request. + TemplateOpts *Template + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, TemplateURL will be ignored + // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate. + // This value is ignored if Template is supplied inline. + TemplateURL string + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, Template will be ignored + // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value + // is a stringified version of the JSON/YAML template. Since the template will likely + // be located in a file, one way to set this variable is by using ioutil.ReadFile: + // import "io/ioutil" + // var opts stacks.CreateOpts + // b, err := ioutil.ReadFile("path/to/you/template/file.json") + // if err != nil { + // // handle error... + // } + // opts.Template = string(b) + Template string + // (OPTIONAL) Enables or disables deletion of all stack resources when a stack + // creation fails. Default is true, meaning all resources are not deleted when + // stack creation fails. + DisableRollback Rollback + // (OPTIONAL) A structure that contains details for the environment of the stack. + EnvironmentOpts *Environment + // (DEPRECATED): Please use EnvironmentOpts to provide Environment data + // (OPTIONAL) A stringified JSON environment for the stack. + Environment string + // (DEPRECATED): Files is automatically determined + // by parsing the template and environment passed as TemplateOpts and + // EnvironmentOpts respectively. + // (OPTIONAL) A map that maps file names to file contents. It can also be used + // to pass provider template contents. Example: + // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}` + Files map[string]interface{} + // (OPTIONAL) User-defined parameters to pass to the template. + Parameters map[string]string +} + +// ToStackAdoptMap casts a CreateOpts struct to a map. +func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.Name == "" { + return s, errors.New("Required field 'Name' not provided.") + } + s["stack_name"] = opts.Name + Files := make(map[string]string) + if opts.AdoptStackData != "" { + s["adopt_stack_data"] = opts.AdoptStackData + } else if opts.TemplateOpts == nil { + if opts.Template != "" { + s["template"] = opts.Template + } else if opts.TemplateURL != "" { + s["template_url"] = opts.TemplateURL + } else { + return s, errors.New("One of AdoptStackData, Template, TemplateURL or TemplateOpts must be provided.") + } + } else { + if err := opts.TemplateOpts.Parse(); err != nil { + return nil, err + } + + if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { + return nil, err + } + opts.TemplateOpts.fixFileRefs() + s["template"] = string(opts.TemplateOpts.Bin) + + for k, v := range opts.TemplateOpts.Files { + Files[k] = v + } + } + + if opts.DisableRollback != nil { + s["disable_rollback"] = &opts.DisableRollback + } + + if opts.EnvironmentOpts != nil { + if err := opts.EnvironmentOpts.Parse(); err != nil { + return nil, err + } + if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { + return nil, err + } + opts.EnvironmentOpts.fixFileRefs() + for k, v := range opts.EnvironmentOpts.Files { + Files[k] = v + } + s["environment"] = string(opts.EnvironmentOpts.Bin) + } else if opts.Environment != "" { + s["environment"] = opts.Environment + } + + if opts.Files != nil { + s["files"] = opts.Files + } else { + s["files"] = Files + } + + if opts.Parameters != nil { + s["parameters"] = opts.Parameters + } + + if opts.Timeout != 0 { + s["timeout"] = opts.Timeout + } + s["timeout_mins"] = opts.Timeout + + return s, nil +} + +// Adopt accepts an AdoptOpts struct and creates a new stack using the resources +// from another stack. +func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) AdoptResult { + var res AdoptResult + + reqBody, err := opts.ToStackAdoptMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(adoptURL(c), reqBody, &res.Body, nil) + return res +} + +// SortDir is a type for specifying in which direction to sort a list of stacks. +type SortDir string + +// SortKey is a type for specifying by which key to sort a list of stacks. +type SortKey string + +var ( + // SortAsc is used to sort a list of stacks in ascending order. + SortAsc SortDir = "asc" + // SortDesc is used to sort a list of stacks in descending order. + SortDesc SortDir = "desc" + // SortName is used to sort a list of stacks by name. + SortName SortKey = "name" + // SortStatus is used to sort a list of stacks by status. + SortStatus SortKey = "status" + // SortCreatedAt is used to sort a list of stacks by date created. + SortCreatedAt SortKey = "created_at" + // SortUpdatedAt is used to sort a list of stacks by date updated. + SortUpdatedAt SortKey = "updated_at" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToStackListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the network attributes you want to see returned. SortKey allows you to sort +// by a particular network attribute. SortDir sets the direction, and is either +// `asc' or `desc'. Marker and Limit are used for pagination. +type ListOpts struct { + Status string `q:"status"` + Name string `q:"name"` + Marker string `q:"marker"` + Limit int `q:"limit"` + SortKey SortKey `q:"sort_keys"` + SortDir SortDir `q:"sort_dir"` +} + +// ToStackListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToStackListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List returns a Pager which allows you to iterate over a collection of +// stacks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToStackListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPage := func(r pagination.PageResult) pagination.Page { + return StackPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Get retreives a stack based on the stack name and stack ID. +func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, stackName, stackID), &res.Body, nil) + return res +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the Update operation in this package. +type UpdateOptsBuilder interface { + ToStackUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts contains the common options struct used in this package's Update +// operation. +type UpdateOpts struct { + // (REQUIRED) A structure that contains either the template file or url. Call the + // associated methods to extract the information relevant to send in a create request. + TemplateOpts *Template + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, TemplateURL will be ignored + // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate. + // This value is ignored if Template is supplied inline. + TemplateURL string + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, Template will be ignored + // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value + // is a stringified version of the JSON/YAML template. Since the template will likely + // be located in a file, one way to set this variable is by using ioutil.ReadFile: + // import "io/ioutil" + // var opts stacks.CreateOpts + // b, err := ioutil.ReadFile("path/to/you/template/file.json") + // if err != nil { + // // handle error... + // } + // opts.Template = string(b) + Template string + // (OPTIONAL) A structure that contains details for the environment of the stack. + EnvironmentOpts *Environment + // (DEPRECATED): Please use EnvironmentOpts to provide Environment data + // (OPTIONAL) A stringified JSON environment for the stack. + Environment string + // (DEPRECATED): Files is automatically determined + // by parsing the template and environment passed as TemplateOpts and + // EnvironmentOpts respectively. + // (OPTIONAL) A map that maps file names to file contents. It can also be used + // to pass provider template contents. Example: + // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}` + Files map[string]interface{} + // (OPTIONAL) User-defined parameters to pass to the template. + Parameters map[string]string + // (OPTIONAL) The timeout for stack creation in minutes. + Timeout int + // (OPTIONAL) A list of tags to assosciate with the Stack + Tags []string +} + +// ToStackUpdateMap casts a CreateOpts struct to a map. +func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + Files := make(map[string]string) + if opts.TemplateOpts == nil { + if opts.Template != "" { + s["template"] = opts.Template + } else if opts.TemplateURL != "" { + s["template_url"] = opts.TemplateURL + } else { + return s, errors.New("Either Template or TemplateURL must be provided.") + } + } else { + if err := opts.TemplateOpts.Parse(); err != nil { + return nil, err + } + + if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { + return nil, err + } + opts.TemplateOpts.fixFileRefs() + s["template"] = string(opts.TemplateOpts.Bin) + + for k, v := range opts.TemplateOpts.Files { + Files[k] = v + } + } + + if opts.EnvironmentOpts != nil { + if err := opts.EnvironmentOpts.Parse(); err != nil { + return nil, err + } + if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { + return nil, err + } + opts.EnvironmentOpts.fixFileRefs() + for k, v := range opts.EnvironmentOpts.Files { + Files[k] = v + } + s["environment"] = string(opts.EnvironmentOpts.Bin) + } else if opts.Environment != "" { + s["environment"] = opts.Environment + } + + if opts.Files != nil { + s["files"] = opts.Files + } else { + s["files"] = Files + } + + if opts.Parameters != nil { + s["parameters"] = opts.Parameters + } + + if opts.Timeout != 0 { + s["timeout_mins"] = opts.Timeout + } + + if opts.Tags != nil { + s["tags"] = strings.Join(opts.Tags, ",") + } + + return s, nil +} + +// Update accepts an UpdateOpts struct and updates an existing stack using the values +// provided. +func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToStackUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(updateURL(c, stackName, stackID), reqBody, nil, nil) + return res +} + +// Delete deletes a stack based on the stack name and stack ID. +func Delete(c *gophercloud.ServiceClient, stackName, stackID string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, stackName, stackID), nil) + return res +} + +// PreviewOptsBuilder is the interface options structs have to satisfy in order +// to be used in the Preview operation in this package. +type PreviewOptsBuilder interface { + ToStackPreviewMap() (map[string]interface{}, error) +} + +// PreviewOpts contains the common options struct used in this package's Preview +// operation. +type PreviewOpts struct { + // (REQUIRED) The name of the stack. It must start with an alphabetic character. + Name string + // (REQUIRED) The timeout for stack creation in minutes. + Timeout int + // (REQUIRED) A structure that contains either the template file or url. Call the + // associated methods to extract the information relevant to send in a create request. + TemplateOpts *Template + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, TemplateURL will be ignored + // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate. + // This value is ignored if Template is supplied inline. + TemplateURL string + // (DEPRECATED): Please use TemplateOpts for providing the template. If + // TemplateOpts is provided, Template will be ignored + // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value + // is a stringified version of the JSON/YAML template. Since the template will likely + // be located in a file, one way to set this variable is by using ioutil.ReadFile: + // import "io/ioutil" + // var opts stacks.CreateOpts + // b, err := ioutil.ReadFile("path/to/you/template/file.json") + // if err != nil { + // // handle error... + // } + // opts.Template = string(b) + Template string + // (OPTIONAL) Enables or disables deletion of all stack resources when a stack + // creation fails. Default is true, meaning all resources are not deleted when + // stack creation fails. + DisableRollback Rollback + // (OPTIONAL) A structure that contains details for the environment of the stack. + EnvironmentOpts *Environment + // (DEPRECATED): Please use EnvironmentOpts to provide Environment data + // (OPTIONAL) A stringified JSON environment for the stack. + Environment string + // (DEPRECATED): Files is automatically determined + // by parsing the template and environment passed as TemplateOpts and + // EnvironmentOpts respectively. + // (OPTIONAL) A map that maps file names to file contents. It can also be used + // to pass provider template contents. Example: + // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}` + Files map[string]interface{} + // (OPTIONAL) User-defined parameters to pass to the template. + Parameters map[string]string +} + +// ToStackPreviewMap casts a PreviewOpts struct to a map. +func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.Name == "" { + return s, errors.New("Required field 'Name' not provided.") + } + s["stack_name"] = opts.Name + Files := make(map[string]string) + if opts.TemplateOpts == nil { + if opts.Template != "" { + s["template"] = opts.Template + } else if opts.TemplateURL != "" { + s["template_url"] = opts.TemplateURL + } else { + return s, errors.New("Either Template or TemplateURL must be provided.") + } + } else { + if err := opts.TemplateOpts.Parse(); err != nil { + return nil, err + } + + if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { + return nil, err + } + opts.TemplateOpts.fixFileRefs() + s["template"] = string(opts.TemplateOpts.Bin) + + for k, v := range opts.TemplateOpts.Files { + Files[k] = v + } + } + if opts.DisableRollback != nil { + s["disable_rollback"] = &opts.DisableRollback + } + + if opts.EnvironmentOpts != nil { + if err := opts.EnvironmentOpts.Parse(); err != nil { + return nil, err + } + if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { + return nil, err + } + opts.EnvironmentOpts.fixFileRefs() + for k, v := range opts.EnvironmentOpts.Files { + Files[k] = v + } + s["environment"] = string(opts.EnvironmentOpts.Bin) + } else if opts.Environment != "" { + s["environment"] = opts.Environment + } + + if opts.Files != nil { + s["files"] = opts.Files + } else { + s["files"] = Files + } + + if opts.Parameters != nil { + s["parameters"] = opts.Parameters + } + + if opts.Timeout != 0 { + s["timeout_mins"] = opts.Timeout + } + + return s, nil +} + +// Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values +// provided. +func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) PreviewResult { + var res PreviewResult + + reqBody, err := opts.ToStackPreviewMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Post(previewURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Abandon deletes the stack with the provided stackName and stackID, but leaves its +// resources intact, and returns data describing the stack and its resources. +func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) AbandonResult { + var res AbandonResult + _, res.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/results.go new file mode 100644 index 000000000..432bc8e0c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/results.go @@ -0,0 +1,313 @@ +package stacks + +import ( + "encoding/json" + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreatedStack represents the object extracted from a Create operation. +type CreatedStack struct { + ID string `mapstructure:"id"` + Links []gophercloud.Link `mapstructure:"links"` +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a CreatedStack object and is called after a +// Create operation. +func (r CreateResult) Extract() (*CreatedStack, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Stack *CreatedStack `mapstructure:"stack"` + } + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return res.Stack, nil +} + +// AdoptResult represents the result of an Adopt operation. AdoptResult has the +// same form as CreateResult. +type AdoptResult struct { + CreateResult +} + +// StackPage is a pagination.Pager that is returned from a call to the List function. +type StackPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ListResult contains no Stacks. +func (r StackPage) IsEmpty() (bool, error) { + stacks, err := ExtractStacks(r) + if err != nil { + return true, err + } + return len(stacks) == 0, nil +} + +// ListedStack represents an element in the slice extracted from a List operation. +type ListedStack struct { + CreationTime time.Time `mapstructure:"-"` + Description string `mapstructure:"description"` + ID string `mapstructure:"id"` + Links []gophercloud.Link `mapstructure:"links"` + Name string `mapstructure:"stack_name"` + Status string `mapstructure:"stack_status"` + StatusReason string `mapstructure:"stack_status_reason"` + Tags []string `mapstructure:"tags"` + UpdatedTime time.Time `mapstructure:"-"` +} + +// ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating +// over a stacks.List call. +func ExtractStacks(page pagination.Page) ([]ListedStack, error) { + casted := page.(StackPage).Body + + var res struct { + Stacks []ListedStack `mapstructure:"stacks"` + } + + err := mapstructure.Decode(casted, &res) + if err != nil { + return nil, err + } + + var rawStacks []interface{} + switch casted.(type) { + case map[string]interface{}: + rawStacks = casted.(map[string]interface{})["stacks"].([]interface{}) + case map[string][]interface{}: + rawStacks = casted.(map[string][]interface{})["stacks"] + default: + return res.Stacks, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawStacks { + thisStack := (rawStacks[i]).(map[string]interface{}) + + if t, ok := thisStack["creation_time"].(string); ok && t != "" { + creationTime, err := time.Parse(gophercloud.STACK_TIME_FMT, t) + if err != nil { + return res.Stacks, err + } + res.Stacks[i].CreationTime = creationTime + } + + if t, ok := thisStack["updated_time"].(string); ok && t != "" { + updatedTime, err := time.Parse(gophercloud.STACK_TIME_FMT, t) + if err != nil { + return res.Stacks, err + } + res.Stacks[i].UpdatedTime = updatedTime + } + } + + return res.Stacks, nil +} + +// RetrievedStack represents the object extracted from a Get operation. +type RetrievedStack struct { + Capabilities []interface{} `mapstructure:"capabilities"` + CreationTime time.Time `mapstructure:"-"` + Description string `mapstructure:"description"` + DisableRollback bool `mapstructure:"disable_rollback"` + ID string `mapstructure:"id"` + Links []gophercloud.Link `mapstructure:"links"` + NotificationTopics []interface{} `mapstructure:"notification_topics"` + Outputs []map[string]interface{} `mapstructure:"outputs"` + Parameters map[string]string `mapstructure:"parameters"` + Name string `mapstructure:"stack_name"` + Status string `mapstructure:"stack_status"` + StatusReason string `mapstructure:"stack_status_reason"` + Tags []string `mapstructure:"tags"` + TemplateDescription string `mapstructure:"template_description"` + Timeout int `mapstructure:"timeout_mins"` + UpdatedTime time.Time `mapstructure:"-"` +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a RetrievedStack object and is called after a +// Get operation. +func (r GetResult) Extract() (*RetrievedStack, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Stack *RetrievedStack `mapstructure:"stack"` + } + + config := &mapstructure.DecoderConfig{ + Result: &res, + WeaklyTypedInput: true, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + + if err := decoder.Decode(r.Body); err != nil { + return nil, err + } + + b := r.Body.(map[string]interface{})["stack"].(map[string]interface{}) + + if date, ok := b["creation_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Stack.CreationTime = t + } + + if date, ok := b["updated_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Stack.UpdatedTime = t + } + + return res.Stack, err +} + +// UpdateResult represents the result of a Update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// PreviewedStack represents the result of a Preview operation. +type PreviewedStack struct { + Capabilities []interface{} `mapstructure:"capabilities"` + CreationTime time.Time `mapstructure:"-"` + Description string `mapstructure:"description"` + DisableRollback bool `mapstructure:"disable_rollback"` + ID string `mapstructure:"id"` + Links []gophercloud.Link `mapstructure:"links"` + Name string `mapstructure:"stack_name"` + NotificationTopics []interface{} `mapstructure:"notification_topics"` + Parameters map[string]string `mapstructure:"parameters"` + Resources []interface{} `mapstructure:"resources"` + TemplateDescription string `mapstructure:"template_description"` + Timeout int `mapstructure:"timeout_mins"` + UpdatedTime time.Time `mapstructure:"-"` +} + +// PreviewResult represents the result of a Preview operation. +type PreviewResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a PreviewedStack object and is called after a +// Preview operation. +func (r PreviewResult) Extract() (*PreviewedStack, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Stack *PreviewedStack `mapstructure:"stack"` + } + + config := &mapstructure.DecoderConfig{ + Result: &res, + WeaklyTypedInput: true, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + + if err := decoder.Decode(r.Body); err != nil { + return nil, err + } + + b := r.Body.(map[string]interface{})["stack"].(map[string]interface{}) + + if date, ok := b["creation_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Stack.CreationTime = t + } + + if date, ok := b["updated_time"]; ok && date != nil { + t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string)) + if err != nil { + return nil, err + } + res.Stack.UpdatedTime = t + } + + return res.Stack, err +} + +// AbandonedStack represents the result of an Abandon operation. +type AbandonedStack struct { + Status string `mapstructure:"status"` + Name string `mapstructure:"name"` + Template map[string]interface{} `mapstructure:"template"` + Action string `mapstructure:"action"` + ID string `mapstructure:"id"` + Resources map[string]interface{} `mapstructure:"resources"` + Files map[string]string `mapstructure:"files"` + StackUserProjectID string `mapstructure:"stack_user_project_id"` + ProjectID string `mapstructure:"project_id"` + Environment map[string]interface{} `mapstructure:"environment"` +} + +// AbandonResult represents the result of an Abandon operation. +type AbandonResult struct { + gophercloud.Result +} + +// Extract returns a pointer to an AbandonedStack object and is called after an +// Abandon operation. +func (r AbandonResult) Extract() (*AbandonedStack, error) { + if r.Err != nil { + return nil, r.Err + } + + var res AbandonedStack + + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return &res, nil +} + +// String converts an AbandonResult to a string. This is useful to when passing +// the result of an Abandon operation to an AdoptOpts AdoptStackData field. +func (r AbandonResult) String() (string, error) { + out, err := json.Marshal(r) + if err != nil { + return "", err + } + return string(out), nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/template.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/template.go new file mode 100644 index 000000000..234ce498e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/template.go @@ -0,0 +1,139 @@ +package stacks + +import ( + "fmt" + "github.com/rackspace/gophercloud" + "reflect" + "strings" +) + +// Template is a structure that represents OpenStack Heat templates +type Template struct { + TE +} + +// TemplateFormatVersions is a map containing allowed variations of the template format version +// Note that this contains the permitted variations of the _keys_ not the values. +var TemplateFormatVersions = map[string]bool{ + "HeatTemplateFormatVersion": true, + "heat_template_version": true, + "AWSTemplateFormatVersion": true, +} + +// Validate validates the contents of the Template +func (t *Template) Validate() error { + if t.Parsed == nil { + if err := t.Parse(); err != nil { + return err + } + } + for key := range t.Parsed { + if _, ok := TemplateFormatVersions[key]; ok { + return nil + } + } + return fmt.Errorf("Template format version not found.") +} + +// GetFileContents recursively parses a template to search for urls. These urls +// are assumed to point to other templates (known in OpenStack Heat as child +// templates). The contents of these urls are fetched and stored in the `Files` +// parameter of the template structure. This is the only way that a user can +// use child templates that are located in their filesystem; urls located on the +// web (e.g. on github or swift) can be fetched directly by Heat engine. +func (t *Template) getFileContents(te interface{}, ignoreIf igFunc, recurse bool) error { + // initialize template if empty + if t.Files == nil { + t.Files = make(map[string]string) + } + if t.fileMaps == nil { + t.fileMaps = make(map[string]string) + } + switch te.(type) { + // if te is a map + case map[string]interface{}, map[interface{}]interface{}: + teMap, err := toStringKeys(te) + if err != nil { + return err + } + for k, v := range teMap { + value, ok := v.(string) + if !ok { + // if the value is not a string, recursively parse that value + if err := t.getFileContents(v, ignoreIf, recurse); err != nil { + return err + } + } else if !ignoreIf(k, value) { + // at this point, the k, v pair has a reference to an external template. + // The assumption of heatclient is that value v is a reference + // to a file in the users environment + + // create a new child template + childTemplate := new(Template) + + // initialize child template + + // get the base location of the child template + baseURL, err := gophercloud.NormalizePathURL(t.baseURL, value) + if err != nil { + return err + } + childTemplate.baseURL = baseURL + childTemplate.client = t.client + + // fetch the contents of the child template + if err := childTemplate.Parse(); err != nil { + return err + } + + // process child template recursively if required. This is + // required if the child template itself contains references to + // other templates + if recurse { + if err := childTemplate.getFileContents(childTemplate.Parsed, ignoreIf, recurse); err != nil { + return err + } + } + // update parent template with current child templates' content. + // At this point, the child template has been parsed recursively. + t.fileMaps[value] = childTemplate.URL + t.Files[childTemplate.URL] = string(childTemplate.Bin) + + } + } + return nil + // if te is a slice, call the function on each element of the slice. + case []interface{}: + teSlice := te.([]interface{}) + for i := range teSlice { + if err := t.getFileContents(teSlice[i], ignoreIf, recurse); err != nil { + return err + } + } + // if te is anything else, return + case string, bool, float64, nil, int: + return nil + default: + return fmt.Errorf("%v: Unrecognized type", reflect.TypeOf(te)) + + } + return nil +} + +// function to choose keys whose values are other template files +func ignoreIfTemplate(key string, value interface{}) bool { + // key must be either `get_file` or `type` for value to be a URL + if key != "get_file" && key != "type" { + return true + } + // value must be a string + valueString, ok := value.(string) + if !ok { + return true + } + // `.template` and `.yaml` are allowed suffixes for template URLs when referred to by `type` + if key == "type" && !(strings.HasSuffix(valueString, ".template") || strings.HasSuffix(valueString, ".yaml")) { + return true + } + return false +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/urls.go new file mode 100644 index 000000000..3dd2bb32e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/urls.go @@ -0,0 +1,35 @@ +package stacks + +import "github.com/rackspace/gophercloud" + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("stacks") +} + +func adoptURL(c *gophercloud.ServiceClient) string { + return createURL(c) +} + +func listURL(c *gophercloud.ServiceClient) string { + return createURL(c) +} + +func getURL(c *gophercloud.ServiceClient, name, id string) string { + return c.ServiceURL("stacks", name, id) +} + +func updateURL(c *gophercloud.ServiceClient, name, id string) string { + return getURL(c, name, id) +} + +func deleteURL(c *gophercloud.ServiceClient, name, id string) string { + return getURL(c, name, id) +} + +func previewURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("stacks", "preview") +} + +func abandonURL(c *gophercloud.ServiceClient, name, id string) string { + return c.ServiceURL("stacks", name, id, "abandon") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/utils.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/utils.go new file mode 100644 index 000000000..7b476a9c3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks/utils.go @@ -0,0 +1,161 @@ +package stacks + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "path/filepath" + "reflect" + "strings" + + "github.com/rackspace/gophercloud" + "gopkg.in/yaml.v2" +) + +// Client is an interface that expects a Get method similar to http.Get. This +// is needed for unit testing, since we can mock an http client. Thus, the +// client will usually be an http.Client EXCEPT in unit tests. +type Client interface { + Get(string) (*http.Response, error) +} + +// TE is a base structure for both Template and Environment +type TE struct { + // Bin stores the contents of the template or environment. + Bin []byte + // URL stores the URL of the template. This is allowed to be a 'file://' + // for local files. + URL string + // Parsed contains a parsed version of Bin. Since there are 2 different + // fields referring to the same value, you must be careful when accessing + // this filed. + Parsed map[string]interface{} + // Files contains a mapping between the urls in templates to their contents. + Files map[string]string + // fileMaps is a map used internally when determining Files. + fileMaps map[string]string + // baseURL represents the location of the template or environment file. + baseURL string + // client is an interface which allows TE to fetch contents from URLS + client Client +} + +// Fetch fetches the contents of a TE from its URL. Once a TE structure has a +// URL, call the fetch method to fetch the contents. +func (t *TE) Fetch() error { + // if the baseURL is not provided, use the current directors as the base URL + if t.baseURL == "" { + u, err := getBasePath() + if err != nil { + return err + } + t.baseURL = u + } + + // if the contents are already present, do nothing. + if t.Bin != nil { + return nil + } + + // get a fqdn from the URL using the baseURL of the TE. For local files, + // the URL's will have the `file` scheme. + u, err := gophercloud.NormalizePathURL(t.baseURL, t.URL) + if err != nil { + return err + } + t.URL = u + + // get an HTTP client if none present + if t.client == nil { + t.client = getHTTPClient() + } + + // use the client to fetch the contents of the TE + resp, err := t.client.Get(t.URL) + if err != nil { + return err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + t.Bin = body + return nil +} + +// get the basepath of the TE +func getBasePath() (string, error) { + basePath, err := filepath.Abs(".") + if err != nil { + return "", err + } + u, err := gophercloud.NormalizePathURL("", basePath) + if err != nil { + return "", err + } + return u, nil +} + +// get a an HTTP client to retrieve URL's. This client allows the use of `file` +// scheme since we may need to fetch files from users filesystem +func getHTTPClient() Client { + transport := &http.Transport{} + transport.RegisterProtocol("file", http.NewFileTransport(http.Dir("/"))) + return &http.Client{Transport: transport} +} + +// Parse will parse the contents and then validate. The contents MUST be either JSON or YAML. +func (t *TE) Parse() error { + if err := t.Fetch(); err != nil { + return err + } + if jerr := json.Unmarshal(t.Bin, &t.Parsed); jerr != nil { + if yerr := yaml.Unmarshal(t.Bin, &t.Parsed); yerr != nil { + return fmt.Errorf("Data in neither json nor yaml format.") + } + } + return t.Validate() +} + +// Validate validates the contents of TE +func (t *TE) Validate() error { + return nil +} + +// igfunc is a parameter used by GetFileContents and GetRRFileContents to check +// for valid URL's. +type igFunc func(string, interface{}) bool + +// convert map[interface{}]interface{} to map[string]interface{} +func toStringKeys(m interface{}) (map[string]interface{}, error) { + switch m.(type) { + case map[string]interface{}, map[interface{}]interface{}: + typedMap := make(map[string]interface{}) + if _, ok := m.(map[interface{}]interface{}); ok { + for k, v := range m.(map[interface{}]interface{}) { + typedMap[k.(string)] = v + } + } else { + typedMap = m.(map[string]interface{}) + } + return typedMap, nil + default: + return nil, fmt.Errorf("Expected a map of type map[string]interface{} or map[interface{}]interface{}, actual type: %v", reflect.TypeOf(m)) + + } +} + +// fix the reference to files by replacing relative URL's by absolute +// URL's +func (t *TE) fixFileRefs() { + tStr := string(t.Bin) + if t.fileMaps == nil { + return + } + for k, v := range t.fileMaps { + tStr = strings.Replace(tStr, k, v, -1) + } + t.Bin = []byte(tStr) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/doc.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/doc.go new file mode 100644 index 000000000..5af0bd62a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/doc.go @@ -0,0 +1,8 @@ +// Package stacktemplates provides operations for working with Heat templates. +// A Cloud Orchestration template is a portable file, written in a user-readable +// language, that describes how a set of resources should be assembled and what +// software should be installed in order to produce a working stack. The template +// specifies what resources should be used, what attributes can be set, and other +// parameters that are critical to the successful, repeatable automation of a +// specific application stack. +package stacktemplates diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/fixtures.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/fixtures.go new file mode 100644 index 000000000..fa9b3016f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/fixtures.go @@ -0,0 +1,95 @@ +package stacktemplates + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +// GetExpected represents the expected object from a Get request. +var GetExpected = "{\n \"description\": \"Simple template to test heat commands\",\n \"heat_template_version\": \"2013-05-23\",\n \"parameters\": {\n \"flavor\": {\n \"default\": \"m1.tiny\",\n \"type\": \"string\"\n }\n },\n \"resources\": {\n \"hello_world\": {\n \"properties\": {\n \"flavor\": {\n \"get_param\": \"flavor\"\n },\n \"image\": \"ad091b52-742f-469e-8f3c-fd81cadf0743\",\n \"key_name\": \"heat_key\"\n },\n \"type\": \"OS::Nova::Server\"\n }\n }\n}" + +// GetOutput represents the response body from a Get request. +const GetOutput = ` +{ + "heat_template_version": "2013-05-23", + "description": "Simple template to test heat commands", + "parameters": { + "flavor": { + "default": "m1.tiny", + "type": "string" + } + }, + "resources": { + "hello_world": { + "type": "OS::Nova::Server", + "properties": { + "key_name": "heat_key", + "flavor": { + "get_param": "flavor" + }, + "image": "ad091b52-742f-469e-8f3c-fd81cadf0743" + } + } + } +}` + +// HandleGetSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87/template` +// on the test handler mux that responds with a `Get` response. +func HandleGetSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87/template", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} + +// ValidateExpected represents the expected object from a Validate request. +var ValidateExpected = &ValidatedTemplate{ + Description: "Simple template to test heat commands", + Parameters: map[string]interface{}{ + "flavor": map[string]interface{}{ + "Default": "m1.tiny", + "Type": "String", + "NoEcho": "false", + "Description": "", + "Label": "flavor", + }, + }, +} + +// ValidateOutput represents the response body from a Validate request. +const ValidateOutput = ` +{ + "Description": "Simple template to test heat commands", + "Parameters": { + "flavor": { + "Default": "m1.tiny", + "Type": "String", + "NoEcho": "false", + "Description": "", + "Label": "flavor" + } + } +}` + +// HandleValidateSuccessfully creates an HTTP handler at `/validate` +// on the test handler mux that responds with a `Validate` response. +func HandleValidateSuccessfully(t *testing.T, output string) { + th.Mux.HandleFunc("/validate", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, output) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/requests.go new file mode 100644 index 000000000..c0cea3575 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/requests.go @@ -0,0 +1,58 @@ +package stacktemplates + +import ( + "fmt" + + "github.com/rackspace/gophercloud" +) + +// Get retreives data for the given stack template. +func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult { + var res GetResult + _, res.Err = c.Request("GET", getURL(c, stackName, stackID), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + }) + return res +} + +// ValidateOptsBuilder describes struct types that can be accepted by the Validate call. +// The ValidateOpts struct in this package does. +type ValidateOptsBuilder interface { + ToStackTemplateValidateMap() (map[string]interface{}, error) +} + +// ValidateOpts specifies the template validation parameters. +type ValidateOpts struct { + Template string + TemplateURL string +} + +// ToStackTemplateValidateMap assembles a request body based on the contents of a ValidateOpts. +func (opts ValidateOpts) ToStackTemplateValidateMap() (map[string]interface{}, error) { + vo := make(map[string]interface{}) + if opts.Template != "" { + vo["template"] = opts.Template + return vo, nil + } + if opts.TemplateURL != "" { + vo["template_url"] = opts.TemplateURL + return vo, nil + } + return vo, fmt.Errorf("One of Template or TemplateURL is required.") +} + +// Validate validates the given stack template. +func Validate(c *gophercloud.ServiceClient, opts ValidateOptsBuilder) ValidateResult { + var res ValidateResult + + reqBody, err := opts.ToStackTemplateValidateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(validateURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/results.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/results.go new file mode 100644 index 000000000..4e9ba5a4c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/results.go @@ -0,0 +1,51 @@ +package stacktemplates + +import ( + "encoding/json" + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" +) + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract returns the JSON template and is called after a Get operation. +func (r GetResult) Extract() ([]byte, error) { + if r.Err != nil { + return nil, r.Err + } + template, err := json.MarshalIndent(r.Body, "", " ") + if err != nil { + return nil, err + } + return template, nil +} + +// ValidatedTemplate represents the parsed object returned from a Validate request. +type ValidatedTemplate struct { + Description string `mapstructure:"Description"` + Parameters map[string]interface{} `mapstructure:"Parameters"` + ParameterGroups map[string]interface{} `mapstructure:"ParameterGroups"` +} + +// ValidateResult represents the result of a Validate operation. +type ValidateResult struct { + gophercloud.Result +} + +// Extract returns a pointer to a ValidatedTemplate object and is called after a +// Validate operation. +func (r ValidateResult) Extract() (*ValidatedTemplate, error) { + if r.Err != nil { + return nil, r.Err + } + + var res ValidatedTemplate + if err := mapstructure.Decode(r.Body, &res); err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/urls.go b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/urls.go new file mode 100644 index 000000000..c30b7ca1a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates/urls.go @@ -0,0 +1,11 @@ +package stacktemplates + +import "github.com/rackspace/gophercloud" + +func getURL(c *gophercloud.ServiceClient, stackName, stackID string) string { + return c.ServiceURL("stacks", stackName, stackID, "template") +} + +func validateURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("validate") +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/utils/choose_version.go b/vendor/github.com/rackspace/gophercloud/openstack/utils/choose_version.go new file mode 100644 index 000000000..b697ba816 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/utils/choose_version.go @@ -0,0 +1,114 @@ +package utils + +import ( + "fmt" + "strings" + + "github.com/rackspace/gophercloud" +) + +// Version is a supported API version, corresponding to a vN package within the appropriate service. +type Version struct { + ID string + Suffix string + Priority int +} + +var goodStatus = map[string]bool{ + "current": true, + "supported": true, + "stable": true, +} + +// ChooseVersion queries the base endpoint of an API to choose the most recent non-experimental alternative from a service's +// published versions. +// It returns the highest-Priority Version among the alternatives that are provided, as well as its corresponding endpoint. +func ChooseVersion(client *gophercloud.ProviderClient, recognized []*Version) (*Version, string, error) { + type linkResp struct { + Href string `json:"href"` + Rel string `json:"rel"` + } + + type valueResp struct { + ID string `json:"id"` + Status string `json:"status"` + Links []linkResp `json:"links"` + } + + type versionsResp struct { + Values []valueResp `json:"values"` + } + + type response struct { + Versions versionsResp `json:"versions"` + } + + normalize := func(endpoint string) string { + if !strings.HasSuffix(endpoint, "/") { + return endpoint + "/" + } + return endpoint + } + identityEndpoint := normalize(client.IdentityEndpoint) + + // If a full endpoint is specified, check version suffixes for a match first. + for _, v := range recognized { + if strings.HasSuffix(identityEndpoint, v.Suffix) { + return v, identityEndpoint, nil + } + } + + var resp response + _, err := client.Request("GET", client.IdentityBase, gophercloud.RequestOpts{ + JSONResponse: &resp, + OkCodes: []int{200, 300}, + }) + + if err != nil { + return nil, "", err + } + + byID := make(map[string]*Version) + for _, version := range recognized { + byID[version.ID] = version + } + + var highest *Version + var endpoint string + + for _, value := range resp.Versions.Values { + href := "" + for _, link := range value.Links { + if link.Rel == "self" { + href = normalize(link.Href) + } + } + + if matching, ok := byID[value.ID]; ok { + // Prefer a version that exactly matches the provided endpoint. + if href == identityEndpoint { + if href == "" { + return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase) + } + return matching, href, nil + } + + // Otherwise, find the highest-priority version with a whitelisted status. + if goodStatus[strings.ToLower(value.Status)] { + if highest == nil || matching.Priority > highest.Priority { + highest = matching + endpoint = href + } + } + } + } + + if highest == nil { + return nil, "", fmt.Errorf("No supported version available from endpoint %s", client.IdentityBase) + } + if endpoint == "" { + return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", highest.ID, client.IdentityBase) + } + + return highest, endpoint, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/http.go b/vendor/github.com/rackspace/gophercloud/pagination/http.go new file mode 100644 index 000000000..1b3fe94ab --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/http.go @@ -0,0 +1,60 @@ +package pagination + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/url" + "strings" + + "github.com/rackspace/gophercloud" +) + +// PageResult stores the HTTP response that returned the current page of results. +type PageResult struct { + gophercloud.Result + url.URL +} + +// PageResultFrom parses an HTTP response as JSON and returns a PageResult containing the +// results, interpreting it as JSON if the content type indicates. +func PageResultFrom(resp *http.Response) (PageResult, error) { + var parsedBody interface{} + + defer resp.Body.Close() + rawBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + return PageResult{}, err + } + + if strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { + err = json.Unmarshal(rawBody, &parsedBody) + if err != nil { + return PageResult{}, err + } + } else { + parsedBody = rawBody + } + + return PageResultFromParsed(resp, parsedBody), err +} + +// PageResultFromParsed constructs a PageResult from an HTTP response that has already had its +// body parsed as JSON (and closed). +func PageResultFromParsed(resp *http.Response, body interface{}) PageResult { + return PageResult{ + Result: gophercloud.Result{ + Body: body, + Header: resp.Header, + }, + URL: *resp.Request.URL, + } +} + +// Request performs an HTTP request and extracts the http.Response from the result. +func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return client.Request("GET", url, gophercloud.RequestOpts{ + MoreHeaders: headers, + OkCodes: []int{200, 204}, + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/linked.go b/vendor/github.com/rackspace/gophercloud/pagination/linked.go new file mode 100644 index 000000000..e9bd8dec9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/linked.go @@ -0,0 +1,67 @@ +package pagination + +import "fmt" + +// LinkedPageBase may be embedded to implement a page that provides navigational "Next" and "Previous" links within its result. +type LinkedPageBase struct { + PageResult + + // LinkPath lists the keys that should be traversed within a response to arrive at the "next" pointer. + // If any link along the path is missing, an empty URL will be returned. + // If any link results in an unexpected value type, an error will be returned. + // When left as "nil", []string{"links", "next"} will be used as a default. + LinkPath []string +} + +// NextPageURL extracts the pagination structure from a JSON response and returns the "next" link, if one is present. +// It assumes that the links are available in a "links" element of the top-level response object. +// If this is not the case, override NextPageURL on your result type. +func (current LinkedPageBase) NextPageURL() (string, error) { + var path []string + var key string + + if current.LinkPath == nil { + path = []string{"links", "next"} + } else { + path = current.LinkPath + } + + submap, ok := current.Body.(map[string]interface{}) + if !ok { + return "", fmt.Errorf("Expected an object, but was %#v", current.Body) + } + + for { + key, path = path[0], path[1:len(path)] + + value, ok := submap[key] + if !ok { + return "", nil + } + + if len(path) > 0 { + submap, ok = value.(map[string]interface{}) + if !ok { + return "", fmt.Errorf("Expected an object, but was %#v", value) + } + } else { + if value == nil { + // Actual null element. + return "", nil + } + + url, ok := value.(string) + if !ok { + return "", fmt.Errorf("Expected a string, but was %#v", value) + } + + return url, nil + } + } +} + +// GetBody returns the linked page's body. This method is needed to satisfy the +// Page interface. +func (current LinkedPageBase) GetBody() interface{} { + return current.Body +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/marker.go b/vendor/github.com/rackspace/gophercloud/pagination/marker.go new file mode 100644 index 000000000..f355afc54 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/marker.go @@ -0,0 +1,40 @@ +package pagination + +// MarkerPage is a stricter Page interface that describes additional functionality required for use with NewMarkerPager. +// For convenience, embed the MarkedPageBase struct. +type MarkerPage interface { + Page + + // LastMarker returns the last "marker" value on this page. + LastMarker() (string, error) +} + +// MarkerPageBase is a page in a collection that's paginated by "limit" and "marker" query parameters. +type MarkerPageBase struct { + PageResult + + // Owner is a reference to the embedding struct. + Owner MarkerPage +} + +// NextPageURL generates the URL for the page of results after this one. +func (current MarkerPageBase) NextPageURL() (string, error) { + currentURL := current.URL + + mark, err := current.Owner.LastMarker() + if err != nil { + return "", err + } + + q := currentURL.Query() + q.Set("marker", mark) + currentURL.RawQuery = q.Encode() + + return currentURL.String(), nil +} + +// GetBody returns the linked page's body. This method is needed to satisfy the +// Page interface. +func (current MarkerPageBase) GetBody() interface{} { + return current.Body +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/null.go b/vendor/github.com/rackspace/gophercloud/pagination/null.go new file mode 100644 index 000000000..ae57e1886 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/null.go @@ -0,0 +1,20 @@ +package pagination + +// nullPage is an always-empty page that trivially satisfies all Page interfacts. +// It's useful to be returned along with an error. +type nullPage struct{} + +// NextPageURL always returns "" to indicate that there are no more pages to return. +func (p nullPage) NextPageURL() (string, error) { + return "", nil +} + +// IsEmpty always returns true to prevent iteration over nullPages. +func (p nullPage) IsEmpty() (bool, error) { + return true, nil +} + +// LastMark always returns "" because the nullPage contains no items to have a mark. +func (p nullPage) LastMark() (string, error) { + return "", nil +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/pager.go b/vendor/github.com/rackspace/gophercloud/pagination/pager.go new file mode 100644 index 000000000..a7593ac88 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/pager.go @@ -0,0 +1,226 @@ +package pagination + +import ( + "errors" + "fmt" + "net/http" + "reflect" + "strings" + + "github.com/rackspace/gophercloud" +) + +var ( + // ErrPageNotAvailable is returned from a Pager when a next or previous page is requested, but does not exist. + ErrPageNotAvailable = errors.New("The requested page does not exist.") +) + +// Page must be satisfied by the result type of any resource collection. +// It allows clients to interact with the resource uniformly, regardless of whether or not or how it's paginated. +// Generally, rather than implementing this interface directly, implementors should embed one of the concrete PageBase structs, +// instead. +// Depending on the pagination strategy of a particular resource, there may be an additional subinterface that the result type +// will need to implement. +type Page interface { + + // NextPageURL generates the URL for the page of data that follows this collection. + // Return "" if no such page exists. + NextPageURL() (string, error) + + // IsEmpty returns true if this Page has no items in it. + IsEmpty() (bool, error) + + // GetBody returns the Page Body. This is used in the `AllPages` method. + GetBody() interface{} +} + +// Pager knows how to advance through a specific resource collection, one page at a time. +type Pager struct { + client *gophercloud.ServiceClient + + initialURL string + + createPage func(r PageResult) Page + + Err error + + // Headers supplies additional HTTP headers to populate on each paged request. + Headers map[string]string +} + +// NewPager constructs a manually-configured pager. +// Supply the URL for the first page, a function that requests a specific page given a URL, and a function that counts a page. +func NewPager(client *gophercloud.ServiceClient, initialURL string, createPage func(r PageResult) Page) Pager { + return Pager{ + client: client, + initialURL: initialURL, + createPage: createPage, + } +} + +// WithPageCreator returns a new Pager that substitutes a different page creation function. This is +// useful for overriding List functions in delegation. +func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager { + return Pager{ + client: p.client, + initialURL: p.initialURL, + createPage: createPage, + } +} + +func (p Pager) fetchNextPage(url string) (Page, error) { + resp, err := Request(p.client, p.Headers, url) + if err != nil { + return nil, err + } + + remembered, err := PageResultFrom(resp) + if err != nil { + return nil, err + } + + return p.createPage(remembered), nil +} + +// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function. +// Return "false" from the handler to prematurely stop iterating. +func (p Pager) EachPage(handler func(Page) (bool, error)) error { + if p.Err != nil { + return p.Err + } + currentURL := p.initialURL + for { + currentPage, err := p.fetchNextPage(currentURL) + if err != nil { + return err + } + + empty, err := currentPage.IsEmpty() + if err != nil { + return err + } + if empty { + return nil + } + + ok, err := handler(currentPage) + if err != nil { + return err + } + if !ok { + return nil + } + + currentURL, err = currentPage.NextPageURL() + if err != nil { + return err + } + if currentURL == "" { + return nil + } + } +} + +// AllPages returns all the pages from a `List` operation in a single page, +// allowing the user to retrieve all the pages at once. +func (p Pager) AllPages() (Page, error) { + // pagesSlice holds all the pages until they get converted into as Page Body. + var pagesSlice []interface{} + // body will contain the final concatenated Page body. + var body reflect.Value + + // Grab a test page to ascertain the page body type. + testPage, err := p.fetchNextPage(p.initialURL) + if err != nil { + return nil, err + } + // Store the page type so we can use reflection to create a new mega-page of + // that type. + pageType := reflect.TypeOf(testPage) + + // Switch on the page body type. Recognized types are `map[string]interface{}`, + // `[]byte`, and `[]interface{}`. + switch testPage.GetBody().(type) { + case map[string]interface{}: + // key is the map key for the page body if the body type is `map[string]interface{}`. + var key string + // Iterate over the pages to concatenate the bodies. + err := p.EachPage(func(page Page) (bool, error) { + b := page.GetBody().(map[string]interface{}) + for k := range b { + // If it's a linked page, we don't want the `links`, we want the other one. + if !strings.HasSuffix(k, "links") { + key = k + } + } + pagesSlice = append(pagesSlice, b[key].([]interface{})...) + return true, nil + }) + if err != nil { + return nil, err + } + // Set body to value of type `map[string]interface{}` + body = reflect.MakeMap(reflect.MapOf(reflect.TypeOf(key), reflect.TypeOf(pagesSlice))) + body.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(pagesSlice)) + case []byte: + // Iterate over the pages to concatenate the bodies. + err := p.EachPage(func(page Page) (bool, error) { + b := page.GetBody().([]byte) + pagesSlice = append(pagesSlice, b) + // seperate pages with a comma + pagesSlice = append(pagesSlice, []byte{10}) + return true, nil + }) + if err != nil { + return nil, err + } + if len(pagesSlice) > 0 { + // Remove the trailing comma. + pagesSlice = pagesSlice[:len(pagesSlice)-1] + } + var b []byte + // Combine the slice of slices in to a single slice. + for _, slice := range pagesSlice { + b = append(b, slice.([]byte)...) + } + // Set body to value of type `bytes`. + body = reflect.New(reflect.TypeOf(b)).Elem() + body.SetBytes(b) + case []interface{}: + // Iterate over the pages to concatenate the bodies. + err := p.EachPage(func(page Page) (bool, error) { + b := page.GetBody().([]interface{}) + pagesSlice = append(pagesSlice, b...) + return true, nil + }) + if err != nil { + return nil, err + } + // Set body to value of type `[]interface{}` + body = reflect.MakeSlice(reflect.TypeOf(pagesSlice), len(pagesSlice), len(pagesSlice)) + for i, s := range pagesSlice { + body.Index(i).Set(reflect.ValueOf(s)) + } + default: + return nil, fmt.Errorf("Page body has unrecognized type.") + } + + // Each `Extract*` function is expecting a specific type of page coming back, + // otherwise the type assertion in those functions will fail. pageType is needed + // to create a type in this method that has the same type that the `Extract*` + // function is expecting and set the Body of that object to the concatenated + // pages. + page := reflect.New(pageType) + // Set the page body to be the concatenated pages. + page.Elem().FieldByName("Body").Set(body) + // Set any additional headers that were pass along. The `objectstorage` pacakge, + // for example, passes a Content-Type header. + h := make(http.Header) + for k, v := range p.Headers { + h.Add(k, v) + } + page.Elem().FieldByName("Header").Set(reflect.ValueOf(h)) + // Type assert the page to a Page interface so that the type assertion in the + // `Extract*` methods will work. + return page.Elem().Interface().(Page), err +} diff --git a/vendor/github.com/rackspace/gophercloud/pagination/pkg.go b/vendor/github.com/rackspace/gophercloud/pagination/pkg.go new file mode 100644 index 000000000..912daea36 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/pkg.go @@ -0,0 +1,4 @@ +/* +Package pagination contains utilities and convenience structs that implement common pagination idioms within OpenStack APIs. +*/ +package pagination diff --git a/vendor/github.com/rackspace/gophercloud/pagination/single.go b/vendor/github.com/rackspace/gophercloud/pagination/single.go new file mode 100644 index 000000000..f78d4ab5d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/pagination/single.go @@ -0,0 +1,15 @@ +package pagination + +// SinglePageBase may be embedded in a Page that contains all of the results from an operation at once. +type SinglePageBase PageResult + +// NextPageURL always returns "" to indicate that there are no more pages to return. +func (current SinglePageBase) NextPageURL() (string, error) { + return "", nil +} + +// GetBody returns the single page's body. This method is needed to satisfy the +// Page interface. +func (current SinglePageBase) GetBody() interface{} { + return current.Body +} diff --git a/vendor/github.com/rackspace/gophercloud/params.go b/vendor/github.com/rackspace/gophercloud/params.go new file mode 100644 index 000000000..4d0f1e6e0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/params.go @@ -0,0 +1,271 @@ +package gophercloud + +import ( + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +// EnabledState is a convenience type, mostly used in Create and Update +// operations. Because the zero value of a bool is FALSE, we need to use a +// pointer instead to indicate zero-ness. +type EnabledState *bool + +// Convenience vars for EnabledState values. +var ( + iTrue = true + iFalse = false + + Enabled EnabledState = &iTrue + Disabled EnabledState = &iFalse +) + +// IntToPointer is a function for converting integers into integer pointers. +// This is useful when passing in options to operations. +func IntToPointer(i int) *int { + return &i +} + +/* +MaybeString is an internal function to be used by request methods in individual +resource packages. + +It takes a string that might be a zero value and returns either a pointer to its +address or nil. This is useful for allowing users to conveniently omit values +from an options struct by leaving them zeroed, but still pass nil to the JSON +serializer so they'll be omitted from the request body. +*/ +func MaybeString(original string) *string { + if original != "" { + return &original + } + return nil +} + +/* +MaybeInt is an internal function to be used by request methods in individual +resource packages. + +Like MaybeString, it accepts an int that may or may not be a zero value, and +returns either a pointer to its address or nil. It's intended to hint that the +JSON serializer should omit its field. +*/ +func MaybeInt(original int) *int { + if original != 0 { + return &original + } + return nil +} + +var t time.Time + +func isZero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Func, reflect.Map, reflect.Slice: + return v.IsNil() + case reflect.Array: + z := true + for i := 0; i < v.Len(); i++ { + z = z && isZero(v.Index(i)) + } + return z + case reflect.Struct: + if v.Type() == reflect.TypeOf(t) { + if v.Interface().(time.Time).IsZero() { + return true + } + return false + } + z := true + for i := 0; i < v.NumField(); i++ { + z = z && isZero(v.Field(i)) + } + return z + } + // Compare other types directly: + z := reflect.Zero(v.Type()) + return v.Interface() == z.Interface() +} + +/* +BuildQueryString is an internal function to be used by request methods in +individual resource packages. + +It accepts a tagged structure and expands it into a URL struct. Field names are +converted into query parameters based on a "q" tag. For example: + + type struct Something { + Bar string `q:"x_bar"` + Baz int `q:"lorem_ipsum"` + } + + instance := Something{ + Bar: "AAA", + Baz: "BBB", + } + +will be converted into "?x_bar=AAA&lorem_ipsum=BBB". + +The struct's fields may be strings, integers, or boolean values. Fields left at +their type's zero value will be omitted from the query. +*/ +func BuildQueryString(opts interface{}) (*url.URL, error) { + optsValue := reflect.ValueOf(opts) + if optsValue.Kind() == reflect.Ptr { + optsValue = optsValue.Elem() + } + + optsType := reflect.TypeOf(opts) + if optsType.Kind() == reflect.Ptr { + optsType = optsType.Elem() + } + + params := url.Values{} + + if optsValue.Kind() == reflect.Struct { + for i := 0; i < optsValue.NumField(); i++ { + v := optsValue.Field(i) + f := optsType.Field(i) + qTag := f.Tag.Get("q") + + // if the field has a 'q' tag, it goes in the query string + if qTag != "" { + tags := strings.Split(qTag, ",") + + // if the field is set, add it to the slice of query pieces + if !isZero(v) { + switch v.Kind() { + case reflect.String: + params.Add(tags[0], v.String()) + case reflect.Int: + params.Add(tags[0], strconv.FormatInt(v.Int(), 10)) + case reflect.Bool: + params.Add(tags[0], strconv.FormatBool(v.Bool())) + case reflect.Slice: + switch v.Type().Elem() { + case reflect.TypeOf(0): + for i := 0; i < v.Len(); i++ { + params.Add(tags[0], strconv.FormatInt(v.Index(i).Int(), 10)) + } + default: + for i := 0; i < v.Len(); i++ { + params.Add(tags[0], v.Index(i).String()) + } + } + } + } else { + // Otherwise, the field is not set. + if len(tags) == 2 && tags[1] == "required" { + // And the field is required. Return an error. + return nil, fmt.Errorf("Required query parameter [%s] not set.", f.Name) + } + } + } + } + + return &url.URL{RawQuery: params.Encode()}, nil + } + // Return an error if the underlying type of 'opts' isn't a struct. + return nil, fmt.Errorf("Options type is not a struct.") +} + +/* +BuildHeaders is an internal function to be used by request methods in +individual resource packages. + +It accepts an arbitrary tagged structure and produces a string map that's +suitable for use as the HTTP headers of an outgoing request. Field names are +mapped to header names based in "h" tags. + + type struct Something { + Bar string `h:"x_bar"` + Baz int `h:"lorem_ipsum"` + } + + instance := Something{ + Bar: "AAA", + Baz: "BBB", + } + +will be converted into: + + map[string]string{ + "x_bar": "AAA", + "lorem_ipsum": "BBB", + } + +Untagged fields and fields left at their zero values are skipped. Integers, +booleans and string values are supported. +*/ +func BuildHeaders(opts interface{}) (map[string]string, error) { + optsValue := reflect.ValueOf(opts) + if optsValue.Kind() == reflect.Ptr { + optsValue = optsValue.Elem() + } + + optsType := reflect.TypeOf(opts) + if optsType.Kind() == reflect.Ptr { + optsType = optsType.Elem() + } + + optsMap := make(map[string]string) + if optsValue.Kind() == reflect.Struct { + for i := 0; i < optsValue.NumField(); i++ { + v := optsValue.Field(i) + f := optsType.Field(i) + hTag := f.Tag.Get("h") + + // if the field has a 'h' tag, it goes in the header + if hTag != "" { + tags := strings.Split(hTag, ",") + + // if the field is set, add it to the slice of query pieces + if !isZero(v) { + switch v.Kind() { + case reflect.String: + optsMap[tags[0]] = v.String() + case reflect.Int: + optsMap[tags[0]] = strconv.FormatInt(v.Int(), 10) + case reflect.Bool: + optsMap[tags[0]] = strconv.FormatBool(v.Bool()) + } + } else { + // Otherwise, the field is not set. + if len(tags) == 2 && tags[1] == "required" { + // And the field is required. Return an error. + return optsMap, fmt.Errorf("Required header not set.") + } + } + } + + } + return optsMap, nil + } + // Return an error if the underlying type of 'opts' isn't a struct. + return optsMap, fmt.Errorf("Options type is not a struct.") +} + +// IDSliceToQueryString takes a slice of elements and converts them into a query +// string. For example, if name=foo and slice=[]int{20, 40, 60}, then the +// result would be `?name=20&name=40&name=60' +func IDSliceToQueryString(name string, ids []int) string { + str := "" + for k, v := range ids { + if k == 0 { + str += "?" + } else { + str += "&" + } + str += fmt.Sprintf("%s=%s", name, strconv.Itoa(v)) + } + return str +} + +// IntWithinRange returns TRUE if an integer falls within a defined range, and +// FALSE if not. +func IntWithinRange(val, min, max int) bool { + return val > min && val < max +} diff --git a/vendor/github.com/rackspace/gophercloud/provider_client.go b/vendor/github.com/rackspace/gophercloud/provider_client.go new file mode 100644 index 000000000..92643556f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/provider_client.go @@ -0,0 +1,308 @@ +package gophercloud + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "strings" +) + +// DefaultUserAgent is the default User-Agent string set in the request header. +const DefaultUserAgent = "gophercloud/1.0.0" + +// UserAgent represents a User-Agent header. +type UserAgent struct { + // prepend is the slice of User-Agent strings to prepend to DefaultUserAgent. + // All the strings to prepend are accumulated and prepended in the Join method. + prepend []string +} + +// Prepend prepends a user-defined string to the default User-Agent string. Users +// may pass in one or more strings to prepend. +func (ua *UserAgent) Prepend(s ...string) { + ua.prepend = append(s, ua.prepend...) +} + +// Join concatenates all the user-defined User-Agend strings with the default +// Gophercloud User-Agent string. +func (ua *UserAgent) Join() string { + uaSlice := append(ua.prepend, DefaultUserAgent) + return strings.Join(uaSlice, " ") +} + +// ProviderClient stores details that are required to interact with any +// services within a specific provider's API. +// +// Generally, you acquire a ProviderClient by calling the NewClient method in +// the appropriate provider's child package, providing whatever authentication +// credentials are required. +type ProviderClient struct { + // IdentityBase is the base URL used for a particular provider's identity + // service - it will be used when issuing authenticatation requests. It + // should point to the root resource of the identity service, not a specific + // identity version. + IdentityBase string + + // IdentityEndpoint is the identity endpoint. This may be a specific version + // of the identity service. If this is the case, this endpoint is used rather + // than querying versions first. + IdentityEndpoint string + + // TokenID is the ID of the most recently issued valid token. + TokenID string + + // EndpointLocator describes how this provider discovers the endpoints for + // its constituent services. + EndpointLocator EndpointLocator + + // HTTPClient allows users to interject arbitrary http, https, or other transit behaviors. + HTTPClient http.Client + + // UserAgent represents the User-Agent header in the HTTP request. + UserAgent UserAgent + + // ReauthFunc is the function used to re-authenticate the user if the request + // fails with a 401 HTTP response code. This a needed because there may be multiple + // authentication functions for different Identity service versions. + ReauthFunc func() error +} + +// AuthenticatedHeaders returns a map of HTTP headers that are common for all +// authenticated service requests. +func (client *ProviderClient) AuthenticatedHeaders() map[string]string { + if client.TokenID == "" { + return map[string]string{} + } + return map[string]string{"X-Auth-Token": client.TokenID} +} + +// RequestOpts customizes the behavior of the provider.Request() method. +type RequestOpts struct { + // JSONBody, if provided, will be encoded as JSON and used as the body of the HTTP request. The + // content type of the request will default to "application/json" unless overridden by MoreHeaders. + // It's an error to specify both a JSONBody and a RawBody. + JSONBody interface{} + // RawBody contains an io.ReadSeeker that will be consumed by the request directly. No content-type + // will be set unless one is provided explicitly by MoreHeaders. + RawBody io.ReadSeeker + + // JSONResponse, if provided, will be populated with the contents of the response body parsed as + // JSON. + JSONResponse interface{} + // OkCodes contains a list of numeric HTTP status codes that should be interpreted as success. If + // the response has a different code, an error will be returned. + OkCodes []int + + // MoreHeaders specifies additional HTTP headers to be provide on the request. If a header is + // provided with a blank value (""), that header will be *omitted* instead: use this to suppress + // the default Accept header or an inferred Content-Type, for example. + MoreHeaders map[string]string +} + +// UnexpectedResponseCodeError is returned by the Request method when a response code other than +// those listed in OkCodes is encountered. +type UnexpectedResponseCodeError struct { + URL string + Method string + Expected []int + Actual int + Body []byte +} + +func (err *UnexpectedResponseCodeError) Error() string { + return fmt.Sprintf( + "Expected HTTP response code %v when accessing [%s %s], but got %d instead\n%s", + err.Expected, err.Method, err.URL, err.Actual, err.Body, + ) +} + +var applicationJSON = "application/json" + +// Request performs an HTTP request using the ProviderClient's current HTTPClient. An authentication +// header will automatically be provided. +func (client *ProviderClient) Request(method, url string, options RequestOpts) (*http.Response, error) { + var body io.ReadSeeker + var contentType *string + + // Derive the content body by either encoding an arbitrary object as JSON, or by taking a provided + // io.ReadSeeker as-is. Default the content-type to application/json. + if options.JSONBody != nil { + if options.RawBody != nil { + panic("Please provide only one of JSONBody or RawBody to gophercloud.Request().") + } + + rendered, err := json.Marshal(options.JSONBody) + if err != nil { + return nil, err + } + + body = bytes.NewReader(rendered) + contentType = &applicationJSON + } + + if options.RawBody != nil { + body = options.RawBody + } + + // Construct the http.Request. + req, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + // Populate the request headers. Apply options.MoreHeaders last, to give the caller the chance to + // modify or omit any header. + if contentType != nil { + req.Header.Set("Content-Type", *contentType) + } + req.Header.Set("Accept", applicationJSON) + + for k, v := range client.AuthenticatedHeaders() { + req.Header.Add(k, v) + } + + // Set the User-Agent header + req.Header.Set("User-Agent", client.UserAgent.Join()) + + if options.MoreHeaders != nil { + for k, v := range options.MoreHeaders { + if v != "" { + req.Header.Set(k, v) + } else { + req.Header.Del(k) + } + } + } + + // Issue the request. + resp, err := client.HTTPClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode == http.StatusUnauthorized { + if client.ReauthFunc != nil { + err = client.ReauthFunc() + if err != nil { + return nil, fmt.Errorf("Error trying to re-authenticate: %s", err) + } + if options.RawBody != nil { + options.RawBody.Seek(0, 0) + } + resp.Body.Close() + resp, err = client.Request(method, url, options) + if err != nil { + return nil, fmt.Errorf("Successfully re-authenticated, but got error executing request: %s", err) + } + + return resp, nil + } + } + + // Allow default OkCodes if none explicitly set + if options.OkCodes == nil { + options.OkCodes = defaultOkCodes(method) + } + + // Validate the HTTP response status. + var ok bool + for _, code := range options.OkCodes { + if resp.StatusCode == code { + ok = true + break + } + } + if !ok { + body, _ := ioutil.ReadAll(resp.Body) + resp.Body.Close() + return resp, &UnexpectedResponseCodeError{ + URL: url, + Method: method, + Expected: options.OkCodes, + Actual: resp.StatusCode, + Body: body, + } + } + + // Parse the response body as JSON, if requested to do so. + if options.JSONResponse != nil { + defer resp.Body.Close() + if err := json.NewDecoder(resp.Body).Decode(options.JSONResponse); err != nil { + return nil, err + } + } + + return resp, nil +} + +func defaultOkCodes(method string) []int { + switch { + case method == "GET": + return []int{200} + case method == "POST": + return []int{201, 202} + case method == "PUT": + return []int{201, 202} + case method == "DELETE": + return []int{202, 204} + } + + return []int{} +} + +func (client *ProviderClient) Get(url string, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { + if opts == nil { + opts = &RequestOpts{} + } + if JSONResponse != nil { + opts.JSONResponse = JSONResponse + } + return client.Request("GET", url, *opts) +} + +func (client *ProviderClient) Post(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { + if opts == nil { + opts = &RequestOpts{} + } + + if v, ok := (JSONBody).(io.ReadSeeker); ok { + opts.RawBody = v + } else if JSONBody != nil { + opts.JSONBody = JSONBody + } + + if JSONResponse != nil { + opts.JSONResponse = JSONResponse + } + + return client.Request("POST", url, *opts) +} + +func (client *ProviderClient) Put(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { + if opts == nil { + opts = &RequestOpts{} + } + + if v, ok := (JSONBody).(io.ReadSeeker); ok { + opts.RawBody = v + } else if JSONBody != nil { + opts.JSONBody = JSONBody + } + + if JSONResponse != nil { + opts.JSONResponse = JSONResponse + } + + return client.Request("PUT", url, *opts) +} + +func (client *ProviderClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { + if opts == nil { + opts = &RequestOpts{} + } + + return client.Request("DELETE", url, *opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/auth_env.go b/vendor/github.com/rackspace/gophercloud/rackspace/auth_env.go new file mode 100644 index 000000000..5852c3ce7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/auth_env.go @@ -0,0 +1,57 @@ +package rackspace + +import ( + "fmt" + "os" + + "github.com/rackspace/gophercloud" +) + +var nilOptions = gophercloud.AuthOptions{} + +// ErrNoAuthUrl, ErrNoUsername, and ErrNoPassword errors indicate of the +// required RS_AUTH_URL, RS_USERNAME, or RS_PASSWORD environment variables, +// respectively, remain undefined. See the AuthOptions() function for more details. +var ( + ErrNoAuthURL = fmt.Errorf("Environment variable RS_AUTH_URL or OS_AUTH_URL need to be set.") + ErrNoUsername = fmt.Errorf("Environment variable RS_USERNAME or OS_USERNAME need to be set.") + ErrNoPassword = fmt.Errorf("Environment variable RS_API_KEY or RS_PASSWORD needs to be set.") +) + +func prefixedEnv(base string) string { + value := os.Getenv("RS_" + base) + if value == "" { + value = os.Getenv("OS_" + base) + } + return value +} + +// AuthOptionsFromEnv fills out an identity.AuthOptions structure with the +// settings found on the various Rackspace RS_* environment variables. +func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { + authURL := prefixedEnv("AUTH_URL") + username := prefixedEnv("USERNAME") + password := prefixedEnv("PASSWORD") + apiKey := prefixedEnv("API_KEY") + + if authURL == "" { + return nilOptions, ErrNoAuthURL + } + + if username == "" { + return nilOptions, ErrNoUsername + } + + if password == "" && apiKey == "" { + return nilOptions, ErrNoPassword + } + + ao := gophercloud.AuthOptions{ + IdentityEndpoint: authURL, + Username: username, + Password: password, + APIKey: apiKey, + } + + return ao, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/delegate.go new file mode 100644 index 000000000..1cd1b6e30 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/delegate.go @@ -0,0 +1,131 @@ +package snapshots + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots" +) + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id) +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToSnapshotCreateMap() (map[string]interface{}, error) +} + +// CreateOpts contains options for creating a Snapshot. This object is passed to +// the snapshots.Create function. For more information about these parameters, +// see the Snapshot object. +type CreateOpts struct { + // REQUIRED + VolumeID string + // OPTIONAL + Description string + // OPTIONAL + Force bool + // OPTIONAL + Name string +} + +// ToSnapshotCreateMap assembles a request body based on the contents of a +// CreateOpts. +func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.VolumeID == "" { + return nil, errors.New("Required CreateOpts field 'VolumeID' not set.") + } + + s["volume_id"] = opts.VolumeID + + if opts.Description != "" { + s["display_description"] = opts.Description + } + if opts.Name != "" { + s["display_name"] = opts.Name + } + if opts.Force { + s["force"] = opts.Force + } + + return map[string]interface{}{"snapshot": s}, nil +} + +// Create will create a new Snapshot based on the values in CreateOpts. To +// extract the Snapshot object from the response, call the Extract method on the +// CreateResult. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + return CreateResult{os.Create(client, opts)} +} + +// Delete will delete the existing Snapshot with the provided ID. +func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(client, id) +} + +// Get retrieves the Snapshot with the provided ID. To extract the Snapshot +// object from the response, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + return GetResult{os.Get(client, id)} +} + +// List returns Snapshots. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client, os.ListOpts{}) +} + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type UpdateOptsBuilder interface { + ToSnapshotUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the common options struct used in this package's Update +// operation. +type UpdateOpts struct { + Name string + Description string +} + +// ToSnapshotUpdateMap casts a UpdateOpts struct to a map. +func (opts UpdateOpts) ToSnapshotUpdateMap() (map[string]interface{}, error) { + s := make(map[string]interface{}) + + if opts.Name != "" { + s["display_name"] = opts.Name + } + if opts.Description != "" { + s["display_description"] = opts.Description + } + + return map[string]interface{}{"snapshot": s}, nil +} + +// Update accepts a UpdateOpts struct and updates an existing snapshot using the +// values provided. +func Update(c *gophercloud.ServiceClient, snapshotID string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToSnapshotUpdateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Request("PUT", updateURL(c, snapshotID), gophercloud.RequestOpts{ + JSONBody: &reqBody, + JSONResponse: &res.Body, + OkCodes: []int{200, 201}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/doc.go new file mode 100644 index 000000000..ad6064f2a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/doc.go @@ -0,0 +1,3 @@ +// Package snapshots provides information and interaction with the snapshot +// API resource for the Rackspace Block Storage service. +package snapshots diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/results.go new file mode 100644 index 000000000..c81644c5d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots/results.go @@ -0,0 +1,147 @@ +package snapshots + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Status is the type used to represent a snapshot's status +type Status string + +// Constants to use for supported statuses +const ( + Creating Status = "CREATING" + Available Status = "AVAILABLE" + Deleting Status = "DELETING" + Error Status = "ERROR" + DeleteError Status = "ERROR_DELETING" +) + +// Snapshot is the Rackspace representation of an external block storage device. +type Snapshot struct { + // The timestamp when this snapshot was created. + CreatedAt string `mapstructure:"created_at"` + + // The human-readable description for this snapshot. + Description string `mapstructure:"display_description"` + + // The human-readable name for this snapshot. + Name string `mapstructure:"display_name"` + + // The UUID for this snapshot. + ID string `mapstructure:"id"` + + // The random metadata associated with this snapshot. Note: unlike standard + // OpenStack snapshots, this cannot actually be set. + Metadata map[string]string `mapstructure:"metadata"` + + // Indicates the current progress of the snapshot's backup procedure. + Progress string `mapstructure:"os-extended-snapshot-attributes:progress"` + + // The project ID. + ProjectID string `mapstructure:"os-extended-snapshot-attributes:project_id"` + + // The size of the volume which this snapshot backs up. + Size int `mapstructure:"size"` + + // The status of the snapshot. + Status Status `mapstructure:"status"` + + // The ID of the volume which this snapshot seeks to back up. + VolumeID string `mapstructure:"volume_id"` +} + +// CreateResult represents the result of a create operation +type CreateResult struct { + os.CreateResult +} + +// GetResult represents the result of a get operation +type GetResult struct { + os.GetResult +} + +// UpdateResult represents the result of an update operation +type UpdateResult struct { + gophercloud.Result +} + +func commonExtract(resp interface{}, err error) (*Snapshot, error) { + if err != nil { + return nil, err + } + + var respStruct struct { + Snapshot *Snapshot `json:"snapshot"` + } + + err = mapstructure.Decode(resp, &respStruct) + + return respStruct.Snapshot, err +} + +// Extract will get the Snapshot object out of the GetResult object. +func (r GetResult) Extract() (*Snapshot, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Snapshot object out of the CreateResult object. +func (r CreateResult) Extract() (*Snapshot, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Snapshot object out of the UpdateResult object. +func (r UpdateResult) Extract() (*Snapshot, error) { + return commonExtract(r.Body, r.Err) +} + +// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call. +func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) { + var response struct { + Snapshots []Snapshot `json:"snapshots"` + } + + err := mapstructure.Decode(page.(os.ListResult).Body, &response) + return response.Snapshots, err +} + +// WaitUntilComplete will continually poll a snapshot until it successfully +// transitions to a specified state. It will do this for at most the number of +// seconds specified. +func (snapshot Snapshot) WaitUntilComplete(c *gophercloud.ServiceClient, timeout int) error { + return gophercloud.WaitFor(timeout, func() (bool, error) { + // Poll resource + current, err := Get(c, snapshot.ID).Extract() + if err != nil { + return false, err + } + + // Has it been built yet? + if current.Progress == "100%" { + return true, nil + } + + return false, nil + }) +} + +// WaitUntilDeleted will continually poll a snapshot until it has been +// successfully deleted, i.e. returns a 404 status. +func (snapshot Snapshot) WaitUntilDeleted(c *gophercloud.ServiceClient, timeout int) error { + return gophercloud.WaitFor(timeout, func() (bool, error) { + // Poll resource + _, err := Get(c, snapshot.ID).Extract() + + // Check for a 404 + if casted, ok := err.(*gophercloud.UnexpectedResponseCodeError); ok && casted.Actual == 404 { + return true, nil + } else if err != nil { + return false, err + } + + return false, nil + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/delegate.go new file mode 100644 index 000000000..438349410 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/delegate.go @@ -0,0 +1,75 @@ +package volumes + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes" + "github.com/rackspace/gophercloud/pagination" +) + +type CreateOpts struct { + os.CreateOpts +} + +func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) { + if opts.Size < 75 || opts.Size > 1024 { + return nil, fmt.Errorf("Size field must be between 75 and 1024") + } + + return opts.CreateOpts.ToVolumeCreateMap() +} + +// Create will create a new Volume based on the values in CreateOpts. To extract +// the Volume object from the response, call the Extract method on the +// CreateResult. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult { + return CreateResult{os.Create(client, opts)} +} + +// Delete will delete the existing Volume with the provided ID. +func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(client, id) +} + +// Get retrieves the Volume with the provided ID. To extract the Volume object +// from the response, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + return GetResult{os.Get(client, id)} +} + +// List returns volumes optionally limited by the conditions provided in ListOpts. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client, os.ListOpts{}) +} + +// UpdateOpts contain options for updating an existing Volume. This object is passed +// to the volumes.Update function. For more information about the parameters, see +// the Volume object. +type UpdateOpts struct { + // OPTIONAL + Name string + // OPTIONAL + Description string +} + +// ToVolumeUpdateMap assembles a request body based on the contents of an +// UpdateOpts. +func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) { + v := make(map[string]interface{}) + + if opts.Description != "" { + v["display_description"] = opts.Description + } + if opts.Name != "" { + v["display_name"] = opts.Name + } + + return map[string]interface{}{"volume": v}, nil +} + +// Update will update the Volume with provided information. To extract the updated +// Volume from the response, call the Extract method on the UpdateResult. +func Update(client *gophercloud.ServiceClient, id string, opts os.UpdateOptsBuilder) UpdateResult { + return UpdateResult{os.Update(client, id, opts)} +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/doc.go new file mode 100644 index 000000000..b2be25c53 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/doc.go @@ -0,0 +1,3 @@ +// Package volumes provides information and interaction with the volume +// API resource for the Rackspace Block Storage service. +package volumes diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/results.go new file mode 100644 index 000000000..c7c2cc498 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes/results.go @@ -0,0 +1,66 @@ +package volumes + +import ( + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes" + "github.com/rackspace/gophercloud/pagination" + + "github.com/mitchellh/mapstructure" +) + +// Volume wraps an Openstack volume +type Volume os.Volume + +// CreateResult represents the result of a create operation +type CreateResult struct { + os.CreateResult +} + +// GetResult represents the result of a get operation +type GetResult struct { + os.GetResult +} + +// UpdateResult represents the result of an update operation +type UpdateResult struct { + os.UpdateResult +} + +func commonExtract(resp interface{}, err error) (*Volume, error) { + if err != nil { + return nil, err + } + + var respStruct struct { + Volume *Volume `json:"volume"` + } + + err = mapstructure.Decode(resp, &respStruct) + + return respStruct.Volume, err +} + +// Extract will get the Volume object out of the GetResult object. +func (r GetResult) Extract() (*Volume, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Volume object out of the CreateResult object. +func (r CreateResult) Extract() (*Volume, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Volume object out of the UpdateResult object. +func (r UpdateResult) Extract() (*Volume, error) { + return commonExtract(r.Body, r.Err) +} + +// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call. +func ExtractVolumes(page pagination.Page) ([]Volume, error) { + var response struct { + Volumes []Volume `json:"volumes"` + } + + err := mapstructure.Decode(page.(os.ListResult).Body, &response) + + return response.Volumes, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/delegate.go new file mode 100644 index 000000000..c96b3e4a3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/delegate.go @@ -0,0 +1,18 @@ +package volumetypes + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns all volume types. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// Get will retrieve the volume type with the provided ID. To extract the volume +// type from the result, call the Extract method on the GetResult. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + return GetResult{os.Get(client, id)} +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/doc.go new file mode 100644 index 000000000..70122b77c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/doc.go @@ -0,0 +1,3 @@ +// Package volumetypes provides information and interaction with the volume type +// API resource for the Rackspace Block Storage service. +package volumetypes diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/results.go new file mode 100644 index 000000000..39c8d6f7f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes/results.go @@ -0,0 +1,37 @@ +package volumetypes + +import ( + "github.com/mitchellh/mapstructure" + os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes" + "github.com/rackspace/gophercloud/pagination" +) + +type VolumeType os.VolumeType + +type GetResult struct { + os.GetResult +} + +// Extract will get the Volume Type struct out of the response. +func (r GetResult) Extract() (*VolumeType, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.VolumeType, err +} + +func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) { + var response struct { + VolumeTypes []VolumeType `mapstructure:"volume_types"` + } + + err := mapstructure.Decode(page.(os.ListResult).Body, &response) + return response.VolumeTypes, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/delegate.go new file mode 100644 index 000000000..5af7e0778 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/delegate.go @@ -0,0 +1,18 @@ +package base + +import ( + "github.com/rackspace/gophercloud" + + os "github.com/rackspace/gophercloud/openstack/cdn/v1/base" +) + +// Get retrieves the home document, allowing the user to discover the +// entire API. +func Get(c *gophercloud.ServiceClient) os.GetResult { + return os.Get(c) +} + +// Ping retrieves a ping to the server. +func Ping(c *gophercloud.ServiceClient) os.PingResult { + return os.Ping(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/doc.go new file mode 100644 index 000000000..5582306a8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/base/doc.go @@ -0,0 +1,4 @@ +// Package base provides information and interaction with the base API +// resource in the Rackspace CDN service. This API resource allows for +// retrieving the Home Document and pinging the root URL. +package base diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/delegate.go new file mode 100644 index 000000000..7152fa23a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/delegate.go @@ -0,0 +1,18 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" + + os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a single page of CDN flavors. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return os.List(c) +} + +// Get retrieves a specific flavor based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/doc.go new file mode 100644 index 000000000..4ad966eac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors/doc.go @@ -0,0 +1,6 @@ +// Package flavors provides information and interaction with the flavors API +// resource in the Rackspace CDN service. This API resource allows for +// listing flavors and retrieving a specific flavor. +// +// A flavor is a mapping configuration to a CDN provider. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/delegate.go new file mode 100644 index 000000000..07c93a8dc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/delegate.go @@ -0,0 +1,13 @@ +package serviceassets + +import ( + "github.com/rackspace/gophercloud" + + os "github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets" +) + +// Delete accepts a unique ID and deletes the CDN service asset associated with +// it. +func Delete(c *gophercloud.ServiceClient, id string, opts os.DeleteOptsBuilder) os.DeleteResult { + return os.Delete(c, id, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/doc.go new file mode 100644 index 000000000..46b3d50a8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets/doc.go @@ -0,0 +1,7 @@ +// Package serviceassets provides information and interaction with the +// serviceassets API resource in the Rackspace CDN service. This API resource +// allows for deleting cached assets. +// +// A service distributes assets across the network. Service assets let you +// interrogate properties about these assets and perform certain actions on them. +package serviceassets diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/delegate.go new file mode 100644 index 000000000..e3f145997 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/delegate.go @@ -0,0 +1,37 @@ +package services + +import ( + "github.com/rackspace/gophercloud" + + os "github.com/rackspace/gophercloud/openstack/cdn/v1/services" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// CDN services. It accepts a ListOpts struct, which allows for pagination via +// marker and limit. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// Create accepts a CreateOpts struct and creates a new CDN service using the +// values provided. +func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, opts) +} + +// Get retrieves a specific service based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(c, id) +} + +// Update accepts a UpdateOpts struct and updates an existing CDN service using +// the values provided. +func Update(c *gophercloud.ServiceClient, id string, patches []os.Patch) os.UpdateResult { + return os.Update(c, id, patches) +} + +// Delete accepts a unique ID and deletes the CDN service associated with it. +func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/doc.go new file mode 100644 index 000000000..ee6e2a54f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/cdn/v1/services/doc.go @@ -0,0 +1,7 @@ +// Package services provides information and interaction with the services API +// resource in the Rackspace CDN service. This API resource allows for +// listing, creating, updating, retrieving, and deleting services. +// +// A service represents an application that has its content cached to the edge +// nodes. +package services diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/client.go b/vendor/github.com/rackspace/gophercloud/rackspace/client.go new file mode 100644 index 000000000..a8f413ed9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/client.go @@ -0,0 +1,224 @@ +package rackspace + +import ( + "fmt" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack" + "github.com/rackspace/gophercloud/openstack/utils" + tokens2 "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens" +) + +const ( + // RackspaceUSIdentity is an identity endpoint located in the United States. + RackspaceUSIdentity = "https://identity.api.rackspacecloud.com/v2.0/" + + // RackspaceUKIdentity is an identity endpoint located in the UK. + RackspaceUKIdentity = "https://lon.identity.api.rackspacecloud.com/v2.0/" +) + +const ( + v20 = "v2.0" +) + +// NewClient creates a client that's prepared to communicate with the Rackspace API, but is not +// yet authenticated. Most users will probably prefer using the AuthenticatedClient function +// instead. +// +// Provide the base URL of the identity endpoint you wish to authenticate against as "endpoint". +// Often, this will be either RackspaceUSIdentity or RackspaceUKIdentity. +func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { + if endpoint == "" { + return os.NewClient(RackspaceUSIdentity) + } + return os.NewClient(endpoint) +} + +// AuthenticatedClient logs in to Rackspace with the provided credentials and constructs a +// ProviderClient that's ready to operate. +// +// If the provided AuthOptions does not specify an explicit IdentityEndpoint, it will default to +// the canonical, production Rackspace US identity endpoint. +func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { + client, err := NewClient(options.IdentityEndpoint) + if err != nil { + return nil, err + } + + err = Authenticate(client, options) + if err != nil { + return nil, err + } + return client, nil +} + +// Authenticate or re-authenticate against the most recent identity service supported at the +// provided endpoint. +func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + versions := []*utils.Version{ + &utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"}, + } + + chosen, endpoint, err := utils.ChooseVersion(client, versions) + if err != nil { + return err + } + + switch chosen.ID { + case v20: + return v2auth(client, endpoint, options) + default: + // The switch statement must be out of date from the versions list. + return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) + } +} + +// AuthenticateV2 explicitly authenticates with v2 of the identity service. +func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + return v2auth(client, "", options) +} + +func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error { + v2Client := NewIdentityV2(client) + if endpoint != "" { + v2Client.Endpoint = endpoint + } + + result := tokens2.Create(v2Client, tokens2.WrapOptions(options)) + + token, err := result.ExtractToken() + if err != nil { + return err + } + + catalog, err := result.ExtractServiceCatalog() + if err != nil { + return err + } + + if options.AllowReauth { + client.ReauthFunc = func() error { + return AuthenticateV2(client, options) + } + } + client.TokenID = token.ID + client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { + return os.V2EndpointURL(catalog, opts) + } + + return nil +} + +// NewIdentityV2 creates a ServiceClient that may be used to access the v2 identity service. +func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient { + v2Endpoint := client.IdentityBase + "v2.0/" + + return &gophercloud.ServiceClient{ + ProviderClient: client, + Endpoint: v2Endpoint, + } +} + +// NewComputeV2 creates a ServiceClient that may be used to access the v2 compute service. +func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("compute") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + + return &gophercloud.ServiceClient{ + ProviderClient: client, + Endpoint: url, + }, nil +} + +// NewObjectCDNV1 creates a ServiceClient that may be used with the Rackspace v1 CDN. +func NewObjectCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("rax:object-cdn") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewObjectStorageV1 creates a ServiceClient that may be used with the Rackspace v1 object storage package. +func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + return os.NewObjectStorageV1(client, eo) +} + +// NewBlockStorageV1 creates a ServiceClient that can be used to access the +// Rackspace Cloud Block Storage v1 API. +func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("volume") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewLBV1 creates a ServiceClient that can be used to access the Rackspace +// Cloud Load Balancer v1 API. +func NewLBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("rax:load-balancer") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewNetworkV2 creates a ServiceClient that can be used to access the Rackspace +// Networking v2 API. +func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("network") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewCDNV1 creates a ServiceClient that may be used to access the Rackspace v1 +// CDN service. +func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("rax:cdn") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service. +func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("orchestration") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewRackConnectV3 creates a ServiceClient that may be used to access the v3 RackConnect service. +func NewRackConnectV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("rax:rackconnect") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} + +// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. +func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("rax:database") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume/delegate.go new file mode 100644 index 000000000..2580459f0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume/delegate.go @@ -0,0 +1,12 @@ +package bootfromvolume + +import ( + "github.com/rackspace/gophercloud" + osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume" + osServers "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// Create requests the creation of a server from the given block device mapping. +func Create(client *gophercloud.ServiceClient, opts osServers.CreateOptsBuilder) osServers.CreateResult { + return osBFV.Create(client, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/delegate.go new file mode 100644 index 000000000..081ea478c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/delegate.go @@ -0,0 +1,43 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" + "github.com/rackspace/gophercloud/pagination" +) + +// ListOpts helps control the results returned by the List() function. For example, a flavor with a +// minDisk field of 10 will not be returned if you specify MinDisk set to 20. +type ListOpts struct { + + // MinDisk and MinRAM, if provided, elide flavors that do not meet your criteria. + MinDisk int `q:"minDisk"` + MinRAM int `q:"minRam"` + + // Marker specifies the ID of the last flavor in the previous page. + Marker string `q:"marker"` + + // Limit instructs List to refrain from sending excessively large lists of flavors. + Limit int `q:"limit"` +} + +// ToFlavorListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToFlavorListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListDetail enumerates the server images available to your account. +func ListDetail(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.ListDetail(client, opts) +} + +// Get returns details about a single flavor, identity by ID. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = client.Get(getURL(client, id), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/doc.go new file mode 100644 index 000000000..278229ab9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/doc.go @@ -0,0 +1,3 @@ +// Package flavors provides information and interaction with the flavor +// API resource for the Rackspace Cloud Servers service. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/fixtures.go new file mode 100644 index 000000000..957dccfd7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/fixtures.go @@ -0,0 +1,137 @@ +// +build fixtures + +package flavors + +// ListOutput is a sample response of a flavor List request. +const ListOutput = ` +{ + "flavors": [ + { + "OS-FLV-EXT-DATA:ephemeral": 0, + "OS-FLV-WITH-EXT-SPECS:extra_specs": { + "class": "performance1", + "disk_io_index": "40", + "number_of_data_disks": "0", + "policy_class": "performance_flavor", + "resize_policy_class": "performance_flavor" + }, + "disk": 20, + "id": "performance1-1", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-1", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-1", + "rel": "bookmark" + } + ], + "name": "1 GB Performance", + "ram": 1024, + "rxtx_factor": 200, + "swap": "", + "vcpus": 1 + }, + { + "OS-FLV-EXT-DATA:ephemeral": 20, + "OS-FLV-WITH-EXT-SPECS:extra_specs": { + "class": "performance1", + "disk_io_index": "40", + "number_of_data_disks": "1", + "policy_class": "performance_flavor", + "resize_policy_class": "performance_flavor" + }, + "disk": 40, + "id": "performance1-2", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-2", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-2", + "rel": "bookmark" + } + ], + "name": "2 GB Performance", + "ram": 2048, + "rxtx_factor": 400, + "swap": "", + "vcpus": 2 + } + ] +}` + +// GetOutput is a sample response from a flavor Get request. Its contents correspond to the +// Performance1Flavor struct. +const GetOutput = ` +{ + "flavor": { + "OS-FLV-EXT-DATA:ephemeral": 0, + "OS-FLV-WITH-EXT-SPECS:extra_specs": { + "class": "performance1", + "disk_io_index": "40", + "number_of_data_disks": "0", + "policy_class": "performance_flavor", + "resize_policy_class": "performance_flavor" + }, + "disk": 20, + "id": "performance1-1", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-1", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-1", + "rel": "bookmark" + } + ], + "name": "1 GB Performance", + "ram": 1024, + "rxtx_factor": 200, + "swap": "", + "vcpus": 1 + } +} +` + +// Performance1Flavor is the expected result of parsing GetOutput, or the first element of +// ListOutput. +var Performance1Flavor = Flavor{ + ID: "performance1-1", + Disk: 20, + RAM: 1024, + Name: "1 GB Performance", + RxTxFactor: 200.0, + Swap: 0, + VCPUs: 1, + ExtraSpecs: ExtraSpecs{ + NumDataDisks: 0, + Class: "performance1", + DiskIOIndex: 0, + PolicyClass: "performance_flavor", + }, +} + +// Performance2Flavor is the second result expected from parsing ListOutput. +var Performance2Flavor = Flavor{ + ID: "performance1-2", + Disk: 40, + RAM: 2048, + Name: "2 GB Performance", + RxTxFactor: 400.0, + Swap: 0, + VCPUs: 2, + ExtraSpecs: ExtraSpecs{ + NumDataDisks: 0, + Class: "performance1", + DiskIOIndex: 0, + PolicyClass: "performance_flavor", + }, +} + +// ExpectedFlavorSlice is the slice of Flavor structs that are expected to be parsed from +// ListOutput. +var ExpectedFlavorSlice = []Flavor{Performance1Flavor, Performance2Flavor} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/results.go new file mode 100644 index 000000000..af444a766 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/results.go @@ -0,0 +1,104 @@ +package flavors + +import ( + "reflect" + + "github.com/rackspace/gophercloud" + "github.com/mitchellh/mapstructure" + os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtraSpecs provide additional information about the flavor. +type ExtraSpecs struct { + // The number of data disks + NumDataDisks int `mapstructure:"number_of_data_disks"` + // The flavor class + Class string `mapstructure:"class"` + // Relative measure of disk I/O performance from 0-99, where higher is faster + DiskIOIndex int `mapstructure:"disk_io_index"` + PolicyClass string `mapstructure:"policy_class"` +} + +// Flavor records represent (virtual) hardware configurations for server resources in a region. +type Flavor struct { + // The Id field contains the flavor's unique identifier. + // For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance. + ID string `mapstructure:"id"` + + // The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively. + Disk int `mapstructure:"disk"` + RAM int `mapstructure:"ram"` + + // The Name field provides a human-readable moniker for the flavor. + Name string `mapstructure:"name"` + + RxTxFactor float64 `mapstructure:"rxtx_factor"` + + // Swap indicates how much space is reserved for swap. + // If not provided, this field will be set to 0. + Swap int `mapstructure:"swap"` + + // VCPUs indicates how many (virtual) CPUs are available for this flavor. + VCPUs int `mapstructure:"vcpus"` + + // ExtraSpecs provides extra information about the flavor + ExtraSpecs ExtraSpecs `mapstructure:"OS-FLV-WITH-EXT-SPECS:extra_specs"` +} + +// GetResult temporarily holds the response from a Get call. +type GetResult struct { + gophercloud.Result +} + +// Extract provides access to the individual Flavor returned by the Get function. +func (gr GetResult) Extract() (*Flavor, error) { + if gr.Err != nil { + return nil, gr.Err + } + + var result struct { + Flavor Flavor `mapstructure:"flavor"` + } + + cfg := &mapstructure.DecoderConfig{ + DecodeHook: defaulter, + Result: &result, + } + decoder, err := mapstructure.NewDecoder(cfg) + if err != nil { + return nil, err + } + err = decoder.Decode(gr.Body) + return &result.Flavor, err +} + +func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) { + if (from == reflect.String) && (to == reflect.Int) { + return 0, nil + } + return v, nil +} + +// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation. +func ExtractFlavors(page pagination.Page) ([]Flavor, error) { + casted := page.(os.FlavorPage).Body + var container struct { + Flavors []Flavor `mapstructure:"flavors"` + } + + cfg := &mapstructure.DecoderConfig{ + DecodeHook: defaulter, + Result: &container, + } + decoder, err := mapstructure.NewDecoder(cfg) + if err != nil { + return container.Flavors, err + } + err = decoder.Decode(casted) + if err != nil { + return container.Flavors, err + } + + return container.Flavors, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/urls.go new file mode 100644 index 000000000..f4e2c3dac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/flavors/urls.go @@ -0,0 +1,9 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" +) + +func getURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("flavors", id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/delegate.go new file mode 100644 index 000000000..18e1f315a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/delegate.go @@ -0,0 +1,22 @@ +package images + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/compute/v2/images" + "github.com/rackspace/gophercloud/pagination" +) + +// ListDetail enumerates the available server images. +func ListDetail(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.ListDetail(client, opts) +} + +// Get acquires additional detail about a specific image by ID. +func Get(client *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(client, id) +} + +// ExtractImages interprets a page as a collection of server images. +func ExtractImages(page pagination.Page) ([]os.Image, error) { + return os.ExtractImages(page) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/doc.go new file mode 100644 index 000000000..cfae80671 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/doc.go @@ -0,0 +1,3 @@ +// Package images provides information and interaction with the image +// API resource for the Rackspace Cloud Servers service. +package images diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/fixtures.go new file mode 100644 index 000000000..ccfbdc6a1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/images/fixtures.go @@ -0,0 +1,200 @@ +// +build fixtures + +package images + +import ( + os "github.com/rackspace/gophercloud/openstack/compute/v2/images" +) + +// ListOutput is an example response from an /images/detail request. +const ListOutput = ` +{ + "images": [ + { + "OS-DCF:diskConfig": "MANUAL", + "OS-EXT-IMG-SIZE:size": 1.017415075e+09, + "created": "2014-10-01T15:49:02Z", + "id": "30aa010e-080e-4d4b-a7f9-09fc55b07d69", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69", + "rel": "bookmark" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69", + "rel": "alternate", + "type": "application/vnd.openstack.image" + } + ], + "metadata": { + "auto_disk_config": "disabled", + "cache_in_nova": "True", + "com.rackspace__1__build_core": "1", + "com.rackspace__1__build_managed": "1", + "com.rackspace__1__build_rackconnect": "1", + "com.rackspace__1__options": "0", + "com.rackspace__1__platform_target": "PublicCloud", + "com.rackspace__1__release_build_date": "2014-10-01_15-46-08", + "com.rackspace__1__release_id": "100", + "com.rackspace__1__release_version": "10", + "com.rackspace__1__source": "kickstart", + "com.rackspace__1__visible_core": "1", + "com.rackspace__1__visible_managed": "0", + "com.rackspace__1__visible_rackconnect": "0", + "image_type": "base", + "org.openstack__1__architecture": "x64", + "org.openstack__1__os_distro": "org.archlinux", + "org.openstack__1__os_version": "2014.8", + "os_distro": "arch", + "os_type": "linux", + "vm_mode": "hvm" + }, + "minDisk": 20, + "minRam": 512, + "name": "Arch 2014.10 (PVHVM)", + "progress": 100, + "status": "ACTIVE", + "updated": "2014-10-01T19:37:58Z" + }, + { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-IMG-SIZE:size": 1.060306463e+09, + "created": "2014-10-01T12:58:11Z", + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "alternate", + "type": "application/vnd.openstack.image" + } + ], + "metadata": { + "auto_disk_config": "True", + "cache_in_nova": "True", + "com.rackspace__1__build_core": "1", + "com.rackspace__1__build_managed": "1", + "com.rackspace__1__build_rackconnect": "1", + "com.rackspace__1__options": "0", + "com.rackspace__1__platform_target": "PublicCloud", + "com.rackspace__1__release_build_date": "2014-10-01_12-31-03", + "com.rackspace__1__release_id": "1007", + "com.rackspace__1__release_version": "6", + "com.rackspace__1__source": "kickstart", + "com.rackspace__1__visible_core": "1", + "com.rackspace__1__visible_managed": "1", + "com.rackspace__1__visible_rackconnect": "1", + "image_type": "base", + "org.openstack__1__architecture": "x64", + "org.openstack__1__os_distro": "com.ubuntu", + "org.openstack__1__os_version": "14.04", + "os_distro": "ubuntu", + "os_type": "linux", + "vm_mode": "xen" + }, + "minDisk": 20, + "minRam": 512, + "name": "Ubuntu 14.04 LTS (Trusty Tahr)", + "progress": 100, + "status": "ACTIVE", + "updated": "2014-10-01T15:51:44Z" + } + ] +} +` + +// GetOutput is an example response from an /images request. +const GetOutput = ` +{ + "image": { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-IMG-SIZE:size": 1060306463, + "created": "2014-10-01T12:58:11Z", + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": [ + { + "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "self" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark" + }, + { + "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "alternate", + "type": "application/vnd.openstack.image" + } + ], + "metadata": { + "auto_disk_config": "True", + "cache_in_nova": "True", + "com.rackspace__1__build_core": "1", + "com.rackspace__1__build_managed": "1", + "com.rackspace__1__build_rackconnect": "1", + "com.rackspace__1__options": "0", + "com.rackspace__1__platform_target": "PublicCloud", + "com.rackspace__1__release_build_date": "2014-10-01_12-31-03", + "com.rackspace__1__release_id": "1007", + "com.rackspace__1__release_version": "6", + "com.rackspace__1__source": "kickstart", + "com.rackspace__1__visible_core": "1", + "com.rackspace__1__visible_managed": "1", + "com.rackspace__1__visible_rackconnect": "1", + "image_type": "base", + "org.openstack__1__architecture": "x64", + "org.openstack__1__os_distro": "com.ubuntu", + "org.openstack__1__os_version": "14.04", + "os_distro": "ubuntu", + "os_type": "linux", + "vm_mode": "xen" + }, + "minDisk": 20, + "minRam": 512, + "name": "Ubuntu 14.04 LTS (Trusty Tahr)", + "progress": 100, + "status": "ACTIVE", + "updated": "2014-10-01T15:51:44Z" + } +} +` + +// ArchImage is the first Image structure that should be parsed from ListOutput. +var ArchImage = os.Image{ + ID: "30aa010e-080e-4d4b-a7f9-09fc55b07d69", + Name: "Arch 2014.10 (PVHVM)", + Created: "2014-10-01T15:49:02Z", + Updated: "2014-10-01T19:37:58Z", + MinDisk: 20, + MinRAM: 512, + Progress: 100, + Status: "ACTIVE", +} + +// UbuntuImage is the second Image structure that should be parsed from ListOutput and +// the only image that should be extracted from GetOutput. +var UbuntuImage = os.Image{ + ID: "e19a734c-c7e6-443a-830c-242209c4d65d", + Name: "Ubuntu 14.04 LTS (Trusty Tahr)", + Created: "2014-10-01T12:58:11Z", + Updated: "2014-10-01T15:51:44Z", + MinDisk: 20, + MinRAM: 512, + Progress: 100, + Status: "ACTIVE", +} + +// ExpectedImageSlice is the collection of images that should be parsed from ListOutput, +// in order. +var ExpectedImageSlice = []os.Image{ArchImage, UbuntuImage} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/delegate.go new file mode 100644 index 000000000..3e53525dc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/delegate.go @@ -0,0 +1,33 @@ +package keypairs + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of KeyPairs. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// Create requests the creation of a new keypair on the server, or to import a pre-existing +// keypair. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, opts) +} + +// Get returns public data about a previously uploaded KeyPair. +func Get(client *gophercloud.ServiceClient, name string) os.GetResult { + return os.Get(client, name) +} + +// Delete requests the deletion of a previous stored KeyPair from the server. +func Delete(client *gophercloud.ServiceClient, name string) os.DeleteResult { + return os.Delete(client, name) +} + +// ExtractKeyPairs interprets a page of results as a slice of KeyPairs. +func ExtractKeyPairs(page pagination.Page) ([]os.KeyPair, error) { + return os.ExtractKeyPairs(page) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/doc.go new file mode 100644 index 000000000..31713752e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs/doc.go @@ -0,0 +1,3 @@ +// Package keypairs provides information and interaction with the keypair +// API resource for the Rackspace Cloud Servers service. +package keypairs diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/doc.go new file mode 100644 index 000000000..8e5c77382 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/doc.go @@ -0,0 +1,3 @@ +// Package networks provides information and interaction with the network +// API resource for the Rackspace Cloud Servers service. +package networks diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/requests.go new file mode 100644 index 000000000..cebbffd36 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/requests.go @@ -0,0 +1,89 @@ +package networks + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// networks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return NetworkPage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(c, listURL(c), createPage) +} + +// Get retrieves a specific network based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToNetworkCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // REQUIRED. See Network object for more info. + CIDR string + // REQUIRED. See Network object for more info. + Label string +} + +// ToNetworkCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) { + n := make(map[string]interface{}) + + if opts.CIDR == "" { + return nil, errors.New("Required field CIDR not set.") + } + if opts.Label == "" { + return nil, errors.New("Required field Label not set.") + } + + n["label"] = opts.Label + n["cidr"] = opts.CIDR + return map[string]interface{}{"network": n}, nil +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. This operation does not actually require a request body, i.e. the +// CreateOpts struct argument can be empty. +// +// The tenant ID that is contained in the URI is the tenant that creates the +// network. An admin user, however, has the option of specifying another tenant +// ID in the CreateOpts struct. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToNetworkCreateMap() + if err != nil { + res.Err = err + return res + } + + // Send request to API + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201, 202}, + }) + return res +} + +// Delete accepts a unique ID and deletes the network associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, networkID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/results.go new file mode 100644 index 000000000..eb6a76c00 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/results.go @@ -0,0 +1,81 @@ +package networks + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a network resource. +func (r commonResult) Extract() (*Network, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + Network *Network `json:"network"` + } + + err := mapstructure.Decode(r.Body, &res) + + return res.Network, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Network represents, well, a network. +type Network struct { + // UUID for the network + ID string `mapstructure:"id" json:"id"` + + // Human-readable name for the network. Might not be unique. + Label string `mapstructure:"label" json:"label"` + + // Classless Inter-Domain Routing + CIDR string `mapstructure:"cidr" json:"cidr"` +} + +// NetworkPage is the page returned by a pager when traversing over a +// collection of networks. +type NetworkPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if the NetworkPage contains no Networks. +func (r NetworkPage) IsEmpty() (bool, error) { + networks, err := ExtractNetworks(r) + if err != nil { + return true, err + } + return len(networks) == 0, nil +} + +// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct, +// and extracts the elements into a slice of Network structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractNetworks(page pagination.Page) ([]Network, error) { + var resp struct { + Networks []Network `mapstructure:"networks" json:"networks"` + } + + err := mapstructure.Decode(page.(NetworkPage).Body, &resp) + + return resp.Networks, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/urls.go new file mode 100644 index 000000000..19a21aa90 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/networks/urls.go @@ -0,0 +1,27 @@ +package networks + +import "github.com/rackspace/gophercloud" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("os-networksv2", id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("os-networksv2") +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/delegate.go new file mode 100644 index 000000000..7810d156a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/delegate.go @@ -0,0 +1,116 @@ +package servers + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/compute/v2/servers" + "github.com/rackspace/gophercloud/pagination" +) + +// List makes a request against the API to list servers accessible to you. +func List(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(client, opts) +} + +// Create requests a server to be provisioned to the user in the current tenant. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, opts) +} + +// Update requests an existing server to be updated with the supplied options. +func Update(client *gophercloud.ServiceClient, id string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(client, id, opts) +} + +// Delete requests that a server previously provisioned be removed from your account. +func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(client, id) +} + +// Get requests details on a single server, by ID. +func Get(client *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(client, id) +} + +// ChangeAdminPassword alters the administrator or root password for a specified server. +func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) os.ActionResult { + return os.ChangeAdminPassword(client, id, newPassword) +} + +// Reboot requests that a given server reboot. Two methods exist for rebooting a server: +// +// os.HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the +// machine, or if a VM, terminating it at the hypervisor level. It's done. Caput. Full stop. Then, +// after a brief wait, power is restored or the VM instance restarted. +// +// os.SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures. E.g., in +// Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine. +func Reboot(client *gophercloud.ServiceClient, id string, how os.RebootMethod) os.ActionResult { + return os.Reboot(client, id, how) +} + +// Rebuild will reprovision the server according to the configuration options provided in the +// RebuildOpts struct. +func Rebuild(client *gophercloud.ServiceClient, id string, opts os.RebuildOptsBuilder) os.RebuildResult { + return os.Rebuild(client, id, opts) +} + +// Resize instructs the provider to change the flavor of the server. +// Note that this implies rebuilding it. +// Unfortunately, one cannot pass rebuild parameters to the resize function. +// When the resize completes, the server will be in RESIZE_VERIFY state. +// While in this state, you can explore the use of the new server's configuration. +// If you like it, call ConfirmResize() to commit the resize permanently. +// Otherwise, call RevertResize() to restore the old configuration. +func Resize(client *gophercloud.ServiceClient, id string, opts os.ResizeOptsBuilder) os.ActionResult { + return os.Resize(client, id, opts) +} + +// ConfirmResize confirms a previous resize operation on a server. +// See Resize() for more details. +func ConfirmResize(client *gophercloud.ServiceClient, id string) os.ActionResult { + return os.ConfirmResize(client, id) +} + +// WaitForStatus will continually poll a server until it successfully transitions to a specified +// status. It will do this for at most the number of seconds specified. +func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error { + return os.WaitForStatus(c, id, status, secs) +} + +// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities. +func ExtractServers(page pagination.Page) ([]os.Server, error) { + return os.ExtractServers(page) +} + +// ListAddresses makes a request against the API to list the servers IP addresses. +func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager { + return os.ListAddresses(client, id) +} + +// ExtractAddresses interprets the results of a single page from a ListAddresses() call, producing a map of Address slices. +func ExtractAddresses(page pagination.Page) (map[string][]os.Address, error) { + return os.ExtractAddresses(page) +} + +// ListAddressesByNetwork makes a request against the API to list the servers IP addresses +// for the given network. +func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager { + return os.ListAddressesByNetwork(client, id, network) +} + +// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call, producing a map of Address slices. +func ExtractNetworkAddresses(page pagination.Page) ([]os.Address, error) { + return os.ExtractNetworkAddresses(page) +} + +// Metadata requests all the metadata for the given server ID. +func Metadata(client *gophercloud.ServiceClient, id string) os.GetMetadataResult { + return os.Metadata(client, id) +} + +// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID. +// This operation does not affect already-existing metadata that is not specified +// by opts. +func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts os.UpdateMetadataOptsBuilder) os.UpdateMetadataResult { + return os.UpdateMetadata(client, id, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/doc.go new file mode 100644 index 000000000..c9f77f694 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/doc.go @@ -0,0 +1,3 @@ +// Package servers provides information and interaction with the server +// API resource for the Rackspace Cloud Servers service. +package servers diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/fixtures.go new file mode 100644 index 000000000..75cccd041 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/fixtures.go @@ -0,0 +1,574 @@ +// +build fixtures + +package servers + +import ( + os "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// ListOutput is the recorded output of a Rackspace servers.List request. +const ListOutput = ` +{ + "servers": [ + { + "OS-DCF:diskConfig": "MANUAL", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "accessIPv4": "1.2.3.4", + "accessIPv6": "1111:4822:7818:121:2000:9b5e:7438:a2d0", + "addresses": { + "private": [ + { + "addr": "10.208.230.113", + "version": 4 + } + ], + "public": [ + { + "addr": "2001:4800:7818:101:2000:9b5e:7428:a2d0", + "version": 6 + }, + { + "addr": "104.130.131.164", + "version": 4 + } + ] + }, + "created": "2014-09-23T12:34:58Z", + "flavor": { + "id": "performance1-8", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-8", + "rel": "bookmark" + } + ] + }, + "hostId": "e8951a524bc465b0898aeac7674da6fe1495e253ae1ea17ddb2c2475", + "id": "59818cee-bc8c-44eb-8073-673ee65105f7", + "image": { + "id": "255df5fb-e3d4-45a3-9a07-c976debf7c14", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/255df5fb-e3d4-45a3-9a07-c976debf7c14", + "rel": "bookmark" + } + ] + }, + "key_name": "mykey", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7", + "rel": "self" + }, + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7", + "rel": "bookmark" + } + ], + "metadata": {}, + "name": "devstack", + "progress": 100, + "status": "ACTIVE", + "tenant_id": "111111", + "updated": "2014-09-23T12:38:19Z", + "user_id": "14ae7bb21d81422694655f3cc30f2930" + }, + { + "OS-DCF:diskConfig": "MANUAL", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "accessIPv4": "1.1.2.3", + "accessIPv6": "2222:4444:7817:101:be76:4eff:f0e5:9e02", + "addresses": { + "private": [ + { + "addr": "10.10.20.30", + "version": 4 + } + ], + "public": [ + { + "addr": "1.1.2.3", + "version": 4 + }, + { + "addr": "2222:4444:7817:101:be76:4eff:f0e5:9e02", + "version": 6 + } + ] + }, + "created": "2014-07-21T19:32:55Z", + "flavor": { + "id": "performance1-2", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-2", + "rel": "bookmark" + } + ] + }, + "hostId": "f859679906d6b1a38c1bd516b78f4dcc7d5fcf012578fa3ce460716c", + "id": "25f1c7f5-e00a-4715-b354-16e24b2f4630", + "image": { + "id": "bb02b1a3-bc77-4d17-ab5b-421d89850fca", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/bb02b1a3-bc77-4d17-ab5b-421d89850fca", + "rel": "bookmark" + } + ] + }, + "key_name": "otherkey", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630", + "rel": "self" + }, + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630", + "rel": "bookmark" + } + ], + "metadata": {}, + "name": "peril-dfw", + "progress": 100, + "status": "ACTIVE", + "tenant_id": "111111", + "updated": "2014-07-21T19:34:24Z", + "user_id": "14ae7bb21d81422694655f3cc30f2930" + } + ] +} +` + +// GetOutput is the recorded output of a Rackspace servers.Get request. +const GetOutput = ` +{ + "server": { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "accessIPv4": "1.2.4.8", + "accessIPv6": "2001:4800:6666:105:2a0f:c056:f594:7777", + "addresses": { + "private": [ + { + "addr": "10.20.40.80", + "version": 4 + } + ], + "public": [ + { + "addr": "1.2.4.8", + "version": 4 + }, + { + "addr": "2001:4800:6666:105:2a0f:c056:f594:7777", + "version": 6 + } + ] + }, + "created": "2014-10-21T14:42:16Z", + "flavor": { + "id": "performance1-1", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1", + "rel": "bookmark" + } + ] + }, + "hostId": "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7", + "id": "8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "image": { + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "self" + }, + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "bookmark" + } + ], + "metadata": {}, + "name": "Gophercloud-pxpGGuey", + "progress": 100, + "status": "ACTIVE", + "tenant_id": "111111", + "updated": "2014-10-21T14:42:57Z", + "user_id": "14ae7bb21d81423694655f4dd30f2930" + } +} +` + +// UpdateOutput is the recorded output of a Rackspace servers.Update request. +const UpdateOutput = ` +{ + "server": { + "OS-DCF:diskConfig": "AUTO", + "OS-EXT-STS:power_state": 1, + "OS-EXT-STS:task_state": null, + "OS-EXT-STS:vm_state": "active", + "accessIPv4": "1.2.4.8", + "accessIPv6": "2001:4800:6666:105:2a0f:c056:f594:7777", + "addresses": { + "private": [ + { + "addr": "10.20.40.80", + "version": 4 + } + ], + "public": [ + { + "addr": "1.2.4.8", + "version": 4 + }, + { + "addr": "2001:4800:6666:105:2a0f:c056:f594:7777", + "version": 6 + } + ] + }, + "created": "2014-10-21T14:42:16Z", + "flavor": { + "id": "performance1-1", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1", + "rel": "bookmark" + } + ] + }, + "hostId": "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7", + "id": "8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "image": { + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "self" + }, + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "bookmark" + } + ], + "metadata": {}, + "name": "test-server-updated", + "progress": 100, + "status": "ACTIVE", + "tenant_id": "111111", + "updated": "2014-10-21T14:42:57Z", + "user_id": "14ae7bb21d81423694655f4dd30f2930" + } +} +` + +// CreateOutput contains a sample of Rackspace's response to a Create call. +const CreateOutput = ` +{ + "server": { + "OS-DCF:diskConfig": "AUTO", + "adminPass": "v7tADqbE5pr9", + "id": "bb63327b-6a2f-34bc-b0ef-4b6d97ea637e", + "links": [ + { + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/bb63327b-6a2f-34bc-b0ef-4b6d97ea637e", + "rel": "self" + }, + { + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/bb63327b-6a2f-34bc-b0ef-4b6d97ea637e", + "rel": "bookmark" + } + ] + } +} +` + +// DevstackServer is the expected first result from parsing ListOutput. +var DevstackServer = os.Server{ + ID: "59818cee-bc8c-44eb-8073-673ee65105f7", + Name: "devstack", + TenantID: "111111", + UserID: "14ae7bb21d81422694655f3cc30f2930", + HostID: "e8951a524bc465b0898aeac7674da6fe1495e253ae1ea17ddb2c2475", + Updated: "2014-09-23T12:38:19Z", + Created: "2014-09-23T12:34:58Z", + AccessIPv4: "1.2.3.4", + AccessIPv6: "1111:4822:7818:121:2000:9b5e:7438:a2d0", + Progress: 100, + Status: "ACTIVE", + Image: map[string]interface{}{ + "id": "255df5fb-e3d4-45a3-9a07-c976debf7c14", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/255df5fb-e3d4-45a3-9a07-c976debf7c14", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "performance1-8", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-8", + "rel": "bookmark", + }, + }, + }, + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "addr": "10.20.30.40", + "version": float64(4.0), + }, + }, + "public": []interface{}{ + map[string]interface{}{ + "addr": "1111:4822:7818:121:2000:9b5e:7438:a2d0", + "version": float64(6.0), + }, + map[string]interface{}{ + "addr": "1.2.3.4", + "version": float64(4.0), + }, + }, + }, + Metadata: map[string]interface{}{}, + Links: []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59918cee-bd9d-44eb-8173-673ee75105f7", + "rel": "self", + }, + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7", + "rel": "bookmark", + }, + }, + KeyName: "mykey", + AdminPass: "", +} + +// PerilServer is the expected second result from parsing ListOutput. +var PerilServer = os.Server{ + ID: "25f1c7f5-e00a-4715-b354-16e24b2f4630", + Name: "peril-dfw", + TenantID: "111111", + UserID: "14ae7bb21d81422694655f3cc30f2930", + HostID: "f859679906d6b1a38c1bd516b78f4dcc7d5fcf012578fa3ce460716c", + Updated: "2014-07-21T19:34:24Z", + Created: "2014-07-21T19:32:55Z", + AccessIPv4: "1.1.2.3", + AccessIPv6: "2222:4444:7817:101:be76:4eff:f0e5:9e02", + Progress: 100, + Status: "ACTIVE", + Image: map[string]interface{}{ + "id": "bb02b1a3-bc77-4d17-ab5b-421d89850fca", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/bb02b1a3-bc77-4d17-ab5b-421d89850fca", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "performance1-2", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-2", + "rel": "bookmark", + }, + }, + }, + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "addr": "10.10.20.30", + "version": float64(4.0), + }, + }, + "public": []interface{}{ + map[string]interface{}{ + "addr": "2222:4444:7817:101:be76:4eff:f0e5:9e02", + "version": float64(6.0), + }, + map[string]interface{}{ + "addr": "1.1.2.3", + "version": float64(4.0), + }, + }, + }, + Metadata: map[string]interface{}{}, + Links: []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630", + "rel": "self", + }, + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630", + "rel": "bookmark", + }, + }, + KeyName: "otherkey", + AdminPass: "", +} + +// GophercloudServer is the expected result from parsing GetOutput. +var GophercloudServer = os.Server{ + ID: "8c65cb68-0681-4c30-bc88-6b83a8a26aee", + Name: "Gophercloud-pxpGGuey", + TenantID: "111111", + UserID: "14ae7bb21d81423694655f4dd30f2930", + HostID: "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7", + Updated: "2014-10-21T14:42:57Z", + Created: "2014-10-21T14:42:16Z", + AccessIPv4: "1.2.4.8", + AccessIPv6: "2001:4800:6666:105:2a0f:c056:f594:7777", + Progress: 100, + Status: "ACTIVE", + Image: map[string]interface{}{ + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "performance1-1", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1", + "rel": "bookmark", + }, + }, + }, + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "addr": "10.20.40.80", + "version": float64(4.0), + }, + }, + "public": []interface{}{ + map[string]interface{}{ + "addr": "2001:4800:6666:105:2a0f:c056:f594:7777", + "version": float64(6.0), + }, + map[string]interface{}{ + "addr": "1.2.4.8", + "version": float64(4.0), + }, + }, + }, + Metadata: map[string]interface{}{}, + Links: []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "self", + }, + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "bookmark", + }, + }, + KeyName: "", + AdminPass: "", +} + +// GophercloudUpdatedServer is the expected result from parsing UpdateOutput. +var GophercloudUpdatedServer = os.Server{ + ID: "8c65cb68-0681-4c30-bc88-6b83a8a26aee", + Name: "test-server-updated", + TenantID: "111111", + UserID: "14ae7bb21d81423694655f4dd30f2930", + HostID: "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7", + Updated: "2014-10-21T14:42:57Z", + Created: "2014-10-21T14:42:16Z", + AccessIPv4: "1.2.4.8", + AccessIPv6: "2001:4800:6666:105:2a0f:c056:f594:7777", + Progress: 100, + Status: "ACTIVE", + Image: map[string]interface{}{ + "id": "e19a734c-c7e6-443a-830c-242209c4d65d", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d", + "rel": "bookmark", + }, + }, + }, + Flavor: map[string]interface{}{ + "id": "performance1-1", + "links": []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1", + "rel": "bookmark", + }, + }, + }, + Addresses: map[string]interface{}{ + "private": []interface{}{ + map[string]interface{}{ + "addr": "10.20.40.80", + "version": float64(4.0), + }, + }, + "public": []interface{}{ + map[string]interface{}{ + "addr": "2001:4800:6666:105:2a0f:c056:f594:7777", + "version": float64(6.0), + }, + map[string]interface{}{ + "addr": "1.2.4.8", + "version": float64(4.0), + }, + }, + }, + Metadata: map[string]interface{}{}, + Links: []interface{}{ + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "self", + }, + map[string]interface{}{ + "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", + "rel": "bookmark", + }, + }, + KeyName: "", + AdminPass: "", +} + +// CreatedServer is the partial Server struct that can be parsed from CreateOutput. +var CreatedServer = os.Server{ + ID: "bb63327b-6a2f-34bc-b0ef-4b6d97ea637e", + AdminPass: "v7tADqbE5pr9", + Links: []interface{}{}, +} + +// ExpectedServerSlice is the collection of servers, in order, that should be parsed from ListOutput. +var ExpectedServerSlice = []os.Server{DevstackServer, PerilServer} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/requests.go new file mode 100644 index 000000000..d4472a080 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/servers/requests.go @@ -0,0 +1,178 @@ +package servers + +import ( + "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume" + "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig" + os "github.com/rackspace/gophercloud/openstack/compute/v2/servers" +) + +// CreateOpts specifies all of the options that Rackspace accepts in its Create request, including +// the union of all extensions that Rackspace supports. +type CreateOpts struct { + // Name [required] is the name to assign to the newly launched server. + Name string + + // ImageRef [optional; required if ImageName is not provided] is the ID or full + // URL to the image that contains the server's OS and initial state. + // Also optional if using the boot-from-volume extension. + ImageRef string + + // ImageName [optional; required if ImageRef is not provided] is the name of the + // image that contains the server's OS and initial state. + // Also optional if using the boot-from-volume extension. + ImageName string + + // FlavorRef [optional; required if FlavorName is not provided] is the ID or + // full URL to the flavor that describes the server's specs. + FlavorRef string + + // FlavorName [optional; required if FlavorRef is not provided] is the name of + // the flavor that describes the server's specs. + FlavorName string + + // SecurityGroups [optional] lists the names of the security groups to which this server should belong. + SecurityGroups []string + + // UserData [optional] contains configuration information or scripts to use upon launch. + // Create will base64-encode it for you. + UserData []byte + + // AvailabilityZone [optional] in which to launch the server. + AvailabilityZone string + + // Networks [optional] dictates how this server will be attached to available networks. + // By default, the server will be attached to all isolated networks for the tenant. + Networks []os.Network + + // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server. + Metadata map[string]string + + // Personality [optional] includes files to inject into the server at launch. + // Create will base64-encode file contents for you. + Personality os.Personality + + // ConfigDrive [optional] enables metadata injection through a configuration drive. + ConfigDrive bool + + // AdminPass [optional] sets the root user password. If not set, a randomly-generated + // password will be created and returned in the response. + AdminPass string + + // Rackspace-specific extensions begin here. + + // KeyPair [optional] specifies the name of the SSH KeyPair to be injected into the newly launched + // server. See the "keypairs" extension in OpenStack compute v2. + KeyPair string + + // DiskConfig [optional] controls how the created server's disk is partitioned. See the "diskconfig" + // extension in OpenStack compute v2. + DiskConfig diskconfig.DiskConfig + + // BlockDevice [optional] will create the server from a volume, which is created from an image, + // a snapshot, or another volume. + BlockDevice []bootfromvolume.BlockDevice +} + +// ToServerCreateMap constructs a request body using all of the OpenStack extensions that are +// active on Rackspace. +func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) { + base := os.CreateOpts{ + Name: opts.Name, + ImageRef: opts.ImageRef, + ImageName: opts.ImageName, + FlavorRef: opts.FlavorRef, + FlavorName: opts.FlavorName, + SecurityGroups: opts.SecurityGroups, + UserData: opts.UserData, + AvailabilityZone: opts.AvailabilityZone, + Networks: opts.Networks, + Metadata: opts.Metadata, + Personality: opts.Personality, + ConfigDrive: opts.ConfigDrive, + AdminPass: opts.AdminPass, + } + + drive := diskconfig.CreateOptsExt{ + CreateOptsBuilder: base, + DiskConfig: opts.DiskConfig, + } + + res, err := drive.ToServerCreateMap() + if err != nil { + return nil, err + } + + if len(opts.BlockDevice) != 0 { + bfv := bootfromvolume.CreateOptsExt{ + CreateOptsBuilder: drive, + BlockDevice: opts.BlockDevice, + } + + res, err = bfv.ToServerCreateMap() + if err != nil { + return nil, err + } + } + + // key_name doesn't actually come from the extension (or at least isn't documented there) so + // we need to add it manually. + serverMap := res["server"].(map[string]interface{}) + if opts.KeyPair != "" { + serverMap["key_name"] = opts.KeyPair + } + + return res, nil +} + +// RebuildOpts represents all of the configuration options used in a server rebuild operation that +// are supported by Rackspace. +type RebuildOpts struct { + // Required. The ID of the image you want your server to be provisioned on + ImageID string + + // Name to set the server to + Name string + + // Required. The server's admin password + AdminPass string + + // AccessIPv4 [optional] provides a new IPv4 address for the instance. + AccessIPv4 string + + // AccessIPv6 [optional] provides a new IPv6 address for the instance. + AccessIPv6 string + + // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server. + Metadata map[string]string + + // Personality [optional] includes files to inject into the server at launch. + // Rebuild will base64-encode file contents for you. + Personality os.Personality + + // Rackspace-specific stuff begins here. + + // DiskConfig [optional] controls how the created server's disk is partitioned. See the "diskconfig" + // extension in OpenStack compute v2. + DiskConfig diskconfig.DiskConfig +} + +// ToServerRebuildMap constructs a request body using all of the OpenStack extensions that are +// active on Rackspace. +func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) { + base := os.RebuildOpts{ + ImageID: opts.ImageID, + Name: opts.Name, + AdminPass: opts.AdminPass, + AccessIPv4: opts.AccessIPv4, + AccessIPv6: opts.AccessIPv6, + Metadata: opts.Metadata, + Personality: opts.Personality, + } + + drive := diskconfig.RebuildOptsExt{ + RebuildOptsBuilder: base, + DiskConfig: opts.DiskConfig, + } + + return drive.ToServerRebuildMap() +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/requests.go new file mode 100644 index 000000000..1ff7c5ae5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/requests.go @@ -0,0 +1,45 @@ +package virtualinterfaces + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// networks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, instanceID string) pagination.Pager { + createPage := func(r pagination.PageResult) pagination.Page { + return VirtualInterfacePage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(c, listURL(c, instanceID), createPage) +} + +// Create creates a new virtual interface for a network and attaches the network +// to the server instance. +func Create(c *gophercloud.ServiceClient, instanceID, networkID string) CreateResult { + var res CreateResult + + reqBody := map[string]map[string]string{ + "virtual_interface": { + "network_id": networkID, + }, + } + + // Send request to API + _, res.Err = c.Post(createURL(c, instanceID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201, 202}, + }) + return res +} + +// Delete deletes the interface with interfaceID attached to the instance with +// instanceID. +func Delete(c *gophercloud.ServiceClient, instanceID, interfaceID string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, instanceID, interfaceID), &gophercloud.RequestOpts{ + OkCodes: []int{200, 204}, + }) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/results.go new file mode 100644 index 000000000..26fa7f31c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/results.go @@ -0,0 +1,81 @@ +package virtualinterfaces + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a network resource. +func (r commonResult) Extract() (*VirtualInterface, error) { + if r.Err != nil { + return nil, r.Err + } + + var res struct { + VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"` + } + + err := mapstructure.Decode(r.Body, &res) + + return &res.VirtualInterfaces[0], err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// IPAddress represents a vitual address attached to a VirtualInterface. +type IPAddress struct { + Address string `mapstructure:"address" json:"address"` + NetworkID string `mapstructure:"network_id" json:"network_id"` + NetworkLabel string `mapstructure:"network_label" json:"network_label"` +} + +// VirtualInterface represents a virtual interface. +type VirtualInterface struct { + // UUID for the virtual interface + ID string `mapstructure:"id" json:"id"` + + MACAddress string `mapstructure:"mac_address" json:"mac_address"` + + IPAddresses []IPAddress `mapstructure:"ip_addresses" json:"ip_addresses"` +} + +// VirtualInterfacePage is the page returned by a pager when traversing over a +// collection of virtual interfaces. +type VirtualInterfacePage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if the NetworkPage contains no Networks. +func (r VirtualInterfacePage) IsEmpty() (bool, error) { + networks, err := ExtractVirtualInterfaces(r) + if err != nil { + return true, err + } + return len(networks) == 0, nil +} + +// ExtractVirtualInterfaces accepts a Page struct, specifically a VirtualInterfacePage struct, +// and extracts the elements into a slice of VirtualInterface structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractVirtualInterfaces(page pagination.Page) ([]VirtualInterface, error) { + var resp struct { + VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"` + } + + err := mapstructure.Decode(page.(VirtualInterfacePage).Body, &resp) + + return resp.VirtualInterfaces, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/urls.go new file mode 100644 index 000000000..9e5693e84 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces/urls.go @@ -0,0 +1,15 @@ +package virtualinterfaces + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient, instanceID string) string { + return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2") +} + +func createURL(c *gophercloud.ServiceClient, instanceID string) string { + return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2") +} + +func deleteURL(c *gophercloud.ServiceClient, instanceID, interfaceID string) string { + return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2", interfaceID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/delegate.go new file mode 100644 index 000000000..c6003e0e5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/delegate.go @@ -0,0 +1,27 @@ +package volumeattach + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager that allows you to iterate over a collection of VolumeAttachments. +func List(client *gophercloud.ServiceClient, serverID string) pagination.Pager { + return os.List(client, serverID) +} + +// Create requests the creation of a new volume attachment on the server +func Create(client *gophercloud.ServiceClient, serverID string, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, serverID, opts) +} + +// Get returns public data about a previously created VolumeAttachment. +func Get(client *gophercloud.ServiceClient, serverID, aID string) os.GetResult { + return os.Get(client, serverID, aID) +} + +// Delete requests the deletion of a previous stored VolumeAttachment from the server. +func Delete(client *gophercloud.ServiceClient, serverID, aID string) os.DeleteResult { + return os.Delete(client, serverID, aID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/doc.go new file mode 100644 index 000000000..2164908e3 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach/doc.go @@ -0,0 +1,3 @@ +// Package volumeattach provides the ability to attach and detach volume +// to instances to Rackspace servers +package volumeattach diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/doc.go new file mode 100644 index 000000000..664eeadb8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/doc.go @@ -0,0 +1,6 @@ +// Package backups provides information and interaction with the backup API +// resource in the Rackspace Database service. +// +// A backup is a copy of a database instance that can be used to restore it to +// some defined point in history. +package backups diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/fixtures.go new file mode 100644 index 000000000..45c2376d6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/fixtures.go @@ -0,0 +1,66 @@ +package backups + +import "time" + +var ( + timestamp = "2015-11-12T14:22:42Z" + timeVal, _ = time.Parse(time.RFC3339, timestamp) +) + +var getResp = ` +{ + "backup": { + "created": "` + timestamp + `", + "description": "My Backup", + "id": "61f12fef-edb1-4561-8122-e7c00ef26a82", + "instance_id": "d4603f69-ec7e-4e9b-803f-600b9205576f", + "locationRef": null, + "name": "snapshot", + "parent_id": null, + "size": 100, + "status": "NEW", + "datastore": { + "version": "5.1", + "type": "MySQL", + "version_id": "20000000-0000-0000-0000-000000000002" + }, + "updated": "` + timestamp + `" + } +} +` + +var createReq = ` +{ + "backup": { + "description": "My Backup", + "instance": "d4603f69-ec7e-4e9b-803f-600b9205576f", + "name": "snapshot" + } +} +` + +var createResp = getResp + +var listResp = ` +{ + "backups": [ + { + "status": "COMPLETED", + "updated": "` + timestamp + `", + "description": "Backup from Restored Instance", + "datastore": { + "version": "5.1", + "type": "MySQL", + "version_id": "20000000-0000-0000-0000-000000000002" + }, + "id": "87972694-4be2-40f5-83f8-501656e0032a", + "size": 0.141026, + "name": "restored_backup", + "created": "` + timestamp + `", + "instance_id": "29af2cd9-0674-48ab-b87a-b160f00208e6", + "parent_id": null, + "locationRef": "http://localhost/path/to/backup" + } + ] +} +` diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/requests.go new file mode 100644 index 000000000..9170d7865 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/requests.go @@ -0,0 +1,138 @@ +package backups + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CreateOptsBuilder is the top-level interface for creating JSON maps. +type CreateOptsBuilder interface { + ToBackupCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is responsible for configuring newly provisioned backups. +type CreateOpts struct { + // [REQUIRED] The name of the backup. The only restriction is the name must + // be less than 64 characters long. + Name string + + // [REQUIRED] The ID of the instance being backed up. + InstanceID string + + // [OPTIONAL] A human-readable explanation of the backup. + Description string +} + +// ToBackupCreateMap will create a JSON map for the Create operation. +func (opts CreateOpts) ToBackupCreateMap() (map[string]interface{}, error) { + if opts.Name == "" { + return nil, errors.New("Name is a required field") + } + if opts.InstanceID == "" { + return nil, errors.New("InstanceID is a required field") + } + + backup := map[string]interface{}{ + "name": opts.Name, + "instance": opts.InstanceID, + } + + if opts.Description != "" { + backup["description"] = opts.Description + } + + return map[string]interface{}{"backup": backup}, nil +} + +// Create asynchronously creates a new backup for a specified database instance. +// During the backup process, write access on MyISAM databases will be +// temporarily disabled; innoDB databases will be unaffected. During this time, +// you will not be able to add or delete databases or users; nor delete, stop +// or reboot the instance itself. Only one backup is permitted at once. +// +// Backups are not deleted when database instances are deleted; you must +// manually delete any backups created using Delete(). Backups are saved to your +// Cloud Files account in a new container called z_CLOUDDB_BACKUPS. It is +// strongly recommended you do not alter this container or its contents; usual +// storage costs apply. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToBackupCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{ + JSONBody: &reqBody, + JSONResponse: &res.Body, + OkCodes: []int{202}, + }) + + return res +} + +// ListOptsBuilder is the top-level interface for creating query strings. +type ListOptsBuilder interface { + ToBackupListQuery() (string, error) +} + +// ListOpts allows you to refine a list search by certain parameters. +type ListOpts struct { + // The type of datastore by which to filter. + Datastore string `q:"datastore"` +} + +// ToBackupListQuery converts a ListOpts struct into a query string. +func (opts ListOpts) ToBackupListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List will list all the saved backups for all database instances. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := baseURL(client) + + if opts != nil { + query, err := opts.ToBackupListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + pageFn := func(r pagination.PageResult) pagination.Page { + return BackupPage{pagination.SinglePageBase(r)} + } + + return pagination.NewPager(client, url, pageFn) +} + +// Get will retrieve details for a particular backup based on its unique ID. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + + _, res.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// Delete will permanently delete a backup. +func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + + _, res.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/results.go new file mode 100644 index 000000000..04faf3227 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/results.go @@ -0,0 +1,149 @@ +package backups + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/pagination" +) + +// Status represents the various states a Backup can be in. +type Status string + +// Enum types for the status. +const ( + StatusNew Status = "NEW" + StatusBuilding Status = "BUILDING" + StatusCompleted Status = "COMPLETED" + StatusFailed Status = "FAILED" + StatusDeleteFailed Status = "DELETE_FAILED" +) + +// Backup represents a Backup API resource. +type Backup struct { + Description string + ID string + InstanceID string `json:"instance_id" mapstructure:"instance_id"` + LocationRef string + Name string + ParentID string `json:"parent_id" mapstructure:"parent_id"` + Size float64 + Status Status + Created time.Time `mapstructure:"-"` + Updated time.Time `mapstructure:"-"` + Datastore datastores.DatastorePartial +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will retrieve a Backup struct from an operation's result. +func (r commonResult) Extract() (*Backup, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Backup Backup `mapstructure:"backup"` + } + + err := mapstructure.Decode(r.Body, &response) + val := r.Body.(map[string]interface{})["backup"].(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Backup, err + } + response.Backup.Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Backup, err + } + response.Backup.Updated = updatedTime + } + + return &response.Backup, err +} + +// BackupPage represents a page of backups. +type BackupPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an BackupPage struct is empty. +func (r BackupPage) IsEmpty() (bool, error) { + is, err := ExtractBackups(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractBackups will retrieve a slice of Backup structs from a paginated collection. +func ExtractBackups(page pagination.Page) ([]Backup, error) { + casted := page.(BackupPage).Body + + var resp struct { + Backups []Backup `mapstructure:"backups" json:"backups"` + } + + if err := mapstructure.Decode(casted, &resp); err != nil { + return nil, err + } + + var vals []interface{} + switch casted.(type) { + case map[string]interface{}: + vals = casted.(map[string]interface{})["backups"].([]interface{}) + case map[string][]interface{}: + vals = casted.(map[string][]interface{})["backups"] + default: + return resp.Backups, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, v := range vals { + val := v.(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Backups, err + } + resp.Backups[i].Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Backups, err + } + resp.Backups[i].Updated = updatedTime + } + } + + return resp.Backups, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/urls.go new file mode 100644 index 000000000..553444e88 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/backups/urls.go @@ -0,0 +1,11 @@ +package backups + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("backups") +} + +func resourceURL(c *gophercloud.ServiceClient, backupID string) string { + return c.ServiceURL("backups", backupID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/delegate.go new file mode 100644 index 000000000..d8cb48ac5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/delegate.go @@ -0,0 +1,79 @@ +package configurations + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/configurations" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all of the available configurations. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// Create will create a new configuration group. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, opts) +} + +// Get will retrieve the details for a specified configuration group. +func Get(client *gophercloud.ServiceClient, configID string) os.GetResult { + return os.Get(client, configID) +} + +// Update will modify an existing configuration group by performing a merge +// between new and existing values. If the key already exists, the new value +// will overwrite. All other keys will remain unaffected. +func Update(client *gophercloud.ServiceClient, configID string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(client, configID, opts) +} + +// Replace will modify an existing configuration group by overwriting the +// entire parameter group with the new values provided. Any existing keys not +// included in UpdateOptsBuilder will be deleted. +func Replace(client *gophercloud.ServiceClient, configID string, opts os.UpdateOptsBuilder) os.ReplaceResult { + return os.Replace(client, configID, opts) +} + +// Delete will permanently delete a configuration group. Please note that +// config groups cannot be deleted whilst still attached to running instances - +// you must detach and then delete them. +func Delete(client *gophercloud.ServiceClient, configID string) os.DeleteResult { + return os.Delete(client, configID) +} + +// ListInstances will list all the instances associated with a particular +// configuration group. +func ListInstances(client *gophercloud.ServiceClient, configID string) pagination.Pager { + return os.ListInstances(client, configID) +} + +// ListDatastoreParams will list all the available and supported parameters +// that can be used for a particular datastore ID and a particular version. +// For example, if you are wondering how you can configure a MySQL 5.6 instance, +// you can use this operation (you will need to retrieve the MySQL datastore ID +// by using the datastores API). +func ListDatastoreParams(client *gophercloud.ServiceClient, datastoreID, versionID string) pagination.Pager { + return os.ListDatastoreParams(client, datastoreID, versionID) +} + +// GetDatastoreParam will retrieve information about a specific configuration +// parameter. For example, you can use this operation to understand more about +// "innodb_file_per_table" configuration param for MySQL datastores. You will +// need the param's ID first, which can be attained by using the ListDatastoreParams +// operation. +func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) os.ParamResult { + return os.GetDatastoreParam(client, datastoreID, versionID, paramID) +} + +// ListGlobalParams is similar to ListDatastoreParams but does not require a +// DatastoreID. +func ListGlobalParams(client *gophercloud.ServiceClient, versionID string) pagination.Pager { + return os.ListGlobalParams(client, versionID) +} + +// GetGlobalParam is similar to GetDatastoreParam but does not require a +// DatastoreID. +func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) os.ParamResult { + return os.GetGlobalParam(client, versionID, paramID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/doc.go new file mode 100644 index 000000000..48c51d60d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/doc.go @@ -0,0 +1 @@ +package configurations diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/fixtures.go new file mode 100644 index 000000000..d8a2233bc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/configurations/fixtures.go @@ -0,0 +1,159 @@ +package configurations + +import ( + "fmt" + "time" + + os "github.com/rackspace/gophercloud/openstack/db/v1/configurations" +) + +var ( + timestamp = "2015-11-12T14:22:42Z" + timeVal, _ = time.Parse(time.RFC3339, timestamp) +) + +var singleConfigJSON = ` +{ + "created": "` + timestamp + `", + "datastore_name": "mysql", + "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb", + "datastore_version_name": "5.6", + "description": "example_description", + "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + "name": "example-configuration-name", + "updated": "` + timestamp + `" +} +` + +var singleConfigWithValuesJSON = ` +{ + "created": "` + timestamp + `", + "datastore_name": "mysql", + "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb", + "datastore_version_name": "5.6", + "description": "example description", + "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + "instance_count": 0, + "name": "example-configuration-name", + "updated": "` + timestamp + `", + "values": { + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120 + } +} +` + +var ( + listConfigsJSON = fmt.Sprintf(`{"configurations": [%s]}`, singleConfigJSON) + getConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigJSON) + createConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigWithValuesJSON) +) + +var createReq = ` +{ + "configuration": { + "datastore": { + "type": "a00000a0-00a0-0a00-00a0-000a000000aa", + "version": "b00000b0-00b0-0b00-00b0-000b000000bb" + }, + "description": "example description", + "name": "example-configuration-name", + "values": { + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120 + } + } +} +` + +var updateReq = ` +{ + "configuration": { + "values": { + "connect_timeout": 300 + } + } +} +` + +var listInstancesJSON = ` +{ + "instances": [ + { + "id": "d4603f69-ec7e-4e9b-803f-600b9205576f", + "name": "json_rack_instance" + } + ] +} +` + +var listParamsJSON = ` +{ + "configuration-parameters": [ + { + "max": 1, + "min": 0, + "name": "innodb_file_per_table", + "restart_required": true, + "type": "integer" + }, + { + "max": 4294967296, + "min": 0, + "name": "key_buffer_size", + "restart_required": false, + "type": "integer" + }, + { + "max": 65535, + "min": 2, + "name": "connect_timeout", + "restart_required": false, + "type": "integer" + }, + { + "max": 4294967296, + "min": 0, + "name": "join_buffer_size", + "restart_required": false, + "type": "integer" + } + ] +} +` + +var getParamJSON = ` +{ + "max": 1, + "min": 0, + "name": "innodb_file_per_table", + "restart_required": true, + "type": "integer" +} +` + +var exampleConfig = os.Config{ + Created: timeVal, + DatastoreName: "mysql", + DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb", + DatastoreVersionName: "5.6", + Description: "example_description", + ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + Name: "example-configuration-name", + Updated: timeVal, +} + +var exampleConfigWithValues = os.Config{ + Created: timeVal, + DatastoreName: "mysql", + DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb", + DatastoreVersionName: "5.6", + Description: "example description", + ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2", + Name: "example-configuration-name", + Updated: timeVal, + Values: map[string]interface{}{ + "collation_server": "latin1_swedish_ci", + "connect_timeout": 120, + }, +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/delegate.go new file mode 100644 index 000000000..56552d187 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/delegate.go @@ -0,0 +1,19 @@ +package databases + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/databases" + "github.com/rackspace/gophercloud/pagination" +) + +func Create(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, instanceID, opts) +} + +func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager { + return os.List(client, instanceID) +} + +func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) os.DeleteResult { + return os.Delete(client, instanceID, dbName) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/doc.go new file mode 100644 index 000000000..1a178b61f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/doc.go @@ -0,0 +1,3 @@ +// Package databases provides information and interaction with the database API +// resource in the Rackspace Database service. +package databases diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/urls.go new file mode 100644 index 000000000..18cbec72e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/databases/urls.go @@ -0,0 +1 @@ +package databases diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/delegate.go new file mode 100644 index 000000000..573496d38 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/delegate.go @@ -0,0 +1,28 @@ +package datastores + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all available flavors. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// Get retrieves the details for a particular flavor. +func Get(client *gophercloud.ServiceClient, flavorID string) os.GetResult { + return os.Get(client, flavorID) +} + +// ListVersions will list all of the available versions for a specified +// datastore type. +func ListVersions(client *gophercloud.ServiceClient, datastoreID string) pagination.Pager { + return os.ListVersions(client, datastoreID) +} + +// GetVersion will retrieve the details of a specified datastore version. +func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) os.GetVersionResult { + return os.GetVersion(client, datastoreID, versionID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/doc.go new file mode 100644 index 000000000..f36997a03 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/datastores/doc.go @@ -0,0 +1 @@ +package datastores diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/delegate.go new file mode 100644 index 000000000..689b81eac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/delegate.go @@ -0,0 +1,17 @@ +package flavors + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/flavors" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all available flavors. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// Get retrieves the details for a particular flavor. +func Get(client *gophercloud.ServiceClient, flavorID string) os.GetResult { + return os.Get(client, flavorID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/doc.go new file mode 100644 index 000000000..922a4e667 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/flavors/doc.go @@ -0,0 +1,3 @@ +// Package flavors provides information and interaction with the flavor API +// resource in the Rackspace Database service. +package flavors diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/delegate.go new file mode 100644 index 000000000..f2656fe3b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/delegate.go @@ -0,0 +1,49 @@ +package instances + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/instances" +) + +// Get retrieves the status and information for a specified database instance. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + return GetResult{os.Get(client, id)} +} + +// Delete permanently destroys the database instance. +func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(client, id) +} + +// EnableRootUser enables the login from any host for the root user and +// provides the user with a generated root password. +func EnableRootUser(client *gophercloud.ServiceClient, id string) os.UserRootResult { + return os.EnableRootUser(client, id) +} + +// IsRootEnabled checks an instance to see if root access is enabled. It returns +// True if root user is enabled for the specified database instance or False +// otherwise. +func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) { + return os.IsRootEnabled(client, id) +} + +// Restart will restart only the MySQL Instance. Restarting MySQL will +// erase any dynamic configuration settings that you have made within MySQL. +// The MySQL service will be unavailable until the instance restarts. +func Restart(client *gophercloud.ServiceClient, id string) os.ActionResult { + return os.Restart(client, id) +} + +// Resize changes the memory size of the instance, assuming a valid +// flavorRef is provided. It will also restart the MySQL service. +func Resize(client *gophercloud.ServiceClient, id, flavorRef string) os.ActionResult { + return os.Resize(client, id, flavorRef) +} + +// ResizeVolume will resize the attached volume for an instance. It supports +// only increasing the volume size and does not support decreasing the size. +// The volume size is in gigabytes (GB) and must be an integer. +func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) os.ActionResult { + return os.ResizeVolume(client, id, size) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/doc.go new file mode 100644 index 000000000..0c8ad6336 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/doc.go @@ -0,0 +1,3 @@ +// Package instances provides information and interaction with the instance API +// resource in the Rackspace Database service. +package instances diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/fixtures.go new file mode 100644 index 000000000..c5ff37aee --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/fixtures.go @@ -0,0 +1,340 @@ +package instances + +import ( + "fmt" + "time" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/openstack/db/v1/flavors" + os "github.com/rackspace/gophercloud/openstack/db/v1/instances" +) + +var ( + timestamp = "2015-11-12T14:22:42Z" + timeVal, _ = time.Parse(time.RFC3339, timestamp) +) + +var instance = ` +{ + "created": "` + timestamp + `", + "datastore": { + "type": "mysql", + "version": "5.6" + }, + "flavor": { + "id": "1", + "links": [ + { + "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", + "rel": "self" + }, + { + "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", + "rel": "bookmark" + } + ] + }, + "links": [ + { + "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", + "rel": "self" + } + ], + "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com", + "id": "{instanceID}", + "name": "json_rack_instance", + "status": "BUILD", + "updated": "` + timestamp + `", + "volume": { + "size": 2 + } +} +` + +var createReq = ` +{ + "instance": { + "databases": [ + { + "character_set": "utf8", + "collate": "utf8_general_ci", + "name": "sampledb" + }, + { + "name": "nextround" + } + ], + "flavorRef": "1", + "name": "json_rack_instance", + "users": [ + { + "databases": [ + { + "name": "sampledb" + } + ], + "name": "demouser", + "password": "demopassword" + } + ], + "volume": { + "size": 2 + }, + "restorePoint": { + "backupRef": "1234567890" + } + } +} +` + +var createReplicaReq = ` +{ + "instance": { + "volume": { + "size": 1 + }, + "flavorRef": "9", + "name": "t2s1_ALT_GUEST", + "replica_of": "6bdca2fc-418e-40bd-a595-62abda61862d" + } +} +` + +var createReplicaResp = ` +{ + "instance": { + "status": "BUILD", + "updated": "` + timestamp + `", + "name": "t2s1_ALT_GUEST", + "links": [ + { + "href": "https://ord.databases.api.rackspacecloud.com/v1.0/5919009/instances/8367c312-7c40-4a66-aab1-5767478914fc", + "rel": "self" + }, + { + "href": "https://ord.databases.api.rackspacecloud.com/instances/8367c312-7c40-4a66-aab1-5767478914fc", + "rel": "bookmark" + } + ], + "created": "` + timestamp + `", + "id": "8367c312-7c40-4a66-aab1-5767478914fc", + "volume": { + "size": 1 + }, + "flavor": { + "id": "9" + }, + "datastore": { + "version": "5.6", + "type": "mysql" + }, + "replica_of": { + "id": "6bdca2fc-418e-40bd-a595-62abda61862d" + } + } +} +` + +var listReplicasResp = ` +{ + "instances": [ + { + "status": "ACTIVE", + "name": "t1s1_ALT_GUEST", + "links": [ + { + "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254", + "rel": "self" + }, + { + "href": "https://ord.databases.api.rackspacecloud.com/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254", + "rel": "bookmark" + } + ], + "ip": [ + "10.0.0.3" + ], + "id": "3c691f06-bf9a-4618-b7ec-2817ce0cf254", + "volume": { + "size": 1 + }, + "flavor": { + "id": "9" + }, + "datastore": { + "version": "5.6", + "type": "mysql" + }, + "replica_of": { + "id": "8b499b45-52d6-402d-b398-f9d8f279c69a" + } + } + ] +} +` + +var getReplicaResp = ` +{ + "instance": { + "status": "ACTIVE", + "updated": "` + timestamp + `", + "name": "t1_ALT_GUEST", + "created": "` + timestamp + `", + "ip": [ + "10.0.0.2" + ], + "replicas": [ + { + "id": "3c691f06-bf9a-4618-b7ec-2817ce0cf254" + } + ], + "id": "8b499b45-52d6-402d-b398-f9d8f279c69a", + "volume": { + "used": 0.54, + "size": 1 + }, + "flavor": { + "id": "9" + }, + "datastore": { + "version": "5.6", + "type": "mysql" + } + } +} +` + +var detachReq = ` +{ + "instance": { + "replica_of": "", + "slave_of": "" + } +} +` + +var getConfigResp = ` +{ + "instance": { + "configuration": { + "basedir": "/usr", + "connect_timeout": "15", + "datadir": "/var/lib/mysql", + "default_storage_engine": "innodb", + "innodb_buffer_pool_instances": "1", + "innodb_buffer_pool_size": "175M", + "innodb_checksum_algorithm": "crc32", + "innodb_data_file_path": "ibdata1:10M:autoextend", + "innodb_file_per_table": "1", + "innodb_io_capacity": "200", + "innodb_log_file_size": "256M", + "innodb_log_files_in_group": "2", + "innodb_open_files": "8192", + "innodb_thread_concurrency": "0", + "join_buffer_size": "1M", + "key_buffer_size": "50M", + "local-infile": "0", + "log-error": "/var/log/mysql/mysqld.log", + "max_allowed_packet": "16M", + "max_connect_errors": "10000", + "max_connections": "40", + "max_heap_table_size": "16M", + "myisam-recover": "BACKUP", + "open_files_limit": "8192", + "performance_schema": "off", + "pid_file": "/var/run/mysqld/mysqld.pid", + "port": "3306", + "query_cache_limit": "1M", + "query_cache_size": "8M", + "query_cache_type": "1", + "read_buffer_size": "256K", + "read_rnd_buffer_size": "1M", + "server_id": "1", + "skip-external-locking": "1", + "skip_name_resolve": "1", + "sort_buffer_size": "256K", + "table_open_cache": "4096", + "thread_stack": "192K", + "tmp_table_size": "16M", + "tmpdir": "/var/tmp", + "user": "mysql", + "wait_timeout": "3600" + } + } +} +` + +var associateReq = `{"instance": {"configuration": "{configGroupID}"}}` + +var listBackupsResp = ` +{ + "backups": [ + { + "status": "COMPLETED", + "updated": "` + timestamp + `", + "description": "Backup from Restored Instance", + "datastore": { + "version": "5.1", + "type": "MySQL", + "version_id": "20000000-0000-0000-0000-000000000002" + }, + "id": "87972694-4be2-40f5-83f8-501656e0032a", + "size": 0.141026, + "name": "restored_backup", + "created": "` + timestamp + `", + "instance_id": "29af2cd9-0674-48ab-b87a-b160f00208e6", + "parent_id": null, + "locationRef": "http://localhost/path/to/backup" + } + ] +} +` + +var ( + createResp = fmt.Sprintf(`{"instance":%s}`, instance) + getResp = fmt.Sprintf(`{"instance":%s}`, instance) + associateResp = fmt.Sprintf(`{"instance":%s}`, instance) + listInstancesResp = fmt.Sprintf(`{"instances":[%s]}`, instance) +) + +var instanceID = "{instanceID}" + +var expectedInstance = &Instance{ + Created: timeVal, + Updated: timeVal, + Datastore: datastores.DatastorePartial{Type: "mysql", Version: "5.6"}, + Flavor: flavors.Flavor{ + ID: "1", + Links: []gophercloud.Link{ + gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "self"}, + gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "bookmark"}, + }, + }, + Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com", + ID: instanceID, + Links: []gophercloud.Link{ + gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "self"}, + }, + Name: "json_rack_instance", + Status: "BUILD", + Volume: os.Volume{Size: 2}, +} + +var expectedReplica = &Instance{ + Status: "BUILD", + Updated: timeVal, + Name: "t2s1_ALT_GUEST", + Links: []gophercloud.Link{ + gophercloud.Link{Rel: "self", Href: "https://ord.databases.api.rackspacecloud.com/v1.0/5919009/instances/8367c312-7c40-4a66-aab1-5767478914fc"}, + gophercloud.Link{Rel: "bookmark", Href: "https://ord.databases.api.rackspacecloud.com/instances/8367c312-7c40-4a66-aab1-5767478914fc"}, + }, + Created: timeVal, + ID: "8367c312-7c40-4a66-aab1-5767478914fc", + Volume: os.Volume{Size: 1}, + Flavor: flavors.Flavor{ID: "9"}, + Datastore: datastores.DatastorePartial{Version: "5.6", Type: "mysql"}, + ReplicaOf: &Instance{ + ID: "6bdca2fc-418e-40bd-a595-62abda61862d", + }, +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/requests.go new file mode 100644 index 000000000..f4df692a4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/requests.go @@ -0,0 +1,199 @@ +package instances + +import ( + "github.com/rackspace/gophercloud" + osDBs "github.com/rackspace/gophercloud/openstack/db/v1/databases" + os "github.com/rackspace/gophercloud/openstack/db/v1/instances" + osUsers "github.com/rackspace/gophercloud/openstack/db/v1/users" + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/rackspace/db/v1/backups" +) + +// CreateOpts is the struct responsible for configuring a new database instance. +type CreateOpts struct { + // Either the integer UUID (in string form) of the flavor, or its URI + // reference as specified in the response from the List() call. Required. + FlavorRef string + + // Specifies the volume size in gigabytes (GB). The value must be between 1 + // and 300. Required. + Size int + + // Name of the instance to create. The length of the name is limited to + // 255 characters and any characters are permitted. Optional. + Name string + + // A slice of database information options. + Databases osDBs.CreateOptsBuilder + + // A slice of user information options. + Users osUsers.CreateOptsBuilder + + // ID of the configuration group to associate with the instance. Optional. + ConfigID string + + // Options to configure the type of datastore the instance will use. This is + // optional, and if excluded will default to MySQL. + Datastore *os.DatastoreOpts + + // Specifies the backup ID from which to restore the database instance. There + // are some things to be aware of before using this field. When you execute + // the Restore Backup operation, a new database instance is created to store + // the backup whose ID is specified by the restorePoint attribute. This will + // mean that: + // - All users, passwords and access that were on the instance at the time of + // the backup will be restored along with the databases. + // - You can create new users or databases if you want, but they cannot be + // the same as the ones from the instance that was backed up. + RestorePoint string + + ReplicaOf string +} + +func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) { + instance, err := os.CreateOpts{ + FlavorRef: opts.FlavorRef, + Size: opts.Size, + Name: opts.Name, + Databases: opts.Databases, + Users: opts.Users, + }.ToInstanceCreateMap() + + if err != nil { + return nil, err + } + + instance = instance["instance"].(map[string]interface{}) + + if opts.ConfigID != "" { + instance["configuration"] = opts.ConfigID + } + + if opts.Datastore != nil { + ds, err := opts.Datastore.ToMap() + if err != nil { + return nil, err + } + instance["datastore"] = ds + } + + if opts.RestorePoint != "" { + instance["restorePoint"] = map[string]string{"backupRef": opts.RestorePoint} + } + + if opts.ReplicaOf != "" { + instance["replica_of"] = opts.ReplicaOf + } + + return map[string]interface{}{"instance": instance}, nil +} + +// Create asynchronously provisions a new database instance. It requires the +// user to specify a flavor and a volume size. The API service then provisions +// the instance with the requested flavor and sets up a volume of the specified +// size, which is the storage for the database instance. +// +// Although this call only allows the creation of 1 instance per request, you +// can create an instance with multiple databases and users. The default +// binding for a MySQL instance is port 3306. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult { + return CreateResult{os.Create(client, opts)} +} + +// ListOpts specifies all of the query options to be used when returning a list +// of database instances. +type ListOpts struct { + // IncludeHA includes or excludes High Availability instances from the result set + IncludeHA bool `q:"include_ha"` + + // IncludeReplicas includes or excludes Replica instances from the result set + IncludeReplicas bool `q:"include_replicas"` +} + +// ToInstanceListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToInstanceListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List retrieves the status and information for all database instances. +func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager { + url := baseURL(client) + + if opts != nil { + query, err := opts.ToInstanceListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + createPageFn := func(r pagination.PageResult) pagination.Page { + return os.InstancePage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, url, createPageFn) +} + +// GetDefaultConfig lists the default configuration settings from the template +// that was applied to the specified instance. In a sense, this is the vanilla +// configuration setting applied to an instance. Further configuration can be +// applied by associating an instance with a configuration group. +func GetDefaultConfig(client *gophercloud.ServiceClient, id string) ConfigResult { + var res ConfigResult + + _, res.Err = client.Request("GET", configURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// AssociateWithConfigGroup associates a specified instance to a specified +// configuration group. If any of the parameters within a configuration group +// require a restart, then the instance will transition into a restart. +func AssociateWithConfigGroup(client *gophercloud.ServiceClient, instanceID, configGroupID string) UpdateResult { + reqBody := map[string]string{ + "configuration": configGroupID, + } + + var res UpdateResult + + _, res.Err = client.Request("PUT", resourceURL(client, instanceID), gophercloud.RequestOpts{ + JSONBody: map[string]map[string]string{"instance": reqBody}, + OkCodes: []int{202}, + }) + + return res +} + +// DetachFromConfigGroup will detach an instance from all config groups. +func DetachFromConfigGroup(client *gophercloud.ServiceClient, instanceID string) UpdateResult { + return AssociateWithConfigGroup(client, instanceID, "") +} + +// ListBackups will list all the backups for a specified database instance. +func ListBackups(client *gophercloud.ServiceClient, instanceID string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return backups.BackupPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(client, backupsURL(client, instanceID), pageFn) +} + +// DetachReplica will detach a specified replica instance from its source +// instance, effectively allowing it to operate independently. Detaching a +// replica will restart the MySQL service on the instance. +func DetachReplica(client *gophercloud.ServiceClient, replicaID string) DetachResult { + var res DetachResult + + _, res.Err = client.Request("PATCH", resourceURL(client, replicaID), gophercloud.RequestOpts{ + JSONBody: map[string]interface{}{"instance": map[string]string{"replica_of": "", "slave_of": ""}}, + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/results.go new file mode 100644 index 000000000..cdcc9c716 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/results.go @@ -0,0 +1,191 @@ +package instances + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/db/v1/datastores" + "github.com/rackspace/gophercloud/openstack/db/v1/flavors" + os "github.com/rackspace/gophercloud/openstack/db/v1/instances" + "github.com/rackspace/gophercloud/pagination" +) + +// Instance represents a remote MySQL instance. +type Instance struct { + // Indicates the datetime that the instance was created + Created time.Time `mapstructure:"-"` + + // Indicates the most recent datetime that the instance was updated. + Updated time.Time `mapstructure:"-"` + + // Indicates how the instance stores data. + Datastore datastores.DatastorePartial + + // Indicates the hardware flavor the instance uses. + Flavor flavors.Flavor + + // A DNS-resolvable hostname associated with the database instance (rather + // than an IPv4 address). Since the hostname always resolves to the correct + // IP address of the database instance, this relieves the user from the task + // of maintaining the mapping. Note that although the IP address may likely + // change on resizing, migrating, and so forth, the hostname always resolves + // to the correct database instance. + Hostname string + + // Indicates the unique identifier for the instance resource. + ID string + + // Exposes various links that reference the instance resource. + Links []gophercloud.Link + + // The human-readable name of the instance. + Name string + + // The build status of the instance. + Status string + + // Information about the attached volume of the instance. + Volume os.Volume + + // IP indicates the various IP addresses which allow access. + IP []string + + // Indicates whether this instance is a replica of another source instance. + ReplicaOf *Instance `mapstructure:"replica_of" json:"replica_of"` + + // Indicates whether this instance is the source of other replica instances. + Replicas []Instance +} + +func commonExtract(err error, body interface{}) (*Instance, error) { + if err != nil { + return nil, err + } + + var response struct { + Instance Instance `mapstructure:"instance"` + } + + err = mapstructure.Decode(body, &response) + + val := body.(map[string]interface{})["instance"].(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Instance, err + } + response.Instance.Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &response.Instance, err + } + response.Instance.Updated = updatedTime + } + + return &response.Instance, err +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + os.CreateResult +} + +// Extract will retrieve an instance from a create result. +func (r CreateResult) Extract() (*Instance, error) { + return commonExtract(r.Err, r.Body) +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + os.GetResult +} + +// Extract will extract an Instance from a GetResult. +func (r GetResult) Extract() (*Instance, error) { + return commonExtract(r.Err, r.Body) +} + +// ConfigResult represents the result of getting default configuration for an +// instance. +type ConfigResult struct { + gophercloud.Result +} + +// DetachResult represents the result of detaching a replica from its source. +type DetachResult struct { + gophercloud.ErrResult +} + +// Extract will extract the configuration information (in the form of a map) +// about a particular instance. +func (r ConfigResult) Extract() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Instance struct { + Config map[string]string `mapstructure:"configuration"` + } `mapstructure:"instance"` + } + + err := mapstructure.Decode(r.Body, &response) + return response.Instance.Config, err +} + +// UpdateResult represents the result of an Update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// ExtractInstances retrieves a slice of instances from a paginated collection. +func ExtractInstances(page pagination.Page) ([]Instance, error) { + casted := page.(os.InstancePage).Body + + var resp struct { + Instances []Instance `mapstructure:"instances"` + } + + if err := mapstructure.Decode(casted, &resp); err != nil { + return nil, err + } + + var vals []interface{} + switch casted.(type) { + case map[string]interface{}: + vals = casted.(map[string]interface{})["instances"].([]interface{}) + case map[string][]interface{}: + vals = casted.(map[string][]interface{})["instances"] + default: + return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i, v := range vals { + val := v.(map[string]interface{}) + + if t, ok := val["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Instances, err + } + resp.Instances[i].Created = creationTime + } + + if t, ok := val["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return resp.Instances, err + } + resp.Instances[i].Updated = updatedTime + } + } + + return resp.Instances, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/urls.go new file mode 100644 index 000000000..5955f4cde --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/instances/urls.go @@ -0,0 +1,23 @@ +package instances + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("instances") +} + +func createURL(c *gophercloud.ServiceClient) string { + return baseURL(c) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id) +} + +func configURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id, "configuration") +} + +func backupsURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("instances", id, "backups") +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/delegate.go new file mode 100644 index 000000000..8298c4605 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/delegate.go @@ -0,0 +1,16 @@ +package users + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/db/v1/users" +) + +// Create will create a new database user for the specified database instance. +func Create(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(client, instanceID, opts) +} + +// Delete will permanently remove a user from a specified database instance. +func Delete(client *gophercloud.ServiceClient, instanceID, userName string) os.DeleteResult { + return os.Delete(client, instanceID, userName) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/doc.go new file mode 100644 index 000000000..84f2eb327 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/doc.go @@ -0,0 +1,3 @@ +// Package users provides information and interaction with the user API +// resource in the Rackspace Database service. +package users diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/fixtures.go new file mode 100644 index 000000000..5314e854f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/fixtures.go @@ -0,0 +1,77 @@ +package users + +const singleDB = `{"databases": [{"name": "databaseE"}]}` + +var changePwdReq = ` +{ + "users": [ + { + "name": "dbuser1", + "password": "newpassword" + }, + { + "name": "dbuser2", + "password": "anotherpassword" + } + ] +} +` + +var updateReq = ` +{ + "user": { + "name": "new_username", + "password": "new_password" + } +} +` + +var getResp = ` +{ + "user": { + "name": "exampleuser", + "host": "foo", + "databases": [ + { + "name": "databaseA" + }, + { + "name": "databaseB" + } + ] + } +} +` + +var listResp = ` +{ +"users": [ + { + "name": "dbuser1", + "host": "localhost", + "databases": [ + { + "name": "databaseA" + } + ] + }, + { + "name": "dbuser2", + "host": "localhost", + "databases": [ + { + "name": "databaseB" + }, + { + "name": "databaseC" + } + ] + } +] +} +` + +var ( + listUserAccessResp = singleDB + grantUserAccessReq = singleDB +) diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/requests.go new file mode 100644 index 000000000..74e47ab23 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/requests.go @@ -0,0 +1,176 @@ +package users + +import ( + "errors" + + "github.com/rackspace/gophercloud" + db "github.com/rackspace/gophercloud/openstack/db/v1/databases" + os "github.com/rackspace/gophercloud/openstack/db/v1/users" + "github.com/rackspace/gophercloud/pagination" +) + +// List will list all available users for a specified database instance. +func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager { + createPageFn := func(r pagination.PageResult) pagination.Page { + return UserPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, baseURL(client, instanceID), createPageFn) +} + +/* +ChangePassword changes the password for one or more users. For example, to +change the respective passwords for two users: + + opts := os.BatchCreateOpts{ + os.CreateOpts{Name: "db_user_1", Password: "new_password_1"}, + os.CreateOpts{Name: "db_user_2", Password: "new_password_2"}, + } + + ChangePassword(client, "instance_id", opts) +*/ +func ChangePassword(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) UpdatePasswordsResult { + var res UpdatePasswordsResult + + reqBody, err := opts.ToUserCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("PUT", baseURL(client, instanceID), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + + return res +} + +// UpdateOpts is the struct responsible for updating an existing user. +type UpdateOpts struct { + // [OPTIONAL] Specifies a name for the user. Valid names can be composed + // of the following characters: letters (either case); numbers; these + // characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is + // permitted anywhere. Prohibited characters that are forbidden include: + // single quotes, double quotes, back quotes, semicolons, commas, backslashes, + // and forward slashes. Spaces at the front or end of a user name are also + // not permitted. + Name string + + // [OPTIONAL] Specifies a password for the user. + Password string + + // [OPTIONAL] Specifies the host from which a user is allowed to connect to + // the database. Possible values are a string containing an IPv4 address or + // "%" to allow connecting from any host. Optional; the default is "%". + Host string +} + +// ToMap is a convenience function for creating sub-maps for individual users. +func (opts UpdateOpts) ToMap() (map[string]interface{}, error) { + if opts.Name == "root" { + return nil, errors.New("root is a reserved user name and cannot be used") + } + + user := map[string]interface{}{} + + if opts.Name != "" { + user["name"] = opts.Name + } + + if opts.Password != "" { + user["password"] = opts.Password + } + + if opts.Host != "" { + user["host"] = opts.Host + } + + return user, nil +} + +// Update will modify the attributes of a specified user. Attributes that can +// be updated are: user name, password, and host. +func Update(client *gophercloud.ServiceClient, instanceID, userName string, opts UpdateOpts) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToMap() + if err != nil { + res.Err = err + return res + } + reqBody = map[string]interface{}{"user": reqBody} + + _, res.Err = client.Request("PUT", userURL(client, instanceID, userName), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + + return res +} + +// Get will retrieve the details for a particular user. +func Get(client *gophercloud.ServiceClient, instanceID, userName string) GetResult { + var res GetResult + + _, res.Err = client.Request("GET", userURL(client, instanceID, userName), gophercloud.RequestOpts{ + JSONResponse: &res.Body, + OkCodes: []int{200}, + }) + + return res +} + +// ListAccess will list all of the databases a user has access to. +func ListAccess(client *gophercloud.ServiceClient, instanceID, userName string) pagination.Pager { + pageFn := func(r pagination.PageResult) pagination.Page { + return AccessPage{pagination.LinkedPageBase{PageResult: r}} + } + + return pagination.NewPager(client, dbsURL(client, instanceID, userName), pageFn) +} + +/* +GrantAccess for the specified user to one or more databases on a specified +instance. For example, to add a user to multiple databases: + + opts := db.BatchCreateOpts{ + db.CreateOpts{Name: "database_1"}, + db.CreateOpts{Name: "database_3"}, + db.CreateOpts{Name: "database_19"}, + } + + GrantAccess(client, "instance_id", "user_name", opts) +*/ +func GrantAccess(client *gophercloud.ServiceClient, instanceID, userName string, opts db.CreateOptsBuilder) GrantAccessResult { + var res GrantAccessResult + + reqBody, err := opts.ToDBCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Request("PUT", dbsURL(client, instanceID, userName), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{202}, + }) + + return res +} + +/* +RevokeAccess will revoke access for the specified user to one or more databases +on a specified instance. For example: + + RevokeAccess(client, "instance_id", "user_name", "db_name") +*/ +func RevokeAccess(client *gophercloud.ServiceClient, instanceID, userName, dbName string) RevokeAccessResult { + var res RevokeAccessResult + + _, res.Err = client.Request("DELETE", dbURL(client, instanceID, userName, dbName), gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/results.go new file mode 100644 index 000000000..85b3a7aaa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/results.go @@ -0,0 +1,149 @@ +package users + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + db "github.com/rackspace/gophercloud/openstack/db/v1/databases" + "github.com/rackspace/gophercloud/pagination" +) + +// User represents a database user +type User struct { + // The user name + Name string + + // The user password + Password string + + // Specifies the host from which a user is allowed to connect to the database. + // Possible values are a string containing an IPv4 address or "%" to allow + // connecting from any host. + Host string + + // The databases associated with this user + Databases []db.Database +} + +// UpdatePasswordsResult represents the result of changing a user password. +type UpdatePasswordsResult struct { + gophercloud.ErrResult +} + +// UpdateResult represents the result of updating a user. +type UpdateResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of getting a user. +type GetResult struct { + gophercloud.Result +} + +// Extract will retrieve a User struct from a getresult. +func (r GetResult) Extract() (*User, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + User User `mapstructure:"user"` + } + + err := mapstructure.Decode(r.Body, &response) + return &response.User, err +} + +// AccessPage represents a single page of a paginated user collection. +type AccessPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks to see whether the collection is empty. +func (page AccessPage) IsEmpty() (bool, error) { + users, err := ExtractDBs(page) + if err != nil { + return true, err + } + return len(users) == 0, nil +} + +// NextPageURL will retrieve the next page URL. +func (page AccessPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"databases_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractDBs will convert a generic pagination struct into a more +// relevant slice of DB structs. +func ExtractDBs(page pagination.Page) ([]db.Database, error) { + casted := page.(AccessPage).Body + + var response struct { + DBs []db.Database `mapstructure:"databases"` + } + + err := mapstructure.Decode(casted, &response) + return response.DBs, err +} + +// UserPage represents a single page of a paginated user collection. +type UserPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks to see whether the collection is empty. +func (page UserPage) IsEmpty() (bool, error) { + users, err := ExtractUsers(page) + if err != nil { + return true, err + } + return len(users) == 0, nil +} + +// NextPageURL will retrieve the next page URL. +func (page UserPage) NextPageURL() (string, error) { + type resp struct { + Links []gophercloud.Link `mapstructure:"users_links"` + } + + var r resp + err := mapstructure.Decode(page.Body, &r) + if err != nil { + return "", err + } + + return gophercloud.ExtractNextURL(r.Links) +} + +// ExtractUsers will convert a generic pagination struct into a more +// relevant slice of User structs. +func ExtractUsers(page pagination.Page) ([]User, error) { + casted := page.(UserPage).Body + + var response struct { + Users []User `mapstructure:"users"` + } + + err := mapstructure.Decode(casted, &response) + + return response.Users, err +} + +// GrantAccessResult represents the result of granting access to a user. +type GrantAccessResult struct { + gophercloud.ErrResult +} + +// RevokeAccessResult represents the result of revoking access to a user. +type RevokeAccessResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/urls.go new file mode 100644 index 000000000..bac8788ff --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/db/v1/users/urls.go @@ -0,0 +1,19 @@ +package users + +import "github.com/rackspace/gophercloud" + +func baseURL(c *gophercloud.ServiceClient, instanceID string) string { + return c.ServiceURL("instances", instanceID, "users") +} + +func userURL(c *gophercloud.ServiceClient, instanceID, userName string) string { + return c.ServiceURL("instances", instanceID, "users", userName) +} + +func dbsURL(c *gophercloud.ServiceClient, instanceID, userName string) string { + return c.ServiceURL("instances", instanceID, "users", userName, "databases") +} + +func dbURL(c *gophercloud.ServiceClient, instanceID, userName, dbName string) string { + return c.ServiceURL("instances", instanceID, "users", userName, "databases", dbName) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/delegate.go new file mode 100644 index 000000000..fc547cde5 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/delegate.go @@ -0,0 +1,24 @@ +package extensions + +import ( + "github.com/rackspace/gophercloud" + common "github.com/rackspace/gophercloud/openstack/common/extensions" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the +// elements into a slice of os.Extension structs. +func ExtractExtensions(page pagination.Page) ([]common.Extension, error) { + return common.ExtractExtensions(page) +} + +// Get retrieves information for a specific extension using its alias. +func Get(c *gophercloud.ServiceClient, alias string) common.GetResult { + return common.Get(c, alias) +} + +// List returns a Pager which allows you to iterate over the full collection of extensions. +// It does not accept query parameters. +func List(c *gophercloud.ServiceClient) pagination.Pager { + return common.List(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/doc.go new file mode 100644 index 000000000..b02a95b53 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/extensions/doc.go @@ -0,0 +1,3 @@ +// Package extensions provides information and interaction with the all the +// extensions available for the Rackspace Identity service. +package extensions diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/delegate.go new file mode 100644 index 000000000..a6ee8515c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/delegate.go @@ -0,0 +1,50 @@ +package roles + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + + os "github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles" +) + +// List is the operation responsible for listing all available global roles +// that a user can adopt. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// AddUserRole is the operation responsible for assigning a particular role to +// a user. This is confined to the scope of the user's tenant - so the tenant +// ID is a required argument. +func AddUserRole(client *gophercloud.ServiceClient, userID, roleID string) UserRoleResult { + var result UserRoleResult + + _, result.Err = client.Request("PUT", userRoleURL(client, userID, roleID), gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + + return result +} + +// DeleteUserRole is the operation responsible for deleting a particular role +// from a user. This is confined to the scope of the user's tenant - so the +// tenant ID is a required argument. +func DeleteUserRole(client *gophercloud.ServiceClient, userID, roleID string) UserRoleResult { + var result UserRoleResult + + _, result.Err = client.Request("DELETE", userRoleURL(client, userID, roleID), gophercloud.RequestOpts{ + OkCodes: []int{204}, + }) + + return result +} + +// UserRoleResult represents the result of either an AddUserRole or +// a DeleteUserRole operation. +type UserRoleResult struct { + gophercloud.ErrResult +} + +func userRoleURL(c *gophercloud.ServiceClient, userID, roleID string) string { + return c.ServiceURL(os.UserPath, userID, os.RolePath, os.ExtPath, roleID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/fixtures.go new file mode 100644 index 000000000..5f22d0f64 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/roles/fixtures.go @@ -0,0 +1,49 @@ +package roles + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func MockListRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/OS-KSADM/roles", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "roles": [ + { + "id": "123", + "name": "compute:admin", + "description": "Nova Administrator", + "serviceId": "cke5372ebabeeabb70a0e702a4626977x4406e5" + } + ] +} + `) + }) +} + +func MockAddUserRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/users/{user_id}/roles/OS-KSADM/{role_id}", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusCreated) + }) +} + +func MockDeleteUserRoleResponse(t *testing.T) { + th.Mux.HandleFunc("/users/{user_id}/roles/OS-KSADM/{role_id}", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/delegate.go new file mode 100644 index 000000000..6cdd0cfbd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/delegate.go @@ -0,0 +1,17 @@ +package tenants + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/identity/v2/tenants" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractTenants interprets a page of List results as a more usable slice of Tenant structs. +func ExtractTenants(page pagination.Page) ([]os.Tenant, error) { + return os.ExtractTenants(page) +} + +// List enumerates the tenants to which the current token grants access. +func List(client *gophercloud.ServiceClient, opts *os.ListOpts) pagination.Pager { + return os.List(client, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/doc.go new file mode 100644 index 000000000..c1825c21d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tenants/doc.go @@ -0,0 +1,3 @@ +// Package tenants provides information and interaction with the tenant +// API resource for the Rackspace Identity service. +package tenants diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/delegate.go new file mode 100644 index 000000000..4f9885af0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/delegate.go @@ -0,0 +1,60 @@ +package tokens + +import ( + "errors" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/identity/v2/tokens" +) + +var ( + // ErrPasswordProvided is returned if both a password and an API key are provided to Create. + ErrPasswordProvided = errors.New("Please provide either a password or an API key.") +) + +// AuthOptions wraps the OpenStack AuthOptions struct to be able to customize the request body +// when API key authentication is used. +type AuthOptions struct { + os.AuthOptions +} + +// WrapOptions embeds a root AuthOptions struct in a package-specific one. +func WrapOptions(original gophercloud.AuthOptions) AuthOptions { + return AuthOptions{AuthOptions: os.WrapOptions(original)} +} + +// ToTokenCreateMap serializes an AuthOptions into a request body. If an API key is provided, it +// will be used, otherwise +func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) { + if auth.APIKey == "" { + return auth.AuthOptions.ToTokenCreateMap() + } + + // Verify that other required attributes are present. + if auth.Username == "" { + return nil, os.ErrUsernameRequired + } + + authMap := make(map[string]interface{}) + + authMap["RAX-KSKEY:apiKeyCredentials"] = map[string]interface{}{ + "username": auth.Username, + "apiKey": auth.APIKey, + } + + if auth.TenantID != "" { + authMap["tenantId"] = auth.TenantID + } + if auth.TenantName != "" { + authMap["tenantName"] = auth.TenantName + } + + return map[string]interface{}{"auth": authMap}, nil +} + +// Create authenticates to Rackspace's identity service and attempts to acquire a Token. Rather +// than interact with this service directly, users should generally call +// rackspace.AuthenticatedClient(). +func Create(client *gophercloud.ServiceClient, auth AuthOptions) os.CreateResult { + return os.Create(client, auth) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/doc.go new file mode 100644 index 000000000..44043e5e1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/tokens/doc.go @@ -0,0 +1,3 @@ +// Package tokens provides information and interaction with the token +// API resource for the Rackspace Identity service. +package tokens diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/delegate.go new file mode 100644 index 000000000..6135bec10 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/delegate.go @@ -0,0 +1,142 @@ +package users + +import ( + "errors" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/identity/v2/users" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a pager that allows traversal over a collection of users. +func List(client *gophercloud.ServiceClient) pagination.Pager { + return os.List(client) +} + +// CommonOpts are the options which are shared between CreateOpts and +// UpdateOpts +type CommonOpts struct { + // Required. The username to assign to the user. When provided, the username + // must: + // - start with an alphabetical (A-Za-z) character + // - have a minimum length of 1 character + // + // The username may contain upper and lowercase characters, as well as any of + // the following special character: . - @ _ + Username string + + // Required. Email address for the user account. + Email string + + // Required. Indicates whether the user can authenticate after the user + // account is created. If no value is specified, the default value is true. + Enabled os.EnabledState + + // Optional. The password to assign to the user. If provided, the password + // must: + // - start with an alphabetical (A-Za-z) character + // - have a minimum length of 8 characters + // - contain at least one uppercase character, one lowercase character, and + // one numeric character. + // + // The password may contain any of the following special characters: . - @ _ + Password string +} + +// CreateOpts represents the options needed when creating new users. +type CreateOpts CommonOpts + +// ToUserCreateMap assembles a request body based on the contents of a CreateOpts. +func (opts CreateOpts) ToUserCreateMap() (map[string]interface{}, error) { + m := make(map[string]interface{}) + + if opts.Username == "" { + return m, errors.New("Username is a required field") + } + if opts.Enabled == nil { + return m, errors.New("Enabled is a required field") + } + if opts.Email == "" { + return m, errors.New("Email is a required field") + } + + if opts.Username != "" { + m["username"] = opts.Username + } + if opts.Email != "" { + m["email"] = opts.Email + } + if opts.Enabled != nil { + m["enabled"] = opts.Enabled + } + if opts.Password != "" { + m["OS-KSADM:password"] = opts.Password + } + + return map[string]interface{}{"user": m}, nil +} + +// Create is the operation responsible for creating new users. +func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult { + return CreateResult{os.Create(client, opts)} +} + +// Get requests details on a single user, either by ID. +func Get(client *gophercloud.ServiceClient, id string) GetResult { + return GetResult{os.Get(client, id)} +} + +// UpdateOptsBuilder allows extensions to add additional attributes to the Update request. +type UpdateOptsBuilder interface { + ToUserUpdateMap() map[string]interface{} +} + +// UpdateOpts specifies the base attributes that may be updated on an existing server. +type UpdateOpts CommonOpts + +// ToUserUpdateMap formats an UpdateOpts structure into a request body. +func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} { + m := make(map[string]interface{}) + + if opts.Username != "" { + m["username"] = opts.Username + } + if opts.Enabled != nil { + m["enabled"] = &opts.Enabled + } + if opts.Email != "" { + m["email"] = opts.Email + } + + return map[string]interface{}{"user": m} +} + +// Update is the operation responsible for updating exist users by their UUID. +func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { + var result UpdateResult + + _, result.Err = client.Request("POST", os.ResourceURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &result.Body, + JSONBody: opts.ToUserUpdateMap(), + OkCodes: []int{200}, + }) + + return result +} + +// Delete is the operation responsible for permanently deleting an API user. +func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(client, id) +} + +// ResetAPIKey resets the User's API key. +func ResetAPIKey(client *gophercloud.ServiceClient, id string) ResetAPIKeyResult { + var result ResetAPIKeyResult + + _, result.Err = client.Request("POST", resetAPIKeyURL(client, id), gophercloud.RequestOpts{ + JSONResponse: &result.Body, + OkCodes: []int{200}, + }) + + return result +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/fixtures.go new file mode 100644 index 000000000..973f39ea8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/fixtures.go @@ -0,0 +1,154 @@ +package users + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func mockListResponse(t *testing.T) { + th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "users":[ + { + "id": "u1000", + "username": "jqsmith", + "email": "john.smith@example.org", + "enabled": true + }, + { + "id": "u1001", + "username": "jqsmith", + "email": "jane.smith@example.org", + "enabled": true + } + ] +} + `) + }) +} + +func mockCreateUser(t *testing.T) { + th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "user": { + "username": "new_user", + "enabled": false, + "email": "new_user@foo.com", + "OS-KSADM:password": "foo" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "RAX-AUTH:defaultRegion": "DFW", + "RAX-AUTH:domainId": "5830280", + "id": "123456", + "username": "new_user", + "email": "new_user@foo.com", + "enabled": false + } +} +`) + }) +} + +func mockGetUser(t *testing.T) { + th.Mux.HandleFunc("/users/new_user", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "RAX-AUTH:defaultRegion": "DFW", + "RAX-AUTH:domainId": "5830280", + "RAX-AUTH:multiFactorEnabled": "true", + "id": "c39e3de9be2d4c779f1dfd6abacc176d", + "username": "jqsmith", + "email": "john.smith@example.org", + "enabled": true + } +} +`) + }) +} + +func mockUpdateUser(t *testing.T) { + th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "user": { + "email": "new_email@foo.com", + "enabled": true + } +} +`) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "user": { + "RAX-AUTH:defaultRegion": "DFW", + "RAX-AUTH:domainId": "5830280", + "RAX-AUTH:multiFactorEnabled": "true", + "id": "123456", + "username": "jqsmith", + "email": "new_email@foo.com", + "enabled": true + } +} +`) + }) +} + +func mockDeleteUser(t *testing.T) { + th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) +} + +func mockResetAPIKey(t *testing.T) { + th.Mux.HandleFunc("/users/99/OS-KSADM/credentials/RAX-KSKEY:apiKeyCredentials/RAX-AUTH/reset", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ` +{ + "RAX-KSKEY:apiKeyCredentials": { + "username": "joesmith", + "apiKey": "mooH1eiLahd5ahYood7r" + } +}`) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/results.go new file mode 100644 index 000000000..6936ecba8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/results.go @@ -0,0 +1,129 @@ +package users + +import ( + "strconv" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/identity/v2/users" + + "github.com/mitchellh/mapstructure" +) + +// User represents a user resource that exists on the API. +type User struct { + // The UUID for this user. + ID string + + // The human name for this user. + Name string + + // The username for this user. + Username string + + // Indicates whether the user is enabled (true) or disabled (false). + Enabled bool + + // The email address for this user. + Email string + + // The ID of the tenant to which this user belongs. + TenantID string `mapstructure:"tenant_id"` + + // Specifies the default region for the user account. This value is inherited + // from the user administrator when the account is created. + DefaultRegion string `mapstructure:"RAX-AUTH:defaultRegion"` + + // Identifies the domain that contains the user account. This value is + // inherited from the user administrator when the account is created. + DomainID string `mapstructure:"RAX-AUTH:domainId"` + + // The password value that the user needs for authentication. If the Add user + // request included a password value, this attribute is not included in the + // response. + Password string `mapstructure:"OS-KSADM:password"` + + // Indicates whether the user has enabled multi-factor authentication. + MultiFactorEnabled bool `mapstructure:"RAX-AUTH:multiFactorEnabled"` +} + +// CreateResult represents the result of a Create operation +type CreateResult struct { + os.CreateResult +} + +// GetResult represents the result of a Get operation +type GetResult struct { + os.GetResult +} + +// UpdateResult represents the result of an Update operation +type UpdateResult struct { + os.UpdateResult +} + +func commonExtract(resp interface{}, err error) (*User, error) { + if err != nil { + return nil, err + } + + var respStruct struct { + User *User `json:"user"` + } + + // Since the API returns a string instead of a bool, we need to hack the JSON + json := resp.(map[string]interface{}) + user := json["user"].(map[string]interface{}) + if s, ok := user["RAX-AUTH:multiFactorEnabled"].(string); ok && s != "" { + if b, err := strconv.ParseBool(s); err == nil { + user["RAX-AUTH:multiFactorEnabled"] = b + } + } + + err = mapstructure.Decode(json, &respStruct) + + return respStruct.User, err +} + +// Extract will get the Snapshot object out of the GetResult object. +func (r GetResult) Extract() (*User, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Snapshot object out of the CreateResult object. +func (r CreateResult) Extract() (*User, error) { + return commonExtract(r.Body, r.Err) +} + +// Extract will get the Snapshot object out of the UpdateResult object. +func (r UpdateResult) Extract() (*User, error) { + return commonExtract(r.Body, r.Err) +} + +// ResetAPIKeyResult represents the server response to the ResetAPIKey method. +type ResetAPIKeyResult struct { + gophercloud.Result +} + +// ResetAPIKeyValue represents an API Key that has been reset. +type ResetAPIKeyValue struct { + // The Username for this API Key reset. + Username string `mapstructure:"username"` + + // The new API Key for this user. + APIKey string `mapstructure:"apiKey"` +} + +// Extract will get the Error or ResetAPIKeyValue object out of the ResetAPIKeyResult object. +func (r ResetAPIKeyResult) Extract() (*ResetAPIKeyValue, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + ResetAPIKeyValue ResetAPIKeyValue `mapstructure:"RAX-KSKEY:apiKeyCredentials"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.ResetAPIKeyValue, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/urls.go new file mode 100644 index 000000000..bc1aaefb0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/identity/v2/users/urls.go @@ -0,0 +1,7 @@ +package users + +import "github.com/rackspace/gophercloud" + +func resetAPIKeyURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("users", id, "OS-KSADM", "credentials", "RAX-KSKEY:apiKeyCredentials", "RAX-AUTH", "reset") +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/doc.go new file mode 100644 index 000000000..42325fe83 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/doc.go @@ -0,0 +1,12 @@ +/* +Package acl provides information and interaction with the access lists feature +of the Rackspace Cloud Load Balancer service. + +The access list management feature allows fine-grained network access controls +to be applied to the load balancer's virtual IP address. A single IP address, +multiple IP addresses, or entire network subnets can be added. Items that are +configured with the ALLOW type always takes precedence over items with the DENY +type. To reject traffic from all items except for those with the ALLOW type, +add a networkItem with an address of "0.0.0.0/0" and a DENY type. +*/ +package acl diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/fixtures.go new file mode 100644 index 000000000..e3c941c81 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/fixtures.go @@ -0,0 +1,109 @@ +package acl + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(lbID int) string { + return "/loadbalancers/" + strconv.Itoa(lbID) + "/accesslist" +} + +func mockListResponse(t *testing.T, id int) { + th.Mux.HandleFunc(_rootURL(id), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "accessList": [ + { + "address": "206.160.163.21", + "id": 21, + "type": "DENY" + }, + { + "address": "206.160.163.22", + "id": 22, + "type": "DENY" + }, + { + "address": "206.160.163.23", + "id": 23, + "type": "DENY" + }, + { + "address": "206.160.163.24", + "id": 24, + "type": "DENY" + } + ] +} + `) + }) +} + +func mockCreateResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "accessList": [ + { + "address": "206.160.163.21", + "type": "DENY" + }, + { + "address": "206.160.165.11", + "type": "DENY" + } + ] +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteAllResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + + for k, v := range ids { + fids := r.Form["id"] + th.AssertEquals(t, strconv.Itoa(v), fids[k]) + } + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteResponse(t *testing.T, lbID, networkID int) { + th.Mux.HandleFunc(_rootURL(lbID)+"/"+strconv.Itoa(networkID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/requests.go new file mode 100644 index 000000000..d4ce7c01f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/requests.go @@ -0,0 +1,111 @@ +package acl + +import ( + "errors" + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List is the operation responsible for returning a paginated collection of +// network items that define a load balancer's access list. +func List(client *gophercloud.ServiceClient, lbID int) pagination.Pager { + url := rootURL(client, lbID) + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return AccessListPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder is the interface responsible for generating the JSON +// for a Create operation. +type CreateOptsBuilder interface { + ToAccessListCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is a slice of CreateOpt structs, that allow the user to create +// multiple nodes in a single operation (one node per CreateOpt). +type CreateOpts []CreateOpt + +// CreateOpt represents the options to create a single node. +type CreateOpt struct { + // Required - the IP address or CIDR for item to add to access list. + Address string + + // Required - the type of the node. Either ALLOW or DENY. + Type Type +} + +// ToAccessListCreateMap converts a slice of options into a map that can be +// used for the JSON. +func (opts CreateOpts) ToAccessListCreateMap() (map[string]interface{}, error) { + type itemMap map[string]interface{} + items := []itemMap{} + + for k, v := range opts { + if v.Address == "" { + return itemMap{}, fmt.Errorf("Address is a required attribute, none provided for %d CreateOpt element", k) + } + if v.Type != ALLOW && v.Type != DENY { + return itemMap{}, fmt.Errorf("Type must be ALLOW or DENY") + } + + item := make(itemMap) + item["address"] = v.Address + item["type"] = v.Type + + items = append(items, item) + } + + return itemMap{"accessList": items}, nil +} + +// Create is the operation responsible for adding network items to the access +// rules for a particular load balancer. If network items already exist, the +// new item will be appended. A single IP address or subnet range is considered +// unique and cannot be duplicated. +func Create(client *gophercloud.ServiceClient, loadBalancerID int, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToAccessListCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = client.Post(rootURL(client, loadBalancerID), reqBody, nil, nil) + return res +} + +// BulkDelete will delete multiple network items from a load balancer's access +// list in a single operation. +func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, itemIDs []int) DeleteResult { + var res DeleteResult + + if len(itemIDs) > 10 || len(itemIDs) == 0 { + res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 item IDs") + return res + } + + url := rootURL(c, loadBalancerID) + url += gophercloud.IDSliceToQueryString("id", itemIDs) + + _, res.Err = c.Delete(url, nil) + return res +} + +// Delete will remove a single network item from a load balancer's access list. +func Delete(c *gophercloud.ServiceClient, lbID, itemID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, lbID, itemID), nil) + return res +} + +// DeleteAll will delete the entire contents of a load balancer's access list, +// effectively resetting it and allowing all traffic. +func DeleteAll(c *gophercloud.ServiceClient, lbID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(rootURL(c, lbID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/results.go new file mode 100644 index 000000000..9ea5ea2f4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/results.go @@ -0,0 +1,72 @@ +package acl + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// AccessList represents the rules of network access to a particular load +// balancer. +type AccessList []NetworkItem + +// NetworkItem describes how an IP address or entire subnet may interact with a +// load balancer. +type NetworkItem struct { + // The IP address or subnet (CIDR) that defines the network item. + Address string + + // The numeric unique ID for this item. + ID int + + // Either ALLOW or DENY. + Type Type +} + +// Type defines how an item may connect to the load balancer. +type Type string + +// Convenience consts. +const ( + ALLOW Type = "ALLOW" + DENY Type = "DENY" +) + +// AccessListPage is the page returned by a pager for traversing over a +// collection of network items in an access list. +type AccessListPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an AccessListPage struct is empty. +func (p AccessListPage) IsEmpty() (bool, error) { + is, err := ExtractAccessList(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractAccessList accepts a Page struct, specifically an AccessListPage +// struct, and extracts the elements into a slice of NetworkItem structs. In +// other words, a generic collection is mapped into a relevant slice. +func ExtractAccessList(page pagination.Page) (AccessList, error) { + var resp struct { + List AccessList `mapstructure:"accessList" json:"accessList"` + } + + err := mapstructure.Decode(page.(AccessListPage).Body, &resp) + + return resp.List, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/urls.go new file mode 100644 index 000000000..e373fa1d8 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/acl/urls.go @@ -0,0 +1,20 @@ +package acl + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + aclPath = "accesslist" +) + +func resourceURL(c *gophercloud.ServiceClient, lbID, networkID int) string { + return c.ServiceURL(path, strconv.Itoa(lbID), aclPath, strconv.Itoa(networkID)) +} + +func rootURL(c *gophercloud.ServiceClient, lbID int) string { + return c.ServiceURL(path, strconv.Itoa(lbID), aclPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/doc.go new file mode 100644 index 000000000..05f003285 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/doc.go @@ -0,0 +1,44 @@ +/* +Package lbs provides information and interaction with the Load Balancer API +resource for the Rackspace Cloud Load Balancer service. + +A load balancer is a logical device which belongs to a cloud account. It is +used to distribute workloads between multiple back-end systems or services, +based on the criteria defined as part of its configuration. This configuration +is defined using the Create operation, and can be updated with Update. + +To conserve IPv4 address space, it is highly recommended that you share Virtual +IPs between load balancers. If you have at least one load balancer, you may +create subsequent ones that share a single virtual IPv4 and/or a single IPv6 by +passing in a virtual IP ID to the Update operation (instead of a type). This +feature is also highly desirable if you wish to load balance both an insecure +and secure protocol using one IP or DNS name. In order to share a virtual IP, +each Load Balancer must utilize a unique port. + +All load balancers have a Status attribute that shows the current configuration +status of the device. This status is immutable by the caller and is updated +automatically based on state changes within the service. When a load balancer +is first created, it is placed into a BUILD state while the configuration is +being generated and applied based on the request. Once the configuration is +applied and finalized, it is in an ACTIVE status. In the event of a +configuration change or update, the status of the load balancer changes to +PENDING_UPDATE to signify configuration changes are in progress but have not yet +been finalized. Load balancers in a SUSPENDED status are configured to reject +traffic and do not forward requests to back-end nodes. + +An HTTP load balancer has the X-Forwarded-For (XFF) HTTP header set by default. +This header contains the originating IP address of a client connecting to a web +server through an HTTP proxy or load balancer, which many web applications are +already designed to use when determining the source address for a request. + +It also includes the X-Forwarded-Proto (XFP) HTTP header, which has been added +for identifying the originating protocol of an HTTP request as "http" or +"https" depending on which protocol the client requested. This is useful when +using SSL termination. + +Finally, it also includes the X-Forwarded-Port HTTP header, which has been +added for being able to generate secure URLs containing the specified port. +This header, along with the X-Forwarded-For header, provides the needed +information to the underlying application servers. +*/ +package lbs diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/fixtures.go new file mode 100644 index 000000000..6325310db --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/fixtures.go @@ -0,0 +1,584 @@ +package lbs + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func mockListLBResponse(t *testing.T) { + th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "loadBalancers":[ + { + "name":"lb-site1", + "id":71, + "protocol":"HTTP", + "port":80, + "algorithm":"RANDOM", + "status":"ACTIVE", + "nodeCount":3, + "virtualIps":[ + { + "id":403, + "address":"206.55.130.1", + "type":"PUBLIC", + "ipVersion":"IPV4" + } + ], + "created":{ + "time":"2010-11-30T03:23:42Z" + }, + "updated":{ + "time":"2010-11-30T03:23:44Z" + } + }, + { + "name":"lb-site2", + "id":72, + "created":{ + "time":"2011-11-30T03:23:42Z" + }, + "updated":{ + "time":"2011-11-30T03:23:44Z" + } + }, + { + "name":"lb-site3", + "id":73, + "created":{ + "time":"2012-11-30T03:23:42Z" + }, + "updated":{ + "time":"2012-11-30T03:23:44Z" + } + } + ] +} + `) + }) +} + +func mockCreateLBResponse(t *testing.T) { + th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "loadBalancer": { + "name": "a-new-loadbalancer", + "port": 80, + "protocol": "HTTP", + "virtualIps": [ + { + "id": 2341 + }, + { + "id": 900001 + } + ], + "nodes": [ + { + "address": "10.1.1.1", + "port": 80, + "condition": "ENABLED" + } + ] + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + + fmt.Fprintf(w, ` +{ + "loadBalancer": { + "name": "a-new-loadbalancer", + "id": 144, + "protocol": "HTTP", + "halfClosed": false, + "port": 83, + "algorithm": "RANDOM", + "status": "BUILD", + "timeout": 30, + "cluster": { + "name": "ztm-n01.staging1.lbaas.rackspace.net" + }, + "nodes": [ + { + "address": "10.1.1.1", + "id": 653, + "port": 80, + "status": "ONLINE", + "condition": "ENABLED", + "weight": 1 + } + ], + "virtualIps": [ + { + "address": "206.10.10.210", + "id": 39, + "type": "PUBLIC", + "ipVersion": "IPV4" + }, + { + "address": "2001:4801:79f1:0002:711b:be4c:0000:0021", + "id": 900001, + "type": "PUBLIC", + "ipVersion": "IPV6" + } + ], + "created": { + "time": "2010-11-30T03:23:42Z" + }, + "updated": { + "time": "2010-11-30T03:23:44Z" + }, + "connectionLogging": { + "enabled": false + } + } +} + `) + }) +} + +func mockBatchDeleteLBResponse(t *testing.T, ids []int) { + th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + + for k, v := range ids { + fids := r.Form["id"] + th.AssertEquals(t, strconv.Itoa(v), fids[k]) + } + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteLBResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockGetLBResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "loadBalancer": { + "id": 2000, + "name": "sample-loadbalancer", + "protocol": "HTTP", + "port": 80, + "algorithm": "RANDOM", + "status": "ACTIVE", + "timeout": 30, + "connectionLogging": { + "enabled": true + }, + "virtualIps": [ + { + "id": 1000, + "address": "206.10.10.210", + "type": "PUBLIC", + "ipVersion": "IPV4" + } + ], + "nodes": [ + { + "id": 1041, + "address": "10.1.1.1", + "port": 80, + "condition": "ENABLED", + "status": "ONLINE" + }, + { + "id": 1411, + "address": "10.1.1.2", + "port": 80, + "condition": "ENABLED", + "status": "ONLINE" + } + ], + "sessionPersistence": { + "persistenceType": "HTTP_COOKIE" + }, + "connectionThrottle": { + "maxConnections": 100 + }, + "cluster": { + "name": "c1.dfw1" + }, + "created": { + "time": "2010-11-30T03:23:42Z" + }, + "updated": { + "time": "2010-11-30T03:23:44Z" + }, + "sourceAddresses": { + "ipv6Public": "2001:4801:79f1:1::1/64", + "ipv4Servicenet": "10.0.0.0", + "ipv4Public": "10.12.99.28" + } + } +} + `) + }) +} + +func mockUpdateLBResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "loadBalancer": { + "name": "a-new-loadbalancer", + "protocol": "TCP", + "halfClosed": true, + "algorithm": "RANDOM", + "port": 8080, + "timeout": 100, + "httpsRedirect": false + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockListProtocolsResponse(t *testing.T) { + th.Mux.HandleFunc("/loadbalancers/protocols", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "protocols": [ + { + "name": "DNS_TCP", + "port": 53 + }, + { + "name": "DNS_UDP", + "port": 53 + }, + { + "name": "FTP", + "port": 21 + }, + { + "name": "HTTP", + "port": 80 + }, + { + "name": "HTTPS", + "port": 443 + }, + { + "name": "IMAPS", + "port": 993 + }, + { + "name": "IMAPv4", + "port": 143 + }, + { + "name": "LDAP", + "port": 389 + }, + { + "name": "LDAPS", + "port": 636 + }, + { + "name": "MYSQL", + "port": 3306 + }, + { + "name": "POP3", + "port": 110 + }, + { + "name": "POP3S", + "port": 995 + }, + { + "name": "SMTP", + "port": 25 + }, + { + "name": "TCP", + "port": 0 + }, + { + "name": "TCP_CLIENT_FIRST", + "port": 0 + }, + { + "name": "UDP", + "port": 0 + }, + { + "name": "UDP_STREAM", + "port": 0 + }, + { + "name": "SFTP", + "port": 22 + }, + { + "name": "TCP_STREAM", + "port": 0 + } + ] +} + `) + }) +} + +func mockListAlgorithmsResponse(t *testing.T) { + th.Mux.HandleFunc("/loadbalancers/algorithms", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "algorithms": [ + { + "name": "LEAST_CONNECTIONS" + }, + { + "name": "RANDOM" + }, + { + "name": "ROUND_ROBIN" + }, + { + "name": "WEIGHTED_LEAST_CONNECTIONS" + }, + { + "name": "WEIGHTED_ROUND_ROBIN" + } + ] +} + `) + }) +} + +func mockGetLoggingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "connectionLogging": { + "enabled": true + } +} + `) + }) +} + +func mockEnableLoggingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "connectionLogging":{ + "enabled":true + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDisableLoggingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "connectionLogging":{ + "enabled":false + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockGetErrorPageResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "errorpage": { + "content": "DEFAULT ERROR PAGE" + } +} + `) + }) +} + +func mockSetErrorPageResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "errorpage": { + "content": "New error page" + } +} + `) + + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "errorpage": { + "content": "New error page" + } +} + `) + }) +} + +func mockDeleteErrorPageResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusOK) + }) +} + +func mockGetStatsResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/stats", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "connectTimeOut": 10, + "connectError": 20, + "connectFailure": 30, + "dataTimedOut": 40, + "keepAliveTimedOut": 50, + "maxConn": 60, + "currentConn": 40, + "connectTimeOutSsl": 10, + "connectErrorSsl": 20, + "connectFailureSsl": 30, + "dataTimedOutSsl": 40, + "keepAliveTimedOutSsl": 50, + "maxConnSsl": 60, + "currentConnSsl": 40 +} + `) + }) +} + +func mockGetCachingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "contentCaching": { + "enabled": true + } +} + `) + }) +} + +func mockEnableCachingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "contentCaching":{ + "enabled":true + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDisableCachingResponse(t *testing.T, id int) { + th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "contentCaching":{ + "enabled":false + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/requests.go new file mode 100644 index 000000000..46f5f02a4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/requests.go @@ -0,0 +1,497 @@ +package lbs + +import ( + "errors" + + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/rackspace/lb/v1/acl" + "github.com/rackspace/gophercloud/rackspace/lb/v1/monitors" + "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes" + "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions" + "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle" + "github.com/rackspace/gophercloud/rackspace/lb/v1/vips" +) + +var ( + errNameRequired = errors.New("Name is a required attribute") + errTimeoutExceeded = errors.New("Timeout must be less than 120") +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToLBListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. +type ListOpts struct { + ChangesSince string `q:"changes-since"` + Status Status `q:"status"` + NodeAddr string `q:"nodeaddress"` + Marker string `q:"marker"` + Limit int `q:"limit"` +} + +// ToLBListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToLBListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List is the operation responsible for returning a paginated collection of +// load balancers. You may pass in a ListOpts struct to filter results. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(client) + if opts != nil { + query, err := opts.ToLBListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return LBPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToLBCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Required - name of the load balancer to create. The name must be 128 + // characters or fewer in length, and all UTF-8 characters are valid. + Name string + + // Optional - nodes to be added. + Nodes []nodes.Node + + // Required - protocol of the service that is being load balanced. + // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html + // for a full list of supported protocols. + Protocol string + + // Optional - enables or disables Half-Closed support for the load balancer. + // Half-Closed support provides the ability for one end of the connection to + // terminate its output, while still receiving data from the other end. Only + // available for TCP/TCP_CLIENT_FIRST protocols. + HalfClosed gophercloud.EnabledState + + // Optional - the type of virtual IPs you want associated with the load + // balancer. + VIPs []vips.VIP + + // Optional - the access list management feature allows fine-grained network + // access controls to be applied to the load balancer virtual IP address. + AccessList *acl.AccessList + + // Optional - algorithm that defines how traffic should be directed between + // back-end nodes. + Algorithm string + + // Optional - current connection logging configuration. + ConnectionLogging *ConnectionLogging + + // Optional - specifies a limit on the number of connections per IP address + // to help mitigate malicious or abusive traffic to your applications. + ConnThrottle *throttle.ConnectionThrottle + + // Optional - the type of health monitor check to perform to ensure that the + // service is performing properly. + HealthMonitor *monitors.Monitor + + // Optional - arbitrary information that can be associated with each LB. + Metadata map[string]interface{} + + // Optional - port number for the service you are load balancing. + Port int + + // Optional - the timeout value for the load balancer and communications with + // its nodes. Defaults to 30 seconds with a maximum of 120 seconds. + Timeout int + + // Optional - specifies whether multiple requests from clients are directed + // to the same node. + SessionPersistence *sessions.SessionPersistence + + // Optional - enables or disables HTTP to HTTPS redirection for the load + // balancer. When enabled, any HTTP request returns status code 301 (Moved + // Permanently), and the requester is redirected to the requested URL via the + // HTTPS protocol on port 443. For example, http://example.com/page.html + // would be redirected to https://example.com/page.html. Only available for + // HTTPS protocol (port=443), or HTTP protocol with a properly configured SSL + // termination (secureTrafficOnly=true, securePort=443). + HTTPSRedirect gophercloud.EnabledState +} + +// ToLBCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToLBCreateMap() (map[string]interface{}, error) { + lb := make(map[string]interface{}) + + if opts.Name == "" { + return lb, errNameRequired + } + if opts.Timeout > 120 { + return lb, errTimeoutExceeded + } + + lb["name"] = opts.Name + + if len(opts.Nodes) > 0 { + nodes := []map[string]interface{}{} + for _, n := range opts.Nodes { + nodes = append(nodes, map[string]interface{}{ + "address": n.Address, + "port": n.Port, + "condition": n.Condition, + }) + } + lb["nodes"] = nodes + } + + if opts.Protocol != "" { + lb["protocol"] = opts.Protocol + } + if opts.HalfClosed != nil { + lb["halfClosed"] = opts.HalfClosed + } + if len(opts.VIPs) > 0 { + lb["virtualIps"] = opts.VIPs + } + if opts.AccessList != nil { + lb["accessList"] = &opts.AccessList + } + if opts.Algorithm != "" { + lb["algorithm"] = opts.Algorithm + } + if opts.ConnectionLogging != nil { + lb["connectionLogging"] = &opts.ConnectionLogging + } + if opts.ConnThrottle != nil { + lb["connectionThrottle"] = &opts.ConnThrottle + } + if opts.HealthMonitor != nil { + lb["healthMonitor"] = &opts.HealthMonitor + } + if len(opts.Metadata) != 0 { + lb["metadata"] = opts.Metadata + } + if opts.Port > 0 { + lb["port"] = opts.Port + } + if opts.Timeout > 0 { + lb["timeout"] = opts.Timeout + } + if opts.SessionPersistence != nil { + lb["sessionPersistence"] = &opts.SessionPersistence + } + if opts.HTTPSRedirect != nil { + lb["httpsRedirect"] = &opts.HTTPSRedirect + } + + return map[string]interface{}{"loadBalancer": lb}, nil +} + +// Create is the operation responsible for asynchronously provisioning a new +// load balancer based on the configuration defined in CreateOpts. Once the +// request is validated and progress has started on the provisioning process, a +// response struct is returned. When extracted (with Extract()), you have +// to the load balancer's unique ID and status. +// +// Once an ID is attained, you can check on the progress of the operation by +// calling Get and passing in the ID. If the corresponding request cannot be +// fulfilled due to insufficient or invalid data, an HTTP 400 (Bad Request) +// error response is returned with information regarding the nature of the +// failure in the body of the response. Failures in the validation process are +// non-recoverable and require the caller to correct the cause of the failure. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToLBCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) + return res +} + +// Get is the operation responsible for providing detailed information +// regarding a specific load balancer which is configured and associated with +// your account. This operation is not capable of returning details for a load +// balancer which has been deleted. +func Get(c *gophercloud.ServiceClient, id int) GetResult { + var res GetResult + + _, res.Err = c.Get(resourceURL(c, id), &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// BulkDelete removes all the load balancers referenced in the slice of IDs. +// Any and all configuration data associated with these load balancers is +// immediately purged and is not recoverable. +// +// If one of the items in the list cannot be removed due to its current status, +// a 400 Bad Request error is returned along with the IDs of the ones the +// system identified as potential failures for this request. +func BulkDelete(c *gophercloud.ServiceClient, ids []int) DeleteResult { + var res DeleteResult + + if len(ids) > 10 || len(ids) == 0 { + res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 LB IDs") + return res + } + + url := rootURL(c) + url += gophercloud.IDSliceToQueryString("id", ids) + + _, res.Err = c.Delete(url, nil) + return res +} + +// Delete removes a single load balancer. +func Delete(c *gophercloud.ServiceClient, id int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, id), nil) + return res +} + +// UpdateOptsBuilder represents a type that can be converted into a JSON-like +// map structure. +type UpdateOptsBuilder interface { + ToLBUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts represents the options for updating an existing load balancer. +type UpdateOpts struct { + // Optional - new name of the load balancer. + Name string + + // Optional - the new protocol you want your load balancer to have. + // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html + // for a full list of supported protocols. + Protocol string + + // Optional - see the HalfClosed field in CreateOpts for more information. + HalfClosed gophercloud.EnabledState + + // Optional - see the Algorithm field in CreateOpts for more information. + Algorithm string + + // Optional - see the Port field in CreateOpts for more information. + Port int + + // Optional - see the Timeout field in CreateOpts for more information. + Timeout int + + // Optional - see the HTTPSRedirect field in CreateOpts for more information. + HTTPSRedirect gophercloud.EnabledState +} + +// ToLBUpdateMap casts an UpdateOpts struct to a map. +func (opts UpdateOpts) ToLBUpdateMap() (map[string]interface{}, error) { + lb := make(map[string]interface{}) + + if opts.Name != "" { + lb["name"] = opts.Name + } + if opts.Protocol != "" { + lb["protocol"] = opts.Protocol + } + if opts.HalfClosed != nil { + lb["halfClosed"] = opts.HalfClosed + } + if opts.Algorithm != "" { + lb["algorithm"] = opts.Algorithm + } + if opts.Port > 0 { + lb["port"] = opts.Port + } + if opts.Timeout > 0 { + lb["timeout"] = opts.Timeout + } + if opts.HTTPSRedirect != nil { + lb["httpsRedirect"] = &opts.HTTPSRedirect + } + + return map[string]interface{}{"loadBalancer": lb}, nil +} + +// Update is the operation responsible for asynchronously updating the +// attributes of a specific load balancer. Upon successful validation of the +// request, the service returns a 202 Accepted response, and the load balancer +// enters a PENDING_UPDATE state. A user can poll the load balancer with Get to +// wait for the changes to be applied. When this happens, the load balancer will +// return to an ACTIVE state. +func Update(c *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToLBUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(resourceURL(c, id), reqBody, nil, nil) + return res +} + +// ListProtocols is the operation responsible for returning a paginated +// collection of load balancer protocols. +func ListProtocols(client *gophercloud.ServiceClient) pagination.Pager { + url := protocolsURL(client) + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return ProtocolPage{pagination.SinglePageBase(r)} + }) +} + +// ListAlgorithms is the operation responsible for returning a paginated +// collection of load balancer algorithms. +func ListAlgorithms(client *gophercloud.ServiceClient) pagination.Pager { + url := algorithmsURL(client) + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return AlgorithmPage{pagination.SinglePageBase(r)} + }) +} + +// IsLoggingEnabled returns true if the load balancer has connection logging +// enabled and false if not. +func IsLoggingEnabled(client *gophercloud.ServiceClient, id int) (bool, error) { + var body interface{} + + _, err := client.Get(loggingURL(client, id), &body, nil) + if err != nil { + return false, err + } + + var resp struct { + CL struct { + Enabled bool `mapstructure:"enabled"` + } `mapstructure:"connectionLogging"` + } + + err = mapstructure.Decode(body, &resp) + return resp.CL.Enabled, err +} + +func toConnLoggingMap(state bool) map[string]map[string]bool { + return map[string]map[string]bool{ + "connectionLogging": map[string]bool{"enabled": state}, + } +} + +// EnableLogging will enable connection logging for a specified load balancer. +func EnableLogging(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult { + var res gophercloud.ErrResult + _, res.Err = client.Put(loggingURL(client, id), toConnLoggingMap(true), nil, nil) + return res +} + +// DisableLogging will disable connection logging for a specified load balancer. +func DisableLogging(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult { + var res gophercloud.ErrResult + _, res.Err = client.Put(loggingURL(client, id), toConnLoggingMap(false), nil, nil) + return res +} + +// GetErrorPage will retrieve the current error page for the load balancer. +func GetErrorPage(client *gophercloud.ServiceClient, id int) ErrorPageResult { + var res ErrorPageResult + _, res.Err = client.Get(errorPageURL(client, id), &res.Body, nil) + return res +} + +// SetErrorPage will set the HTML of the load balancer's error page to a +// specific value. +func SetErrorPage(client *gophercloud.ServiceClient, id int, html string) ErrorPageResult { + var res ErrorPageResult + + type stringMap map[string]string + reqBody := map[string]stringMap{"errorpage": stringMap{"content": html}} + + _, res.Err = client.Put(errorPageURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// DeleteErrorPage will delete the current error page for the load balancer. +func DeleteErrorPage(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult { + var res gophercloud.ErrResult + _, res.Err = client.Delete(errorPageURL(client, id), &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// GetStats will retrieve detailed stats related to the load balancer's usage. +func GetStats(client *gophercloud.ServiceClient, id int) StatsResult { + var res StatsResult + _, res.Err = client.Get(statsURL(client, id), &res.Body, nil) + return res +} + +// IsContentCached will check to see whether the specified load balancer caches +// content. When content caching is enabled, recently-accessed files are stored +// on the load balancer for easy retrieval by web clients. Content caching +// improves the performance of high traffic web sites by temporarily storing +// data that was recently accessed. While it's cached, requests for that data +// are served by the load balancer, which in turn reduces load off the back-end +// nodes. The result is improved response times for those requests and less +// load on the web server. +func IsContentCached(client *gophercloud.ServiceClient, id int) (bool, error) { + var body interface{} + + _, err := client.Get(cacheURL(client, id), &body, nil) + if err != nil { + return false, err + } + + var resp struct { + CC struct { + Enabled bool `mapstructure:"enabled"` + } `mapstructure:"contentCaching"` + } + + err = mapstructure.Decode(body, &resp) + return resp.CC.Enabled, err +} + +func toCachingMap(state bool) map[string]map[string]bool { + return map[string]map[string]bool{ + "contentCaching": map[string]bool{"enabled": state}, + } +} + +// EnableCaching will enable content-caching for the specified load balancer. +func EnableCaching(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult { + var res gophercloud.ErrResult + _, res.Err = client.Put(cacheURL(client, id), toCachingMap(true), nil, nil) + return res +} + +// DisableCaching will disable content-caching for the specified load balancer. +func DisableCaching(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult { + var res gophercloud.ErrResult + _, res.Err = client.Put(cacheURL(client, id), toCachingMap(false), nil, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/results.go new file mode 100644 index 000000000..98f3962d7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/results.go @@ -0,0 +1,420 @@ +package lbs + +import ( + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" + "github.com/rackspace/gophercloud/rackspace/lb/v1/acl" + "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes" + "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions" + "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle" + "github.com/rackspace/gophercloud/rackspace/lb/v1/vips" +) + +// Protocol represents the network protocol which the load balancer accepts. +type Protocol struct { + // The name of the protocol, e.g. HTTP, LDAP, FTP, etc. + Name string + + // The port number for the protocol. + Port int +} + +// Algorithm defines how traffic should be directed between back-end nodes. +type Algorithm struct { + // The name of the algorithm, e.g RANDOM, ROUND_ROBIN, etc. + Name string +} + +// Status represents the potential state of a load balancer resource. +type Status string + +const ( + // ACTIVE indicates that the LB is configured properly and ready to serve + // traffic to incoming requests via the configured virtual IPs. + ACTIVE Status = "ACTIVE" + + // BUILD indicates that the LB is being provisioned for the first time and + // configuration is being applied to bring the service online. The service + // cannot yet serve incoming requests. + BUILD Status = "BUILD" + + // PENDINGUPDATE indicates that the LB is online but configuration changes + // are being applied to update the service based on a previous request. + PENDINGUPDATE Status = "PENDING_UPDATE" + + // PENDINGDELETE indicates that the LB is online but configuration changes + // are being applied to begin deletion of the service based on a previous + // request. + PENDINGDELETE Status = "PENDING_DELETE" + + // SUSPENDED indicates that the LB has been taken offline and disabled. + SUSPENDED Status = "SUSPENDED" + + // ERROR indicates that the system encountered an error when attempting to + // configure the load balancer. + ERROR Status = "ERROR" + + // DELETED indicates that the LB has been deleted. + DELETED Status = "DELETED" +) + +// Datetime represents the structure of a Created or Updated field. +type Datetime struct { + Time time.Time `mapstructure:"-"` +} + +// LoadBalancer represents a load balancer API resource. +type LoadBalancer struct { + // Human-readable name for the load balancer. + Name string + + // The unique ID for the load balancer. + ID int + + // Represents the service protocol being load balanced. See Protocol type for + // a list of accepted values. + // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html + // for a full list of supported protocols. + Protocol string + + // Defines how traffic should be directed between back-end nodes. The default + // algorithm is RANDOM. See Algorithm type for a list of accepted values. + Algorithm string + + // The current status of the load balancer. + Status Status + + // The number of load balancer nodes. + NodeCount int `mapstructure:"nodeCount"` + + // Slice of virtual IPs associated with this load balancer. + VIPs []vips.VIP `mapstructure:"virtualIps"` + + // Datetime when the LB was created. + Created Datetime + + // Datetime when the LB was created. + Updated Datetime + + // Port number for the service you are load balancing. + Port int + + // HalfClosed provides the ability for one end of the connection to + // terminate its output while still receiving data from the other end. This + // is only available on TCP/TCP_CLIENT_FIRST protocols. + HalfClosed bool + + // Timeout represents the timeout value between a load balancer and its + // nodes. Defaults to 30 seconds with a maximum of 120 seconds. + Timeout int + + // The cluster name. + Cluster Cluster + + // Nodes shows all the back-end nodes which are associated with the load + // balancer. These are the devices which are delivered traffic. + Nodes []nodes.Node + + // Current connection logging configuration. + ConnectionLogging ConnectionLogging + + // SessionPersistence specifies whether multiple requests from clients are + // directed to the same node. + SessionPersistence sessions.SessionPersistence + + // ConnectionThrottle specifies a limit on the number of connections per IP + // address to help mitigate malicious or abusive traffic to your applications. + ConnectionThrottle throttle.ConnectionThrottle + + // The source public and private IP addresses. + SourceAddrs SourceAddrs `mapstructure:"sourceAddresses"` + + // Represents the access rules for this particular load balancer. IP addresses + // or subnet ranges, depending on their type (ALLOW or DENY), can be permitted + // or blocked. + AccessList acl.AccessList +} + +// SourceAddrs represents the source public and private IP addresses. +type SourceAddrs struct { + IPv4Public string `json:"ipv4Public" mapstructure:"ipv4Public"` + IPv4Private string `json:"ipv4Servicenet" mapstructure:"ipv4Servicenet"` + IPv6Public string `json:"ipv6Public" mapstructure:"ipv6Public"` + IPv6Private string `json:"ipv6Servicenet" mapstructure:"ipv6Servicenet"` +} + +// ConnectionLogging - temp +type ConnectionLogging struct { + Enabled bool +} + +// Cluster - temp +type Cluster struct { + Name string +} + +// LBPage is the page returned by a pager when traversing over a collection of +// LBs. +type LBPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks whether a NetworkPage struct is empty. +func (p LBPage) IsEmpty() (bool, error) { + is, err := ExtractLBs(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractLBs accepts a Page struct, specifically a LBPage struct, and extracts +// the elements into a slice of LoadBalancer structs. In other words, a generic +// collection is mapped into a relevant slice. +func ExtractLBs(page pagination.Page) ([]LoadBalancer, error) { + var resp struct { + LBs []LoadBalancer `mapstructure:"loadBalancers" json:"loadBalancers"` + } + + coll := page.(LBPage).Body + err := mapstructure.Decode(coll, &resp) + + s := reflect.ValueOf(coll.(map[string]interface{})["loadBalancers"]) + + for i := 0; i < s.Len(); i++ { + val := (s.Index(i).Interface()).(map[string]interface{}) + + ts, err := extractTS(val, "created") + if err != nil { + return resp.LBs, err + } + resp.LBs[i].Created.Time = ts + + ts, err = extractTS(val, "updated") + if err != nil { + return resp.LBs, err + } + resp.LBs[i].Updated.Time = ts + } + + return resp.LBs, err +} + +func extractTS(body map[string]interface{}, key string) (time.Time, error) { + val := body[key].(map[string]interface{}) + return time.Parse(time.RFC3339, val["time"].(string)) +} + +type commonResult struct { + gophercloud.Result +} + +// Extract interprets any commonResult as a LB, if possible. +func (r commonResult) Extract() (*LoadBalancer, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + LB LoadBalancer `mapstructure:"loadBalancer"` + } + + err := mapstructure.Decode(r.Body, &response) + + json := r.Body.(map[string]interface{}) + lb := json["loadBalancer"].(map[string]interface{}) + + ts, err := extractTS(lb, "created") + if err != nil { + return nil, err + } + response.LB.Created.Time = ts + + ts, err = extractTS(lb, "updated") + if err != nil { + return nil, err + } + response.LB.Updated.Time = ts + + return &response.LB, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// ProtocolPage is the page returned by a pager when traversing over a +// collection of LB protocols. +type ProtocolPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether a ProtocolPage struct is empty. +func (p ProtocolPage) IsEmpty() (bool, error) { + is, err := ExtractProtocols(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractProtocols accepts a Page struct, specifically a ProtocolPage struct, +// and extracts the elements into a slice of Protocol structs. In other +// words, a generic collection is mapped into a relevant slice. +func ExtractProtocols(page pagination.Page) ([]Protocol, error) { + var resp struct { + Protocols []Protocol `mapstructure:"protocols" json:"protocols"` + } + err := mapstructure.Decode(page.(ProtocolPage).Body, &resp) + return resp.Protocols, err +} + +// AlgorithmPage is the page returned by a pager when traversing over a +// collection of LB algorithms. +type AlgorithmPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether an AlgorithmPage struct is empty. +func (p AlgorithmPage) IsEmpty() (bool, error) { + is, err := ExtractAlgorithms(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractAlgorithms accepts a Page struct, specifically an AlgorithmPage struct, +// and extracts the elements into a slice of Algorithm structs. In other +// words, a generic collection is mapped into a relevant slice. +func ExtractAlgorithms(page pagination.Page) ([]Algorithm, error) { + var resp struct { + Algorithms []Algorithm `mapstructure:"algorithms" json:"algorithms"` + } + err := mapstructure.Decode(page.(AlgorithmPage).Body, &resp) + return resp.Algorithms, err +} + +// ErrorPage represents the HTML file that is shown to an end user who is +// attempting to access a load balancer node that is offline/unavailable. +// +// During provisioning, every load balancer is configured with a default error +// page that gets displayed when traffic is requested for an offline node. +// +// You can add a single custom error page with an HTTP-based protocol to a load +// balancer. Page updates override existing content. If a custom error page is +// deleted, or the load balancer is changed to a non-HTTP protocol, the default +// error page is restored. +type ErrorPage struct { + Content string +} + +// ErrorPageResult represents the result of an error page operation - +// specifically getting or creating one. +type ErrorPageResult struct { + gophercloud.Result +} + +// Extract interprets any commonResult as an ErrorPage, if possible. +func (r ErrorPageResult) Extract() (*ErrorPage, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + ErrorPage ErrorPage `mapstructure:"errorpage"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.ErrorPage, err +} + +// Stats represents all the key information about a load balancer's usage. +type Stats struct { + // The number of connections closed by this load balancer because its + // ConnectTimeout interval was exceeded. + ConnectTimeout int `mapstructure:"connectTimeOut"` + + // The number of transaction or protocol errors for this load balancer. + ConnectError int + + // Number of connection failures for this load balancer. + ConnectFailure int + + // Number of connections closed by this load balancer because its Timeout + // interval was exceeded. + DataTimedOut int + + // Number of connections closed by this load balancer because the + // 'keepalive_timeout' interval was exceeded. + KeepAliveTimedOut int + + // The maximum number of simultaneous TCP connections this load balancer has + // processed at any one time. + MaxConnections int `mapstructure:"maxConn"` + + // Number of simultaneous connections active at the time of the request. + CurrentConnections int `mapstructure:"currentConn"` + + // Number of SSL connections closed by this load balancer because the + // ConnectTimeout interval was exceeded. + SSLConnectTimeout int `mapstructure:"connectTimeOutSsl"` + + // Number of SSL transaction or protocol erros in this load balancer. + SSLConnectError int `mapstructure:"connectErrorSsl"` + + // Number of SSL connection failures in this load balancer. + SSLConnectFailure int `mapstructure:"connectFailureSsl"` + + // Number of SSL connections closed by this load balancer because the + // Timeout interval was exceeded. + SSLDataTimedOut int `mapstructure:"dataTimedOutSsl"` + + // Number of SSL connections closed by this load balancer because the + // 'keepalive_timeout' interval was exceeded. + SSLKeepAliveTimedOut int `mapstructure:"keepAliveTimedOutSsl"` + + // Maximum number of simultaneous SSL connections this load balancer has + // processed at any one time. + SSLMaxConnections int `mapstructure:"maxConnSsl"` + + // Number of simultaneous SSL connections active at the time of the request. + SSLCurrentConnections int `mapstructure:"currentConnSsl"` +} + +// StatsResult represents the result of a Stats operation. +type StatsResult struct { + gophercloud.Result +} + +// Extract interprets any commonResult as a Stats struct, if possible. +func (r StatsResult) Extract() (*Stats, error) { + if r.Err != nil { + return nil, r.Err + } + res := &Stats{} + err := mapstructure.Decode(r.Body, res) + return res, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/urls.go new file mode 100644 index 000000000..471a86b0a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/lbs/urls.go @@ -0,0 +1,49 @@ +package lbs + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + protocolsPath = "protocols" + algorithmsPath = "algorithms" + logPath = "connectionlogging" + epPath = "errorpage" + stPath = "stats" + cachePath = "contentcaching" +) + +func resourceURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id)) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(path) +} + +func protocolsURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(path, protocolsPath) +} + +func algorithmsURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(path, algorithmsPath) +} + +func loggingURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), logPath) +} + +func errorPageURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), epPath) +} + +func statsURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), stPath) +} + +func cacheURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), cachePath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/doc.go new file mode 100644 index 000000000..2c5be75ae --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/doc.go @@ -0,0 +1,21 @@ +/* +Package monitors provides information and interaction with the Health Monitor +API resource for the Rackspace Cloud Load Balancer service. + +The load balancing service includes a health monitoring resource that +periodically checks your back-end nodes to ensure they are responding correctly. +If a node does not respond, it is removed from rotation until the health monitor +determines that the node is functional. In addition to being performed +periodically, a health check also executes against every new node that is +added, to ensure that the node is operating properly before allowing it to +service traffic. Only one health monitor is allowed to be enabled on a load +balancer at a time. + +As part of a good strategy for monitoring connections, secondary nodes should +also be created which provide failover for effectively routing traffic in case +the primary node fails. This is an additional feature that ensures that you +remain up in case your primary node fails. + +There are three types of health monitor: CONNECT, HTTP and HTTPS. +*/ +package monitors diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/fixtures.go new file mode 100644 index 000000000..a565abced --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/fixtures.go @@ -0,0 +1,87 @@ +package monitors + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(lbID int) string { + return "/loadbalancers/" + strconv.Itoa(lbID) + "/healthmonitor" +} + +func mockGetResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "healthMonitor": { + "type": "CONNECT", + "delay": 10, + "timeout": 10, + "attemptsBeforeDeactivation": 3 + } +} + `) + }) +} + +func mockUpdateConnectResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "healthMonitor": { + "type": "CONNECT", + "delay": 10, + "timeout": 10, + "attemptsBeforeDeactivation": 3 + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockUpdateHTTPResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "healthMonitor": { + "attemptsBeforeDeactivation": 3, + "bodyRegex": "{regex}", + "delay": 10, + "path": "/foo", + "statusRegex": "200", + "timeout": 10, + "type": "HTTPS" + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/requests.go new file mode 100644 index 000000000..d4ba27653 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/requests.go @@ -0,0 +1,160 @@ +package monitors + +import ( + "errors" + + "github.com/rackspace/gophercloud" +) + +var ( + errAttemptLimit = errors.New("AttemptLimit field must be an int greater than 1 and less than 10") + errDelay = errors.New("Delay field must be an int greater than 1 and less than 10") + errTimeout = errors.New("Timeout field must be an int greater than 1 and less than 10") +) + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. +type UpdateOptsBuilder interface { + ToMonitorUpdateMap() (map[string]interface{}, error) +} + +// UpdateConnectMonitorOpts represents the options needed to update a CONNECT +// monitor. +type UpdateConnectMonitorOpts struct { + // Required - number of permissible monitor failures before removing a node + // from rotation. Must be a number between 1 and 10. + AttemptLimit int + + // Required - the minimum number of seconds to wait before executing the + // health monitor. Must be a number between 1 and 3600. + Delay int + + // Required - maximum number of seconds to wait for a connection to be + // established before timing out. Must be a number between 1 and 300. + Timeout int +} + +// ToMonitorUpdateMap produces a map for updating CONNECT monitors. +func (opts UpdateConnectMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) { + type m map[string]interface{} + + if !gophercloud.IntWithinRange(opts.AttemptLimit, 1, 10) { + return m{}, errAttemptLimit + } + if !gophercloud.IntWithinRange(opts.Delay, 1, 3600) { + return m{}, errDelay + } + if !gophercloud.IntWithinRange(opts.Timeout, 1, 300) { + return m{}, errTimeout + } + + return m{"healthMonitor": m{ + "attemptsBeforeDeactivation": opts.AttemptLimit, + "delay": opts.Delay, + "timeout": opts.Timeout, + "type": CONNECT, + }}, nil +} + +// UpdateHTTPMonitorOpts represents the options needed to update a HTTP monitor. +type UpdateHTTPMonitorOpts struct { + // Required - number of permissible monitor failures before removing a node + // from rotation. Must be a number between 1 and 10. + AttemptLimit int `mapstructure:"attemptsBeforeDeactivation"` + + // Required - the minimum number of seconds to wait before executing the + // health monitor. Must be a number between 1 and 3600. + Delay int + + // Required - maximum number of seconds to wait for a connection to be + // established before timing out. Must be a number between 1 and 300. + Timeout int + + // Required - a regular expression that will be used to evaluate the contents + // of the body of the response. + BodyRegex string + + // Required - the HTTP path that will be used in the sample request. + Path string + + // Required - a regular expression that will be used to evaluate the HTTP + // status code returned in the response. + StatusRegex string + + // Optional - the name of a host for which the health monitors will check. + HostHeader string + + // Required - either HTTP or HTTPS + Type Type +} + +// ToMonitorUpdateMap produces a map for updating HTTP(S) monitors. +func (opts UpdateHTTPMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) { + type m map[string]interface{} + + if !gophercloud.IntWithinRange(opts.AttemptLimit, 1, 10) { + return m{}, errAttemptLimit + } + if !gophercloud.IntWithinRange(opts.Delay, 1, 3600) { + return m{}, errDelay + } + if !gophercloud.IntWithinRange(opts.Timeout, 1, 300) { + return m{}, errTimeout + } + if opts.Type != HTTP && opts.Type != HTTPS { + return m{}, errors.New("Type must either by HTTP or HTTPS") + } + if opts.BodyRegex == "" { + return m{}, errors.New("BodyRegex is a required field") + } + if opts.Path == "" { + return m{}, errors.New("Path is a required field") + } + if opts.StatusRegex == "" { + return m{}, errors.New("StatusRegex is a required field") + } + + json := m{ + "attemptsBeforeDeactivation": opts.AttemptLimit, + "delay": opts.Delay, + "timeout": opts.Timeout, + "type": opts.Type, + "bodyRegex": opts.BodyRegex, + "path": opts.Path, + "statusRegex": opts.StatusRegex, + } + + if opts.HostHeader != "" { + json["hostHeader"] = opts.HostHeader + } + + return m{"healthMonitor": json}, nil +} + +// Update is the operation responsible for updating a health monitor. +func Update(c *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToMonitorUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(rootURL(c, id), reqBody, nil, nil) + return res +} + +// Get is the operation responsible for showing details of a health monitor. +func Get(c *gophercloud.ServiceClient, id int) GetResult { + var res GetResult + _, res.Err = c.Get(rootURL(c, id), &res.Body, nil) + return res +} + +// Delete is the operation responsible for deleting a health monitor. +func Delete(c *gophercloud.ServiceClient, id int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(rootURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/results.go new file mode 100644 index 000000000..eec556f34 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/results.go @@ -0,0 +1,90 @@ +package monitors + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" +) + +// Type represents the type of Monitor. +type Type string + +// Useful constants. +const ( + CONNECT Type = "CONNECT" + HTTP Type = "HTTP" + HTTPS Type = "HTTPS" +) + +// Monitor represents a health monitor API resource. A monitor comes in three +// forms: CONNECT, HTTP or HTTPS. +// +// A CONNECT monitor establishes a basic connection to each node on its defined +// port to ensure that the service is listening properly. The connect monitor +// is the most basic type of health check and does no post-processing or +// protocol-specific health checks. +// +// HTTP and HTTPS health monitors are generally considered more intelligent and +// powerful than CONNECT. It is capable of processing an HTTP or HTTPS response +// to determine the condition of a node. It supports the same basic properties +// as CONNECT and includes additional attributes that are used to evaluate the +// HTTP response. +type Monitor struct { + // Number of permissible monitor failures before removing a node from + // rotation. + AttemptLimit int `mapstructure:"attemptsBeforeDeactivation"` + + // The minimum number of seconds to wait before executing the health monitor. + Delay int + + // Maximum number of seconds to wait for a connection to be established + // before timing out. + Timeout int + + // Type of the health monitor. + Type Type + + // A regular expression that will be used to evaluate the contents of the + // body of the response. + BodyRegex string + + // The name of a host for which the health monitors will check. + HostHeader string + + // The HTTP path that will be used in the sample request. + Path string + + // A regular expression that will be used to evaluate the HTTP status code + // returned in the response. + StatusRegex string +} + +// UpdateResult represents the result of an Update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// DeleteResult represents the result of an Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// Extract interprets any GetResult as a Monitor. +func (r GetResult) Extract() (*Monitor, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + M Monitor `mapstructure:"healthMonitor"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.M, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/urls.go new file mode 100644 index 000000000..0a1e6df5f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/monitors/urls.go @@ -0,0 +1,16 @@ +package monitors + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + monitorPath = "healthmonitor" +) + +func rootURL(c *gophercloud.ServiceClient, lbID int) string { + return c.ServiceURL(path, strconv.Itoa(lbID), monitorPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/doc.go new file mode 100644 index 000000000..49c431894 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/doc.go @@ -0,0 +1,35 @@ +/* +Package nodes provides information and interaction with the Node API resource +for the Rackspace Cloud Load Balancer service. + +Nodes are responsible for servicing the requests received through the load +balancer's virtual IP. A node is usually a virtual machine. By default, the +load balancer employs a basic health check that ensures the node is listening +on its defined port. The node is checked at the time of addition and at regular +intervals as defined by the load balancer's health check configuration. If a +back-end node is not listening on its port, or does not meet the conditions of +the defined check, then connections will not be forwarded to the node, and its +status is changed to OFFLINE. Only nodes that are in an ONLINE status receive +and can service traffic from the load balancer. + +All nodes have an associated status that indicates whether the node is +ONLINE, OFFLINE, or DRAINING. Only nodes that are in ONLINE status can receive +and service traffic from the load balancer. The OFFLINE status represents a +node that cannot accept or service traffic. A node in DRAINING status +represents a node that stops the traffic manager from sending any additional +new connections to the node, but honors established sessions. If the traffic +manager receives a request and session persistence requires that the node is +used, the traffic manager uses it. The status is determined by the passive or +active health monitors. + +If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the +caller should assign the relevant weights to the node as part of the weight +attribute of the node element. When the algorithm of the load balancer is +changed to WEIGHTED_ROUND_ROBIN and the nodes do not already have an assigned +weight, the service automatically sets the weight to 1 for all nodes. + +One or more secondary nodes can be added to a specified load balancer so that +if all the primary nodes fail, traffic can be redirected to secondary nodes. +The type attribute allows configuring the node as either PRIMARY or SECONDARY. +*/ +package nodes diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/fixtures.go new file mode 100644 index 000000000..8899fc5e9 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/fixtures.go @@ -0,0 +1,243 @@ +package nodes + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(lbID int) string { + return "/loadbalancers/" + strconv.Itoa(lbID) + "/nodes" +} + +func _nodeURL(lbID, nodeID int) string { + return _rootURL(lbID) + "/" + strconv.Itoa(nodeID) +} + +func mockListResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "nodes": [ + { + "id": 410, + "address": "10.1.1.1", + "port": 80, + "condition": "ENABLED", + "status": "ONLINE", + "weight": 3, + "type": "PRIMARY" + }, + { + "id": 411, + "address": "10.1.1.2", + "port": 80, + "condition": "ENABLED", + "status": "ONLINE", + "weight": 8, + "type": "SECONDARY" + } + ] +} + `) + }) +} + +func mockCreateResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "nodes": [ + { + "address": "10.2.2.3", + "port": 80, + "condition": "ENABLED", + "type": "PRIMARY" + }, + { + "address": "10.2.2.4", + "port": 81, + "condition": "ENABLED", + "type": "SECONDARY" + } + ] +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + + fmt.Fprintf(w, ` +{ + "nodes": [ + { + "address": "10.2.2.3", + "id": 185, + "port": 80, + "status": "ONLINE", + "condition": "ENABLED", + "weight": 1, + "type": "PRIMARY" + }, + { + "address": "10.2.2.4", + "id": 186, + "port": 81, + "status": "ONLINE", + "condition": "ENABLED", + "weight": 1, + "type": "SECONDARY" + } + ] +} + `) + }) +} + +func mockCreateErrResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "nodes": [ + { + "address": "10.2.2.3", + "port": 80, + "condition": "ENABLED", + "type": "PRIMARY" + }, + { + "address": "10.2.2.4", + "port": 81, + "condition": "ENABLED", + "type": "SECONDARY" + } + ] +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(422) // Unprocessable Entity + + fmt.Fprintf(w, ` +{ + "code": 422, + "message": "Load Balancer '%d' has a status of 'PENDING_UPDATE' and is considered immutable." +} + `, lbID) + }) +} + +func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + + for k, v := range ids { + fids := r.Form["id"] + th.AssertEquals(t, strconv.Itoa(v), fids[k]) + } + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteResponse(t *testing.T, lbID, nodeID int) { + th.Mux.HandleFunc(_nodeURL(lbID, nodeID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockGetResponse(t *testing.T, lbID, nodeID int) { + th.Mux.HandleFunc(_nodeURL(lbID, nodeID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "node": { + "id": 410, + "address": "10.1.1.1", + "port": 80, + "condition": "ENABLED", + "status": "ONLINE", + "weight": 12, + "type": "PRIMARY" + } +} + `) + }) +} + +func mockUpdateResponse(t *testing.T, lbID, nodeID int) { + th.Mux.HandleFunc(_nodeURL(lbID, nodeID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "node": { + "condition": "DRAINING", + "weight": 10, + "type": "SECONDARY" + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockListEventsResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID)+"/events", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "nodeServiceEvents": [ + { + "detailedMessage": "Node is ok", + "nodeId": 373, + "id": 7, + "type": "UPDATE_NODE", + "description": "Node '373' status changed to 'ONLINE' for load balancer '323'", + "category": "UPDATE", + "severity": "INFO", + "relativeUri": "/406271/loadbalancers/323/nodes/373/events", + "accountId": 406271, + "loadbalancerId": 323, + "title": "Node Status Updated", + "author": "Rackspace Cloud", + "created": "10-30-2012 10:18:23" + } + ] +} +`) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/requests.go new file mode 100644 index 000000000..dc2d46c89 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/requests.go @@ -0,0 +1,251 @@ +package nodes + +import ( + "errors" + "fmt" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List is the operation responsible for returning a paginated collection of +// load balancer nodes. It requires the node ID, its parent load balancer ID, +// and optional limit integer (passed in either as a pointer or a nil poitner). +func List(client *gophercloud.ServiceClient, loadBalancerID int, limit *int) pagination.Pager { + url := rootURL(client, loadBalancerID) + if limit != nil { + url += fmt.Sprintf("?limit=%d", limit) + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return NodePage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder is the interface responsible for generating the JSON +// for a Create operation. +type CreateOptsBuilder interface { + ToNodeCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is a slice of CreateOpt structs, that allow the user to create +// multiple nodes in a single operation (one node per CreateOpt). +type CreateOpts []CreateOpt + +// CreateOpt represents the options to create a single node. +type CreateOpt struct { + // Required - the IP address or CIDR for this back-end node. It can either be + // a private IP (ServiceNet) or a public IP. + Address string + + // Optional - the port on which traffic is sent and received. + Port int + + // Optional - the condition of the node. See the consts in Results.go. + Condition Condition + + // Optional - the type of the node. See the consts in Results.go. + Type Type + + // Optional - a pointer to an integer between 0 and 100. + Weight *int +} + +func validateWeight(weight *int) error { + if weight != nil && (*weight > 100 || *weight < 0) { + return errors.New("Weight must be a valid int between 0 and 100") + } + return nil +} + +// ToNodeCreateMap converts a slice of options into a map that can be used for +// the JSON. +func (opts CreateOpts) ToNodeCreateMap() (map[string]interface{}, error) { + type nodeMap map[string]interface{} + nodes := []nodeMap{} + + for k, v := range opts { + if v.Address == "" { + return nodeMap{}, fmt.Errorf("ID is a required attribute, none provided for %d CreateOpt element", k) + } + if weightErr := validateWeight(v.Weight); weightErr != nil { + return nodeMap{}, weightErr + } + + node := make(map[string]interface{}) + node["address"] = v.Address + + if v.Port > 0 { + node["port"] = v.Port + } + if v.Condition != "" { + node["condition"] = v.Condition + } + if v.Type != "" { + node["type"] = v.Type + } + if v.Weight != nil { + node["weight"] = &v.Weight + } + + nodes = append(nodes, node) + } + + return nodeMap{"nodes": nodes}, nil +} + +// Create is the operation responsible for creating a new node on a load +// balancer. Since every load balancer exists in both ServiceNet and the public +// Internet, both private and public IP addresses can be used for nodes. +// +// If nodes need time to boot up services before they become operational, you +// can temporarily prevent traffic from being sent to that node by setting the +// Condition field to DRAINING. Health checks will still be performed; but once +// your node is ready, you can update its condition to ENABLED and have it +// handle traffic. +func Create(client *gophercloud.ServiceClient, loadBalancerID int, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToNodeCreateMap() + if err != nil { + res.Err = err + return res + } + + resp, err := client.Post(rootURL(client, loadBalancerID), reqBody, &res.Body, nil) + + if err != nil { + res.Err = err + return res + } + + pr := pagination.PageResultFromParsed(resp, res.Body) + return CreateResult{pagination.SinglePageBase(pr)} +} + +// BulkDelete is the operation responsible for batch deleting multiple nodes in +// a single operation. It accepts a slice of integer IDs and will remove them +// from the load balancer. The maximum limit is 10 node removals at once. +func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, nodeIDs []int) DeleteResult { + var res DeleteResult + + if len(nodeIDs) > 10 || len(nodeIDs) == 0 { + res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 node IDs") + return res + } + + url := rootURL(c, loadBalancerID) + url += gophercloud.IDSliceToQueryString("id", nodeIDs) + + _, res.Err = c.Delete(url, nil) + return res +} + +// Get is the operation responsible for showing details for a single node. +func Get(c *gophercloud.ServiceClient, lbID, nodeID int) GetResult { + var res GetResult + _, res.Err = c.Get(resourceURL(c, lbID, nodeID), &res.Body, nil) + return res +} + +// UpdateOptsBuilder represents a type that can be converted into a JSON-like +// map structure. +type UpdateOptsBuilder interface { + ToNodeUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts represent the options for updating an existing node. +type UpdateOpts struct { + // Optional - the condition of the node. See the consts in Results.go. + Condition Condition + + // Optional - the type of the node. See the consts in Results.go. + Type Type + + // Optional - a pointer to an integer between 0 and 100. + Weight *int +} + +// ToNodeUpdateMap converts an options struct into a JSON-like map. +func (opts UpdateOpts) ToNodeUpdateMap() (map[string]interface{}, error) { + node := make(map[string]interface{}) + + if opts.Condition != "" { + node["condition"] = opts.Condition + } + if opts.Weight != nil { + if weightErr := validateWeight(opts.Weight); weightErr != nil { + return node, weightErr + } + node["weight"] = &opts.Weight + } + if opts.Type != "" { + node["type"] = opts.Type + } + + return map[string]interface{}{"node": node}, nil +} + +// Update is the operation responsible for updating an existing node. A node's +// IP, port, and status are immutable attributes and cannot be modified. +func Update(c *gophercloud.ServiceClient, lbID, nodeID int, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToNodeUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(resourceURL(c, lbID, nodeID), reqBody, nil, nil) + return res +} + +// Delete is the operation responsible for permanently deleting a node. +func Delete(c *gophercloud.ServiceClient, lbID, nodeID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, lbID, nodeID), nil) + return res +} + +// ListEventsOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListEventsOptsBuilder interface { + ToEventsListQuery() (string, error) +} + +// ListEventsOpts allows the filtering and sorting of paginated collections through +// the API. +type ListEventsOpts struct { + Marker string `q:"marker"` + Limit int `q:"limit"` +} + +// ToEventsListQuery formats a ListOpts into a query string. +func (opts ListEventsOpts) ToEventsListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListEvents is the operation responsible for listing all the events +// associated with the activity between the node and the load balancer. The +// events report errors found with the node. The detailedMessage provides the +// detailed reason for the error. +func ListEvents(client *gophercloud.ServiceClient, loadBalancerID int, opts ListEventsOptsBuilder) pagination.Pager { + url := eventsURL(client, loadBalancerID) + + if opts != nil { + query, err := opts.ToEventsListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return NodeEventPage{pagination.SinglePageBase(r)} + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/results.go new file mode 100644 index 000000000..57835dc4b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/results.go @@ -0,0 +1,213 @@ +package nodes + +import ( + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Node represents a back-end device, usually a virtual machine, that can +// handle traffic. It is assigned traffic based on its parent load balancer. +type Node struct { + // The IP address or CIDR for this back-end node. + Address string + + // The unique ID for this node. + ID int + + // The port on which traffic is sent and received. + Port int + + // The node's status. + Status Status + + // The node's condition. + Condition Condition + + // The priority at which this node will receive traffic if a weighted + // algorithm is used by its parent load balancer. Ranges from 1 to 100. + Weight int + + // Type of node. + Type Type +} + +// Type indicates whether the node is of a PRIMARY or SECONDARY nature. +type Type string + +const ( + // PRIMARY nodes are in the normal rotation to receive traffic from the load + // balancer. + PRIMARY Type = "PRIMARY" + + // SECONDARY nodes are only in the rotation to receive traffic from the load + // balancer when all the primary nodes fail. This provides a failover feature + // that automatically routes traffic to the secondary node in the event that + // the primary node is disabled or in a failing state. Note that active + // health monitoring must be enabled on the load balancer to enable the + // failover feature to the secondary node. + SECONDARY Type = "SECONDARY" +) + +// Condition represents the condition of a node. +type Condition string + +const ( + // ENABLED indicates that the node is permitted to accept new connections. + ENABLED Condition = "ENABLED" + + // DISABLED indicates that the node is not permitted to accept any new + // connections regardless of session persistence configuration. Existing + // connections are forcibly terminated. + DISABLED Condition = "DISABLED" + + // DRAINING indicates that the node is allowed to service existing + // established connections and connections that are being directed to it as a + // result of the session persistence configuration. + DRAINING Condition = "DRAINING" +) + +// Status indicates whether the node can accept service traffic. If a node is +// not listening on its port or does not meet the conditions of the defined +// active health check for the load balancer, then the load balancer does not +// forward connections, and its status is listed as OFFLINE. +type Status string + +const ( + // ONLINE indicates that the node is healthy and capable of receiving traffic + // from the load balancer. + ONLINE Status = "ONLINE" + + // OFFLINE indicates that the node is not in a position to receive service + // traffic. It is usually switched into this state when a health check is not + // satisfied with the node's response time. + OFFLINE Status = "OFFLINE" +) + +// NodePage is the page returned by a pager when traversing over a collection +// of nodes. +type NodePage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether a NodePage struct is empty. +func (p NodePage) IsEmpty() (bool, error) { + is, err := ExtractNodes(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +func commonExtractNodes(body interface{}) ([]Node, error) { + var resp struct { + Nodes []Node `mapstructure:"nodes" json:"nodes"` + } + + err := mapstructure.Decode(body, &resp) + + return resp.Nodes, err +} + +// ExtractNodes accepts a Page struct, specifically a NodePage struct, and +// extracts the elements into a slice of Node structs. In other words, a +// generic collection is mapped into a relevant slice. +func ExtractNodes(page pagination.Page) ([]Node, error) { + return commonExtractNodes(page.(NodePage).Body) +} + +// CreateResult represents the result of a create operation. Since multiple +// nodes can be added in one operation, this result represents multiple nodes +// and should be treated as a typical pagination Page. Use its ExtractNodes +// method to get out a slice of Node structs. +type CreateResult struct { + pagination.SinglePageBase +} + +// ExtractNodes extracts a slice of Node structs from a CreateResult. +func (res CreateResult) ExtractNodes() ([]Node, error) { + if res.Err != nil { + return nil, res.Err + } + return commonExtractNodes(res.Body) +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +type commonResult struct { + gophercloud.Result +} + +// GetResult represents the result of a get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +func (r commonResult) Extract() (*Node, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Node Node `mapstructure:"node"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.Node, err +} + +// NodeEvent represents a service event that occurred between a node and a +// load balancer. +type NodeEvent struct { + ID int + DetailedMessage string + NodeID int + Type string + Description string + Category string + Severity string + RelativeURI string + AccountID int + LoadBalancerID int + Title string + Author string + Created string +} + +// NodeEventPage is a concrete type which embeds the common SinglePageBase +// struct, and is used when traversing node event collections. +type NodeEventPage struct { + pagination.SinglePageBase +} + +// IsEmpty is a concrete function which indicates whether an NodeEventPage is +// empty or not. +func (r NodeEventPage) IsEmpty() (bool, error) { + is, err := ExtractNodeEvents(r) + if err != nil { + return true, err + } + return len(is) == 0, nil +} + +// ExtractNodeEvents accepts a Page struct, specifically a NodeEventPage +// struct, and extracts the elements into a slice of NodeEvent structs. In +// other words, the collection is mapped into a relevant slice. +func ExtractNodeEvents(page pagination.Page) ([]NodeEvent, error) { + var resp struct { + Events []NodeEvent `mapstructure:"nodeServiceEvents" json:"nodeServiceEvents"` + } + + err := mapstructure.Decode(page.(NodeEventPage).Body, &resp) + + return resp.Events, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/urls.go new file mode 100644 index 000000000..2cefee264 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/nodes/urls.go @@ -0,0 +1,25 @@ +package nodes + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + lbPath = "loadbalancers" + nodePath = "nodes" + eventPath = "events" +) + +func resourceURL(c *gophercloud.ServiceClient, lbID, nodeID int) string { + return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath, strconv.Itoa(nodeID)) +} + +func rootURL(c *gophercloud.ServiceClient, lbID int) string { + return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath) +} + +func eventsURL(c *gophercloud.ServiceClient, lbID int) string { + return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath, eventPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/doc.go new file mode 100644 index 000000000..dcec0a87e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/doc.go @@ -0,0 +1,30 @@ +/* +Package sessions provides information and interaction with the Session +Persistence feature of the Rackspace Cloud Load Balancer service. + +Session persistence is a feature of the load balancing service that forces +multiple requests from clients (of the same protocol) to be directed to the +same node. This is common with many web applications that do not inherently +share application state between back-end servers. + +There are two modes to choose from: HTTP_COOKIE and SOURCE_IP. You can only set +one of the session persistence modes on a load balancer, and it can only +support one protocol. If you set HTTP_COOKIE mode for an HTTP load balancer, it +supports session persistence for HTTP requests only. Likewise, if you set +SOURCE_IP mode for an HTTPS load balancer, it supports session persistence for +only HTTPS requests. + +To support session persistence for both HTTP and HTTPS requests concurrently, +choose one of the following options: + +- Use two load balancers, one configured for session persistence for HTTP +requests and the other configured for session persistence for HTTPS requests. +That way, the load balancers support session persistence for both HTTP and +HTTPS requests concurrently, with each load balancer supporting one of the +protocols. + +- Use one load balancer, configure it for session persistence for HTTP requests, +and then enable SSL termination for that load balancer. The load balancer +supports session persistence for both HTTP and HTTPS requests concurrently. +*/ +package sessions diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/fixtures.go new file mode 100644 index 000000000..077ef0470 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/fixtures.go @@ -0,0 +1,59 @@ +package sessions + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(id int) string { + return "/loadbalancers/" + strconv.Itoa(id) + "/sessionpersistence" +} + +func mockGetResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "sessionPersistence": { + "persistenceType": "HTTP_COOKIE" + } +} +`) + }) +} + +func mockEnableResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "sessionPersistence": { + "persistenceType": "HTTP_COOKIE" + } +} + `) + + w.WriteHeader(http.StatusAccepted) + fmt.Fprintf(w, `{}`) + }) +} + +func mockDisableResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/requests.go new file mode 100644 index 000000000..a93d766cd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/requests.go @@ -0,0 +1,63 @@ +package sessions + +import ( + "errors" + + "github.com/rackspace/gophercloud" +) + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. +type CreateOptsBuilder interface { + ToSPCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Required - can either be HTTPCOOKIE or SOURCEIP + Type Type +} + +// ToSPCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToSPCreateMap() (map[string]interface{}, error) { + sp := make(map[string]interface{}) + + if opts.Type == "" { + return sp, errors.New("Type is a required field") + } + + sp["persistenceType"] = opts.Type + return map[string]interface{}{"sessionPersistence": sp}, nil +} + +// Enable is the operation responsible for enabling session persistence for a +// particular load balancer. +func Enable(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) EnableResult { + var res EnableResult + + reqBody, err := opts.ToSPCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, nil) + return res +} + +// Get is the operation responsible for showing details of the session +// persistence configuration for a particular load balancer. +func Get(c *gophercloud.ServiceClient, lbID int) GetResult { + var res GetResult + _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil) + return res +} + +// Disable is the operation responsible for disabling session persistence for a +// particular load balancer. +func Disable(c *gophercloud.ServiceClient, lbID int) DisableResult { + var res DisableResult + _, res.Err = c.Delete(rootURL(c, lbID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/results.go new file mode 100644 index 000000000..fe90e722c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/results.go @@ -0,0 +1,58 @@ +package sessions + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" +) + +// Type represents the type of session persistence being used. +type Type string + +const ( + // HTTPCOOKIE is a session persistence mechanism that inserts an HTTP cookie + // and is used to determine the destination back-end node. This is supported + // for HTTP load balancing only. + HTTPCOOKIE Type = "HTTP_COOKIE" + + // SOURCEIP is a session persistence mechanism that keeps track of the source + // IP address that is mapped and is able to determine the destination + // back-end node. This is supported for HTTPS pass-through and non-HTTP load + // balancing only. + SOURCEIP Type = "SOURCE_IP" +) + +// SessionPersistence indicates how a load balancer is using session persistence +type SessionPersistence struct { + Type Type `mapstructure:"persistenceType"` +} + +// EnableResult represents the result of an enable operation. +type EnableResult struct { + gophercloud.ErrResult +} + +// DisableResult represents the result of a disable operation. +type DisableResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult as an SP, if possible. +func (r GetResult) Extract() (*SessionPersistence, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + SP SessionPersistence `mapstructure:"sessionPersistence"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.SP, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/urls.go new file mode 100644 index 000000000..c4a896d90 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/sessions/urls.go @@ -0,0 +1,16 @@ +package sessions + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + spPath = "sessionpersistence" +) + +func rootURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), spPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/doc.go new file mode 100644 index 000000000..6a2c174ae --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/doc.go @@ -0,0 +1,22 @@ +/* +Package ssl provides information and interaction with the SSL Termination +feature of the Rackspace Cloud Load Balancer service. + +You may only enable and configure SSL termination on load balancers with +non-secure protocols, such as HTTP, but not HTTPS. + +SSL-terminated load balancers decrypt the traffic at the traffic manager and +pass unencrypted traffic to the back-end node. Because of this, the customer's +back-end nodes don't know what protocol the client requested. For this reason, +the X-Forwarded-Proto (XFP) header has been added for identifying the +originating protocol of an HTTP request as "http" or "https" depending on what +protocol the client requested. + +Not every service returns certificates in the proper order. Please verify that +your chain of certificates matches that of walking up the chain from the domain +to the CA root. + +If used for HTTP to HTTPS redirection, the LoadBalancer's securePort attribute +must be set to 443, and its secureTrafficOnly attribute must be true. +*/ +package ssl diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/fixtures.go new file mode 100644 index 000000000..5a52962d4 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/fixtures.go @@ -0,0 +1,196 @@ +package ssl + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(id int) string { + return "/loadbalancers/" + strconv.Itoa(id) + "/ssltermination" +} + +func _certURL(id, certID int) string { + url := _rootURL(id) + "/certificatemappings" + if certID > 0 { + url += "/" + strconv.Itoa(certID) + } + return url +} + +func mockGetResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "sslTermination": { + "certificate": "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "enabled": true, + "secureTrafficOnly": false, + "intermediateCertificate": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n", + "securePort": 443 + } +} +`) + }) +} + +func mockUpdateResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "sslTermination": { + "enabled": true, + "securePort": 443, + "secureTrafficOnly": false, + "privateKey": "foo", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} + `) + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{}`) + }) +} + +func mockDeleteResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusOK) + }) +} + +func mockListCertsResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_certURL(lbID, 0), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "certificateMappings": [ + { + "certificateMapping": { + "id": 123, + "hostName": "rackspace.com" + } + }, + { + "certificateMapping": { + "id": 124, + "hostName": "*.rackspace.com" + } + } + ] +} +`) + }) +} + +func mockAddCertResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_certURL(lbID, 0), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "certificateMapping": { + "hostName": "rackspace.com", + "privateKey":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n", + "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} + `) + + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "certificateMapping": { + "id": 123, + "hostName": "rackspace.com", + "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} + `) + }) +} + +func mockGetCertResponse(t *testing.T, lbID, certID int) { + th.Mux.HandleFunc(_certURL(lbID, certID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "certificateMapping": { + "id": 123, + "hostName": "rackspace.com", + "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} +`) + }) +} + +func mockUpdateCertResponse(t *testing.T, lbID, certID int) { + th.Mux.HandleFunc(_certURL(lbID, certID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "certificateMapping": { + "hostName": "rackspace.com", + "privateKey":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n", + "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} + `) + + w.WriteHeader(http.StatusAccepted) + + fmt.Fprintf(w, ` +{ + "certificateMapping": { + "id": 123, + "hostName": "rackspace.com", + "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n", + "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n" + } +} + `) + }) +} + +func mockDeleteCertResponse(t *testing.T, lbID, certID int) { + th.Mux.HandleFunc(_certURL(lbID, certID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusOK) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/requests.go new file mode 100644 index 000000000..bb53ef896 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/requests.go @@ -0,0 +1,247 @@ +package ssl + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +var ( + errPrivateKey = errors.New("PrivateKey is a required field") + errCertificate = errors.New("Certificate is a required field") + errIntCertificate = errors.New("IntCertificate is a required field") +) + +// UpdateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Update operation in this package. +type UpdateOptsBuilder interface { + ToSSLUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the common options struct used in this package's Update +// operation. +type UpdateOpts struct { + // Required - consult the SSLTermConfig struct for more info. + SecurePort int + + // Required - consult the SSLTermConfig struct for more info. + PrivateKey string + + // Required - consult the SSLTermConfig struct for more info. + Certificate string + + // Required - consult the SSLTermConfig struct for more info. + IntCertificate string + + // Optional - consult the SSLTermConfig struct for more info. + Enabled *bool + + // Optional - consult the SSLTermConfig struct for more info. + SecureTrafficOnly *bool +} + +// ToSSLUpdateMap casts a CreateOpts struct to a map. +func (opts UpdateOpts) ToSSLUpdateMap() (map[string]interface{}, error) { + ssl := make(map[string]interface{}) + + if opts.SecurePort == 0 { + return ssl, errors.New("SecurePort needs to be an integer greater than 0") + } + if opts.PrivateKey == "" { + return ssl, errPrivateKey + } + if opts.Certificate == "" { + return ssl, errCertificate + } + if opts.IntCertificate == "" { + return ssl, errIntCertificate + } + + ssl["securePort"] = opts.SecurePort + ssl["privateKey"] = opts.PrivateKey + ssl["certificate"] = opts.Certificate + ssl["intermediateCertificate"] = opts.IntCertificate + + if opts.Enabled != nil { + ssl["enabled"] = &opts.Enabled + } + + if opts.SecureTrafficOnly != nil { + ssl["secureTrafficOnly"] = &opts.SecureTrafficOnly + } + + return map[string]interface{}{"sslTermination": ssl}, nil +} + +// Update is the operation responsible for updating the SSL Termination +// configuration for a load balancer. +func Update(c *gophercloud.ServiceClient, lbID int, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + + reqBody, err := opts.ToSSLUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// Get is the operation responsible for showing the details of the SSL +// Termination configuration for a load balancer. +func Get(c *gophercloud.ServiceClient, lbID int) GetResult { + var res GetResult + _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil) + return res +} + +// Delete is the operation responsible for deleting the SSL Termination +// configuration for a load balancer. +func Delete(c *gophercloud.ServiceClient, lbID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(rootURL(c, lbID), &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return res +} + +// ListCerts will list all of the certificate mappings associated with a +// SSL-terminated HTTP load balancer. +func ListCerts(c *gophercloud.ServiceClient, lbID int) pagination.Pager { + url := certURL(c, lbID) + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return CertPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateCertOptsBuilder is the interface options structs have to satisfy in +// order to be used in the AddCert operation in this package. +type CreateCertOptsBuilder interface { + ToCertCreateMap() (map[string]interface{}, error) +} + +// CreateCertOpts represents the options used when adding a new certificate mapping. +type CreateCertOpts struct { + HostName string + PrivateKey string + Certificate string + IntCertificate string +} + +// ToCertCreateMap will cast an CreateCertOpts struct to a map for JSON serialization. +func (opts CreateCertOpts) ToCertCreateMap() (map[string]interface{}, error) { + cm := make(map[string]interface{}) + + if opts.HostName == "" { + return cm, errors.New("HostName is a required option") + } + if opts.PrivateKey == "" { + return cm, errPrivateKey + } + if opts.Certificate == "" { + return cm, errCertificate + } + + cm["hostName"] = opts.HostName + cm["privateKey"] = opts.PrivateKey + cm["certificate"] = opts.Certificate + + if opts.IntCertificate != "" { + cm["intermediateCertificate"] = opts.IntCertificate + } + + return map[string]interface{}{"certificateMapping": cm}, nil +} + +// CreateCert will add a new SSL certificate and allow an SSL-terminated HTTP +// load balancer to use it. This feature is useful because it allows multiple +// certificates to be used. The maximum number of certificates that can be +// stored per LB is 20. +func CreateCert(c *gophercloud.ServiceClient, lbID int, opts CreateCertOptsBuilder) CreateCertResult { + var res CreateCertResult + + reqBody, err := opts.ToCertCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(certURL(c, lbID), reqBody, &res.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} + +// GetCert will show the details of an existing SSL certificate. +func GetCert(c *gophercloud.ServiceClient, lbID, certID int) GetCertResult { + var res GetCertResult + _, res.Err = c.Get(certResourceURL(c, lbID, certID), &res.Body, nil) + return res +} + +// UpdateCertOptsBuilder is the interface options structs have to satisfy in +// order to be used in the UpdateCert operation in this package. +type UpdateCertOptsBuilder interface { + ToCertUpdateMap() (map[string]interface{}, error) +} + +// UpdateCertOpts represents the options needed to update a SSL certificate. +type UpdateCertOpts struct { + HostName string + PrivateKey string + Certificate string + IntCertificate string +} + +// ToCertUpdateMap will cast an UpdateCertOpts struct into a map for JSON +// seralization. +func (opts UpdateCertOpts) ToCertUpdateMap() (map[string]interface{}, error) { + cm := make(map[string]interface{}) + + if opts.HostName != "" { + cm["hostName"] = opts.HostName + } + if opts.PrivateKey != "" { + cm["privateKey"] = opts.PrivateKey + } + if opts.Certificate != "" { + cm["certificate"] = opts.Certificate + } + if opts.IntCertificate != "" { + cm["intermediateCertificate"] = opts.IntCertificate + } + + return map[string]interface{}{"certificateMapping": cm}, nil +} + +// UpdateCert is the operation responsible for updating the details of an +// existing SSL certificate. +func UpdateCert(c *gophercloud.ServiceClient, lbID, certID int, opts UpdateCertOptsBuilder) UpdateCertResult { + var res UpdateCertResult + + reqBody, err := opts.ToCertUpdateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(certResourceURL(c, lbID, certID), reqBody, &res.Body, nil) + return res +} + +// DeleteCert is the operation responsible for permanently removing a SSL +// certificate. +func DeleteCert(c *gophercloud.ServiceClient, lbID, certID int) DeleteResult { + var res DeleteResult + + _, res.Err = c.Delete(certResourceURL(c, lbID, certID), &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/results.go new file mode 100644 index 000000000..ead9fcd37 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/results.go @@ -0,0 +1,148 @@ +package ssl + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// SSLTermConfig represents the SSL configuration for a particular load balancer. +type SSLTermConfig struct { + // The port on which the SSL termination load balancer listens for secure + // traffic. The value must be unique to the existing LB protocol/port + // combination + SecurePort int `mapstructure:"securePort"` + + // The private key for the SSL certificate which is validated and verified + // against the provided certificates. + PrivateKey string `mapstructure:"privatekey"` + + // The certificate used for SSL termination, which is validated and verified + // against the key and intermediate certificate if provided. + Certificate string + + // The intermediate certificate (for the user). The intermediate certificate + // is validated and verified against the key and certificate credentials + // provided. A user may only provide this value when accompanied by a + // Certificate, PrivateKey, and SecurePort. It may not be added or updated as + // a single attribute in a future operation. + IntCertificate string `mapstructure:"intermediatecertificate"` + + // Determines if the load balancer is enabled to terminate SSL traffic or not. + // If this is set to false, the load balancer retains its specified SSL + // attributes but does not terminate SSL traffic. + Enabled bool + + // Determines if the load balancer can only accept secure traffic. If set to + // true, the load balancer will not accept non-secure traffic. + SecureTrafficOnly bool +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult as a SSLTermConfig struct, if possible. +func (r GetResult) Extract() (*SSLTermConfig, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + SSL SSLTermConfig `mapstructure:"sslTermination"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.SSL, err +} + +// Certificate represents an SSL certificate associated with an SSL-terminated +// HTTP load balancer. +type Certificate struct { + ID int + HostName string + Certificate string + IntCertificate string `mapstructure:"intermediateCertificate"` +} + +// CertPage represents a page of certificates. +type CertPage struct { + pagination.LinkedPageBase +} + +// IsEmpty checks whether a CertMappingPage struct is empty. +func (p CertPage) IsEmpty() (bool, error) { + is, err := ExtractCerts(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractCerts accepts a Page struct, specifically a CertPage struct, and +// extracts the elements into a slice of Cert structs. In other words, a generic +// collection is mapped into a relevant slice. +func ExtractCerts(page pagination.Page) ([]Certificate, error) { + type NestedMap struct { + Cert Certificate `mapstructure:"certificateMapping" json:"certificateMapping"` + } + var resp struct { + Certs []NestedMap `mapstructure:"certificateMappings" json:"certificateMappings"` + } + + err := mapstructure.Decode(page.(CertPage).Body, &resp) + + slice := []Certificate{} + for _, cert := range resp.Certs { + slice = append(slice, cert.Cert) + } + + return slice, err +} + +type certResult struct { + gophercloud.Result +} + +// Extract interprets a result as a CertMapping struct, if possible. +func (r certResult) Extract() (*Certificate, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + Cert Certificate `mapstructure:"certificateMapping"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.Cert, err +} + +// CreateCertResult represents the result of an CreateCert operation. +type CreateCertResult struct { + certResult +} + +// GetCertResult represents the result of a GetCert operation. +type GetCertResult struct { + certResult +} + +// UpdateCertResult represents the result of an UpdateCert operation. +type UpdateCertResult struct { + certResult +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/urls.go new file mode 100644 index 000000000..aa814b358 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/ssl/urls.go @@ -0,0 +1,25 @@ +package ssl + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + sslPath = "ssltermination" + certPath = "certificatemappings" +) + +func rootURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), sslPath) +} + +func certURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), sslPath, certPath) +} + +func certResourceURL(c *gophercloud.ServiceClient, id, certID int) string { + return c.ServiceURL(path, strconv.Itoa(id), sslPath, certPath, strconv.Itoa(certID)) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/doc.go new file mode 100644 index 000000000..1ed605d36 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/doc.go @@ -0,0 +1,5 @@ +/* +Package throttle provides information and interaction with the Connection +Throttling feature of the Rackspace Cloud Load Balancer service. +*/ +package throttle diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/fixtures.go new file mode 100644 index 000000000..f3e49fa68 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/fixtures.go @@ -0,0 +1,62 @@ +package throttle + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(id int) string { + return "/loadbalancers/" + strconv.Itoa(id) + "/connectionthrottle" +} + +func mockGetResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "connectionThrottle": { + "maxConnections": 100 + } +} +`) + }) +} + +func mockCreateResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "connectionThrottle": { + "maxConnectionRate": 0, + "maxConnections": 200, + "minConnections": 0, + "rateInterval": 0 + } +} + `) + + w.WriteHeader(http.StatusAccepted) + fmt.Fprintf(w, `{}`) + }) +} + +func mockDeleteResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/requests.go new file mode 100644 index 000000000..0446b97a1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/requests.go @@ -0,0 +1,76 @@ +package throttle + +import ( + "errors" + + "github.com/rackspace/gophercloud" +) + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. +type CreateOptsBuilder interface { + ToCTCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Required - the maximum amount of connections per IP address to allow per LB. + MaxConnections int + + // Deprecated as of v1.22. + MaxConnectionRate int + + // Deprecated as of v1.22. + MinConnections int + + // Deprecated as of v1.22. + RateInterval int +} + +// ToCTCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToCTCreateMap() (map[string]interface{}, error) { + ct := make(map[string]interface{}) + + if opts.MaxConnections < 0 || opts.MaxConnections > 100000 { + return ct, errors.New("MaxConnections must be an int between 0 and 100000") + } + + ct["maxConnections"] = opts.MaxConnections + ct["maxConnectionRate"] = opts.MaxConnectionRate + ct["minConnections"] = opts.MinConnections + ct["rateInterval"] = opts.RateInterval + + return map[string]interface{}{"connectionThrottle": ct}, nil +} + +// Create is the operation responsible for creating or updating the connection +// throttling configuration for a load balancer. +func Create(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToCTCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, nil) + return res +} + +// Get is the operation responsible for showing the details of the connection +// throttling configuration for a load balancer. +func Get(c *gophercloud.ServiceClient, lbID int) GetResult { + var res GetResult + _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil) + return res +} + +// Delete is the operation responsible for deleting the connection throttling +// configuration for a load balancer. +func Delete(c *gophercloud.ServiceClient, lbID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(rootURL(c, lbID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/results.go new file mode 100644 index 000000000..db93c6f3f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/results.go @@ -0,0 +1,43 @@ +package throttle + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" +) + +// ConnectionThrottle represents the connection throttle configuration for a +// particular load balancer. +type ConnectionThrottle struct { + MaxConnections int +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + gophercloud.ErrResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} + +// GetResult represents the result of a get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract interprets a GetResult as a SP, if possible. +func (r GetResult) Extract() (*ConnectionThrottle, error) { + if r.Err != nil { + return nil, r.Err + } + + var response struct { + CT ConnectionThrottle `mapstructure:"connectionThrottle"` + } + + err := mapstructure.Decode(r.Body, &response) + + return &response.CT, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/urls.go new file mode 100644 index 000000000..b77f0ac1c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/throttle/urls.go @@ -0,0 +1,16 @@ +package throttle + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + path = "loadbalancers" + ctPath = "connectionthrottle" +) + +func rootURL(c *gophercloud.ServiceClient, id int) string { + return c.ServiceURL(path, strconv.Itoa(id), ctPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/doc.go new file mode 100644 index 000000000..5c3846d44 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/doc.go @@ -0,0 +1,13 @@ +/* +Package vips provides information and interaction with the Virtual IP API +resource for the Rackspace Cloud Load Balancer service. + +A virtual IP (VIP) makes a load balancer accessible by clients. The load +balancing service supports either a public VIP, routable on the public Internet, +or a ServiceNet address, routable only within the region in which the load +balancer resides. + +All load balancers must have at least one virtual IP associated with them at +all times. +*/ +package vips diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/fixtures.go new file mode 100644 index 000000000..158759f7f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/fixtures.go @@ -0,0 +1,88 @@ +package vips + +import ( + "fmt" + "net/http" + "strconv" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + fake "github.com/rackspace/gophercloud/testhelper/client" +) + +func _rootURL(lbID int) string { + return "/loadbalancers/" + strconv.Itoa(lbID) + "/virtualips" +} + +func mockListResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "virtualIps": [ + { + "id": 1000, + "address": "206.10.10.210", + "type": "PUBLIC" + } + ] +} + `) + }) +} + +func mockCreateResponse(t *testing.T, lbID int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + th.TestJSONRequest(t, r, ` +{ + "type":"PUBLIC", + "ipVersion":"IPV6" +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + + fmt.Fprintf(w, ` +{ + "address":"fd24:f480:ce44:91bc:1af2:15ff:0000:0002", + "id":9000134, + "type":"PUBLIC", + "ipVersion":"IPV6" +} + `) + }) +} + +func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) { + th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + + for k, v := range ids { + fids := r.Form["id"] + th.AssertEquals(t, strconv.Itoa(v), fids[k]) + } + + w.WriteHeader(http.StatusAccepted) + }) +} + +func mockDeleteResponse(t *testing.T, lbID, vipID int) { + url := _rootURL(lbID) + "/" + strconv.Itoa(vipID) + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/requests.go new file mode 100644 index 000000000..2bc924f29 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/requests.go @@ -0,0 +1,97 @@ +package vips + +import ( + "errors" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List is the operation responsible for returning a paginated collection of +// load balancer virtual IP addresses. +func List(client *gophercloud.ServiceClient, loadBalancerID int) pagination.Pager { + url := rootURL(client, loadBalancerID) + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return VIPPage{pagination.SinglePageBase(r)} + }) +} + +// CreateOptsBuilder is the interface options structs have to satisfy in order +// to be used in the main Create operation in this package. Since many +// extensions decorate or modify the common logic, it is useful for them to +// satisfy a basic interface in order for them to be used. +type CreateOptsBuilder interface { + ToVIPCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Optional - the ID of an existing virtual IP. By doing this, you are + // allowing load balancers to share IPV6 addresses. + ID string + + // Optional - the type of address. + Type Type + + // Optional - the version of address. + Version Version +} + +// ToVIPCreateMap casts a CreateOpts struct to a map. +func (opts CreateOpts) ToVIPCreateMap() (map[string]interface{}, error) { + lb := make(map[string]interface{}) + + if opts.ID != "" { + lb["id"] = opts.ID + } + if opts.Type != "" { + lb["type"] = opts.Type + } + if opts.Version != "" { + lb["ipVersion"] = opts.Version + } + + return lb, nil +} + +// Create is the operation responsible for assigning a new Virtual IP to an +// existing load balancer resource. Currently, only version 6 IP addresses may +// be added. +func Create(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) CreateResult { + var res CreateResult + + reqBody, err := opts.ToVIPCreateMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(rootURL(c, lbID), reqBody, &res.Body, nil) + return res +} + +// BulkDelete is the operation responsible for batch deleting multiple VIPs in +// a single operation. It accepts a slice of integer IDs and will remove them +// from the load balancer. The maximum limit is 10 VIP removals at once. +func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, vipIDs []int) DeleteResult { + var res DeleteResult + + if len(vipIDs) > 10 || len(vipIDs) == 0 { + res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 VIP IDs") + return res + } + + url := rootURL(c, loadBalancerID) + url += gophercloud.IDSliceToQueryString("id", vipIDs) + + _, res.Err = c.Delete(url, nil) + return res +} + +// Delete is the operation responsible for permanently deleting a VIP. +func Delete(c *gophercloud.ServiceClient, lbID, vipID int) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(resourceURL(c, lbID, vipID), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/results.go new file mode 100644 index 000000000..678b2aff7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/results.go @@ -0,0 +1,89 @@ +package vips + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// VIP represents a Virtual IP API resource. +type VIP struct { + Address string `json:"address,omitempty"` + ID int `json:"id,omitempty"` + Type Type `json:"type,omitempty"` + Version Version `json:"ipVersion,omitempty" mapstructure:"ipVersion"` +} + +// Version represents the version of a VIP. +type Version string + +// Convenient constants to use for type +const ( + IPV4 Version = "IPV4" + IPV6 Version = "IPV6" +) + +// Type represents the type of a VIP. +type Type string + +const ( + // PUBLIC indicates a VIP type that is routable on the public Internet. + PUBLIC Type = "PUBLIC" + + // PRIVATE indicates a VIP type that is routable only on ServiceNet. + PRIVATE Type = "SERVICENET" +) + +// VIPPage is the page returned by a pager when traversing over a collection +// of VIPs. +type VIPPage struct { + pagination.SinglePageBase +} + +// IsEmpty checks whether a VIPPage struct is empty. +func (p VIPPage) IsEmpty() (bool, error) { + is, err := ExtractVIPs(p) + if err != nil { + return true, nil + } + return len(is) == 0, nil +} + +// ExtractVIPs accepts a Page struct, specifically a VIPPage struct, and +// extracts the elements into a slice of VIP structs. In other words, a +// generic collection is mapped into a relevant slice. +func ExtractVIPs(page pagination.Page) ([]VIP, error) { + var resp struct { + VIPs []VIP `mapstructure:"virtualIps" json:"virtualIps"` + } + + err := mapstructure.Decode(page.(VIPPage).Body, &resp) + + return resp.VIPs, err +} + +type commonResult struct { + gophercloud.Result +} + +func (r commonResult) Extract() (*VIP, error) { + if r.Err != nil { + return nil, r.Err + } + + resp := &VIP{} + err := mapstructure.Decode(r.Body, resp) + + return resp, err +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/urls.go new file mode 100644 index 000000000..28f063a0f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/lb/v1/vips/urls.go @@ -0,0 +1,20 @@ +package vips + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +const ( + lbPath = "loadbalancers" + vipPath = "virtualips" +) + +func resourceURL(c *gophercloud.ServiceClient, lbID, nodeID int) string { + return c.ServiceURL(lbPath, strconv.Itoa(lbID), vipPath, strconv.Itoa(nodeID)) +} + +func rootURL(c *gophercloud.ServiceClient, lbID int) string { + return c.ServiceURL(lbPath, strconv.Itoa(lbID), vipPath) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/common/common_tests.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/common/common_tests.go new file mode 100644 index 000000000..129cd63ae --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/common/common_tests.go @@ -0,0 +1,12 @@ +package common + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/testhelper/client" +) + +const TokenID = client.TokenID + +func ServiceClient() *gophercloud.ServiceClient { + return client.ServiceClient() +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/networks/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/networks/delegate.go new file mode 100644 index 000000000..dcb0855db --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/networks/delegate.go @@ -0,0 +1,41 @@ +package networks + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/networking/v2/networks" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// networks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// Get retrieves a specific network based on its unique ID. +func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult { + return os.Get(c, networkID) +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. This operation does not actually require a request body, i.e. the +// CreateOpts struct argument can be empty. +// +// The tenant ID that is contained in the URI is the tenant that creates the +// network. An admin user, however, has the option of specifying another tenant +// ID in the CreateOpts struct. +func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, opts) +} + +// Update accepts a UpdateOpts struct and updates an existing network using the +// values provided. For more information, see the Create function. +func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, networkID, opts) +} + +// Delete accepts a unique ID and deletes the network associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult { + return os.Delete(c, networkID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/ports/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/ports/delegate.go new file mode 100644 index 000000000..95728d185 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/ports/delegate.go @@ -0,0 +1,43 @@ +package ports + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/networking/v2/ports" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// ports. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those ports that are owned by the tenant +// who submits the request, unless the request is submitted by a user with +// administrative rights. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// Get retrieves a specific port based on its unique ID. +func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult { + return os.Get(c, networkID) +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. You must remember to provide a NetworkID value. +// +// NOTE: Currently the SecurityGroup option is not implemented to work with +// Rackspace. +func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, opts) +} + +// Update accepts a UpdateOpts struct and updates an existing port using the +// values provided. +func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, networkID, opts) +} + +// Delete accepts a unique ID and deletes the port associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult { + return os.Delete(c, networkID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/doc.go new file mode 100644 index 000000000..31f744ccd --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/doc.go @@ -0,0 +1,32 @@ +// Package security contains functionality to work with security group and +// security group rules Neutron resources. +// +// Security groups and security group rules allows administrators and tenants +// the ability to specify the type of traffic and direction (ingress/egress) +// that is allowed to pass through a port. A security group is a container for +// security group rules. +// +// When a port is created in Networking it is associated with a security group. +// If a security group is not specified the port is associated with a 'default' +// security group. By default, this group drops all ingress traffic and allows +// all egress. Rules can be added to this group in order to change the behaviour. +// +// The basic characteristics of Neutron Security Groups are: +// +// For ingress traffic (to an instance) +// - Only traffic matched with security group rules are allowed. +// - When there is no rule defined, all traffic is dropped. +// +// For egress traffic (from an instance) +// - Only traffic matched with security group rules are allowed. +// - When there is no rule defined, all egress traffic are dropped. +// - When a new security group is created, rules to allow all egress traffic +// is automatically added. +// +// "default security group" is defined for each tenant. +// - For the default security group a rule which allows intercommunication +// among hosts associated with the default security group is defined by default. +// - As a result, all egress traffic and intercommunication in the default +// group are allowed and all ingress from outside of the default group is +// dropped by default (in the default security group). +package security diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/groups/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/groups/delegate.go new file mode 100644 index 000000000..1e9a23a05 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/groups/delegate.go @@ -0,0 +1,30 @@ +package groups + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// security groups. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts os.ListOpts) pagination.Pager { + return os.List(c, opts) +} + +// Create is an operation which provisions a new security group with default +// security group rules for the IPv4 and IPv6 ether types. +func Create(c *gophercloud.ServiceClient, opts os.CreateOpts) os.CreateResult { + return os.Create(c, opts) +} + +// Get retrieves a particular security group based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(c, id) +} + +// Delete will permanently delete a particular security group based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/rules/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/rules/delegate.go new file mode 100644 index 000000000..23b4b318e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/security/rules/delegate.go @@ -0,0 +1,30 @@ +package rules + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// security group rules. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts os.ListOpts) pagination.Pager { + return os.List(c, opts) +} + +// Create is an operation which provisions a new security group with default +// security group rules for the IPv4 and IPv6 ether types. +func Create(c *gophercloud.ServiceClient, opts os.CreateOpts) os.CreateResult { + return os.Create(c, opts) +} + +// Get retrieves a particular security group based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) os.GetResult { + return os.Get(c, id) +} + +// Delete will permanently delete a particular security group based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult { + return os.Delete(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/subnets/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/subnets/delegate.go new file mode 100644 index 000000000..a7fb7bb15 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/networking/v2/subnets/delegate.go @@ -0,0 +1,40 @@ +package subnets + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/networking/v2/subnets" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns a Pager which allows you to iterate over a collection of +// subnets. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those subnets that are owned by the tenant +// who submits the request, unless the request is submitted by a user with +// administrative rights. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// Get retrieves a specific subnet based on its unique ID. +func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult { + return os.Get(c, networkID) +} + +// Create accepts a CreateOpts struct and creates a new subnet using the values +// provided. You must remember to provide a valid NetworkID, CIDR and IP version. +func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, opts) +} + +// Update accepts a UpdateOpts struct and updates an existing subnet using the +// values provided. +func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, networkID, opts) +} + +// Delete accepts a unique ID and deletes the subnet associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult { + return os.Delete(c, networkID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/delegate.go new file mode 100644 index 000000000..94739308f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/delegate.go @@ -0,0 +1,39 @@ +package accounts + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts" +) + +// Get is a function that retrieves an account's metadata. To extract just the +// custom metadata, call the ExtractMetadata method on the GetResult. To extract +// all the headers that are returned (including the metadata), call the +// ExtractHeader method on the GetResult. +func Get(c *gophercloud.ServiceClient) os.GetResult { + return os.Get(c, nil) +} + +// UpdateOpts is a structure that contains parameters for updating, creating, or +// deleting an account's metadata. +type UpdateOpts struct { + Metadata map[string]string + TempURLKey string `h:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `h:"X-Account-Meta-Temp-URL-Key-2"` +} + +// ToAccountUpdateMap formats an UpdateOpts into a map[string]string of headers. +func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) { + headers, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + headers["X-Account-Meta-"+k] = v + } + return headers, err +} + +// Update will update an account's metadata with the Metadata in the UpdateOptsBuilder. +func Update(c *gophercloud.ServiceClient, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/doc.go new file mode 100644 index 000000000..293a93088 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts/doc.go @@ -0,0 +1,3 @@ +// Package accounts provides information and interaction with the account +// API resource for the Rackspace Cloud Files service. +package accounts diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/doc.go new file mode 100644 index 000000000..9c89e22b2 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/doc.go @@ -0,0 +1,3 @@ +// Package bulk provides functionality for working with bulk operations in the +// Rackspace Cloud Files service. +package bulk diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/requests.go new file mode 100644 index 000000000..0aeec155b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/requests.go @@ -0,0 +1,51 @@ +package bulk + +import ( + "net/url" + "strings" + + "github.com/rackspace/gophercloud" +) + +// DeleteOptsBuilder allows extensions to add additional parameters to the +// Delete request. +type DeleteOptsBuilder interface { + ToBulkDeleteBody() (string, error) +} + +// DeleteOpts is a structure that holds parameters for deleting an object. +type DeleteOpts []string + +// ToBulkDeleteBody formats a DeleteOpts into a request body. +func (opts DeleteOpts) ToBulkDeleteBody() (string, error) { + return url.QueryEscape(strings.Join(opts, "\n")), nil +} + +// Delete will delete objects or containers in bulk. +func Delete(c *gophercloud.ServiceClient, opts DeleteOptsBuilder) DeleteResult { + var res DeleteResult + + if opts == nil { + return res + } + + reqString, err := opts.ToBulkDeleteBody() + if err != nil { + res.Err = err + return res + } + + reqBody := strings.NewReader(reqString) + + resp, err := c.Request("DELETE", deleteURL(c), gophercloud.RequestOpts{ + MoreHeaders: map[string]string{"Content-Type": "text/plain"}, + OkCodes: []int{200}, + JSONBody: reqBody, + JSONResponse: &res.Body, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/results.go new file mode 100644 index 000000000..fddc125ac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/results.go @@ -0,0 +1,28 @@ +package bulk + +import ( + "github.com/rackspace/gophercloud" + + "github.com/mitchellh/mapstructure" +) + +// DeleteResult represents the result of a bulk delete operation. +type DeleteResult struct { + gophercloud.Result +} + +// DeleteRespBody is the form of the response body returned by a bulk delete request. +type DeleteRespBody struct { + NumberNotFound int `mapstructure:"Number Not Found"` + ResponseStatus string `mapstructure:"Response Status"` + Errors []string `mapstructure:"Errors"` + NumberDeleted int `mapstructure:"Number Deleted"` + ResponseBody string `mapstructure:"Response Body"` +} + +// ExtractBody will extract the body returned by the bulk extract request. +func (dr DeleteResult) ExtractBody() (DeleteRespBody, error) { + var resp DeleteRespBody + err := mapstructure.Decode(dr.Body, &resp) + return resp, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/urls.go new file mode 100644 index 000000000..2e112033b --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk/urls.go @@ -0,0 +1,11 @@ +package bulk + +import "github.com/rackspace/gophercloud" + +func deleteURL(c *gophercloud.ServiceClient) string { + return c.Endpoint + "?bulk-delete" +} + +func extractURL(c *gophercloud.ServiceClient, ext string) string { + return c.Endpoint + "?extract-archive=" + ext +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/delegate.go new file mode 100644 index 000000000..89adb8396 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/delegate.go @@ -0,0 +1,38 @@ +package cdncontainers + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractNames interprets a page of List results when just the container +// names are requested. +func ExtractNames(page pagination.Page) ([]string, error) { + return os.ExtractNames(page) +} + +// ListOpts are options for listing Rackspace CDN containers. +type ListOpts struct { + EndMarker string `q:"end_marker"` + Format string `q:"format"` + Limit int `q:"limit"` + Marker string `q:"marker"` +} + +// ToContainerListParams formats a ListOpts into a query string and boolean +// representing whether to list complete information for each container. +func (opts ListOpts) ToContainerListParams() (bool, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return false, "", err + } + return false, q.String(), nil +} + +// List is a function that retrieves containers associated with the account as +// well as account metadata. It returns a pager which can be iterated with the +// EachPage function. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/doc.go new file mode 100644 index 000000000..7b0930eee --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/doc.go @@ -0,0 +1,3 @@ +// Package cdncontainers provides information and interaction with the CDN +// Container API resource for the Rackspace Cloud Files service. +package cdncontainers diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/requests.go new file mode 100644 index 000000000..6acebb0aa --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/requests.go @@ -0,0 +1,161 @@ +package cdncontainers + +import ( + "strconv" + + "github.com/rackspace/gophercloud" +) + +// EnableOptsBuilder allows extensions to add additional parameters to the Enable +// request. +type EnableOptsBuilder interface { + ToCDNContainerEnableMap() (map[string]string, error) +} + +// EnableOpts is a structure that holds options for enabling a CDN container. +type EnableOpts struct { + // CDNEnabled indicates whether or not the container is CDN enabled. Set to + // `true` to enable the container. Note that changing this setting from true + // to false will disable the container in the CDN but only after the TTL has + // expired. + CDNEnabled bool `h:"X-Cdn-Enabled"` + // TTL is the time-to-live for the container (in seconds). + TTL int `h:"X-Ttl"` +} + +// ToCDNContainerEnableMap formats an EnableOpts into a map of headers. +func (opts EnableOpts) ToCDNContainerEnableMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + return h, nil +} + +// Enable is a function that enables/disables a CDN container. +func Enable(c *gophercloud.ServiceClient, containerName string, opts EnableOptsBuilder) EnableResult { + var res EnableResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToCDNContainerEnableMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("PUT", enableURL(c, containerName), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201, 202, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// Get is a function that retrieves the metadata of a container. To extract just +// the custom metadata, pass the GetResult response to the ExtractMetadata +// function. +func Get(c *gophercloud.ServiceClient, containerName string) GetResult { + var res GetResult + resp, err := c.Request("HEAD", getURL(c, containerName), gophercloud.RequestOpts{ + OkCodes: []int{200, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} + +// State is the state of an option. It is a pointer to a boolean to enable checking for +// a zero-value of nil instead of false, which is a valid option. +type State *bool + +var ( + iTrue = true + iFalse = false + + // Enabled is used for a true value for options in request bodies. + Enabled State = &iTrue + // Disabled is used for a false value for options in request bodies. + Disabled State = &iFalse +) + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToContainerUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that holds parameters for updating, creating, or +// deleting a container's metadata. +type UpdateOpts struct { + // Whether or not to CDN-enable a container. Prefer using XCDNEnabled, which + // is of type *bool underneath. + // TODO v2.0: change type to Enabled/Disabled (*bool) + CDNEnabled bool `h:"X-Cdn-Enabled"` + // Whether or not to enable log retention. Prefer using XLogRetention, which + // is of type *bool underneath. + // TODO v2.0: change type to Enabled/Disabled (*bool) + LogRetention bool `h:"X-Log-Retention"` + XCDNEnabled *bool + XLogRetention *bool + TTL int `h:"X-Ttl"` +} + +// ToContainerUpdateMap formats a CreateOpts into a map of headers. +func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + h["X-Cdn-Enabled"] = strconv.FormatBool(opts.CDNEnabled) + h["X-Log-Retention"] = strconv.FormatBool(opts.LogRetention) + + if opts.XCDNEnabled != nil { + h["X-Cdn-Enabled"] = strconv.FormatBool(*opts.XCDNEnabled) + } + + if opts.XLogRetention != nil { + h["X-Log-Retention"] = strconv.FormatBool(*opts.XLogRetention) + } + + return h, nil +} + +// Update is a function that creates, updates, or deletes a container's +// metadata. +func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult { + var res UpdateResult + h := c.AuthenticatedHeaders() + + if opts != nil { + headers, err := opts.ToContainerUpdateMap() + if err != nil { + res.Err = err + return res + } + + for k, v := range headers { + h[k] = v + } + } + + resp, err := c.Request("POST", updateURL(c, containerName), gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{202, 204}, + }) + if resp != nil { + res.Header = resp.Header + } + res.Err = err + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/results.go new file mode 100644 index 000000000..cb0ad3096 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/results.go @@ -0,0 +1,149 @@ +package cdncontainers + +import ( + "strings" + "time" + + "github.com/rackspace/gophercloud" +) + +// EnableHeader represents the headers returned in the response from an Enable request. +type EnableHeader struct { + CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"` + CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"` + CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"` + CDNUri string `mapstructure:"X-Cdn-Uri"` + ContentLength int `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// EnableResult represents the result of an Enable operation. +type EnableResult struct { + gophercloud.HeaderResult +} + +// Extract will return extract an EnableHeader from the response to an Enable +// request. To obtain a map of headers, call the ExtractHeader method on the EnableResult. +func (er EnableResult) Extract() (EnableHeader, error) { + var eh EnableHeader + if er.Err != nil { + return eh, er.Err + } + + if err := gophercloud.DecodeHeader(er.Header, &eh); err != nil { + return eh, err + } + + if date, ok := er.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, er.Header["Date"][0]) + if err != nil { + return eh, err + } + eh.Date = t + } + + return eh, nil +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + CDNEnabled bool `mapstructure:"X-Cdn-Enabled"` + CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"` + CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"` + CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"` + CDNUri string `mapstructure:"X-Cdn-Uri"` + ContentLength int `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + LogRetention bool `mapstructure:"X-Log-Retention"` + TransID string `mapstructure:"X-Trans-Id"` + TTL int `mapstructure:"X-Ttl"` +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (gr GetResult) Extract() (GetHeader, error) { + var gh GetHeader + if gr.Err != nil { + return gh, gr.Err + } + + if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil { + return gh, err + } + + if date, ok := gr.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, gr.Header["Date"][0]) + if err != nil { + return gh, err + } + gh.Date = t + } + + return gh, nil +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metadata associated with the container. +func (gr GetResult) ExtractMetadata() (map[string]string, error) { + if gr.Err != nil { + return nil, gr.Err + } + metadata := make(map[string]string) + for k, v := range gr.Header { + if strings.HasPrefix(k, "X-Container-Meta-") { + key := strings.TrimPrefix(k, "X-Container-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} + +// UpdateHeader represents the headers returned in the response from a Update request. +type UpdateHeader struct { + CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"` + CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"` + CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"` + CDNUri string `mapstructure:"X-Cdn-Uri"` + ContentLength int `mapstructure:"Content-Length"` + ContentType string `mapstructure:"Content-Type"` + Date time.Time `mapstructure:"-"` + TransID string `mapstructure:"X-Trans-Id"` +} + +// UpdateResult represents the result of an update operation. To extract the +// the headers from the HTTP response, you can invoke the 'ExtractHeader' +// method on the result struct. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Update. To obtain +// a map of headers, call the ExtractHeader method on the UpdateResult. +func (ur UpdateResult) Extract() (UpdateHeader, error) { + var uh UpdateHeader + if ur.Err != nil { + return uh, ur.Err + } + + if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil { + return uh, err + } + + if date, ok := ur.Header["Date"]; ok && len(date) > 0 { + t, err := time.Parse(time.RFC1123, ur.Header["Date"][0]) + if err != nil { + return uh, err + } + uh.Date = t + } + + return uh, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/urls.go new file mode 100644 index 000000000..541249a92 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers/urls.go @@ -0,0 +1,15 @@ +package cdncontainers + +import "github.com/rackspace/gophercloud" + +func enableURL(c *gophercloud.ServiceClient, containerName string) string { + return c.ServiceURL(containerName) +} + +func getURL(c *gophercloud.ServiceClient, container string) string { + return c.ServiceURL(container) +} + +func updateURL(c *gophercloud.ServiceClient, container string) string { + return getURL(c, container) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/delegate.go new file mode 100644 index 000000000..e9d2ff1d6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/delegate.go @@ -0,0 +1,11 @@ +package cdnobjects + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects" +) + +// Delete is a function that deletes an object from the CDN. +func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DeleteOptsBuilder) os.DeleteResult { + return os.Delete(c, containerName, objectName, nil) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/doc.go new file mode 100644 index 000000000..90cd5c97f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/doc.go @@ -0,0 +1,3 @@ +// Package cdnobjects provides information and interaction with the CDN +// Object API resource for the Rackspace Cloud Files service. +package cdnobjects diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/request.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/request.go new file mode 100644 index 000000000..540e0cd29 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects/request.go @@ -0,0 +1,15 @@ +package cdnobjects + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers" +) + +// CDNURL returns the unique CDN URI for the given container and object. +func CDNURL(c *gophercloud.ServiceClient, containerName, objectName string) (string, error) { + h, err := cdncontainers.Get(c, containerName).Extract() + if err != nil { + return "", err + } + return h.CDNUri + "/" + objectName, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/delegate.go new file mode 100644 index 000000000..77ed00257 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/delegate.go @@ -0,0 +1,93 @@ +package containers + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractInfo interprets a page of List results when full container info +// is requested. +func ExtractInfo(page pagination.Page) ([]os.Container, error) { + return os.ExtractInfo(page) +} + +// ExtractNames interprets a page of List results when just the container +// names are requested. +func ExtractNames(page pagination.Page) ([]string, error) { + return os.ExtractNames(page) +} + +// List is a function that retrieves containers associated with the account as +// well as account metadata. It returns a pager which can be iterated with the +// EachPage function. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// CreateOpts is a structure that holds parameters for creating a container. +type CreateOpts struct { + Metadata map[string]string + ContainerRead string `h:"X-Container-Read"` + ContainerWrite string `h:"X-Container-Write"` + VersionsLocation string `h:"X-Versions-Location"` +} + +// ToContainerCreateMap formats a CreateOpts into a map of headers. +func (opts CreateOpts) ToContainerCreateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Container-Meta-"+k] = v + } + return h, nil +} + +// Create is a function that creates a new container. +func Create(c *gophercloud.ServiceClient, containerName string, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, containerName, opts) +} + +// Delete is a function that deletes a container. +func Delete(c *gophercloud.ServiceClient, containerName string) os.DeleteResult { + return os.Delete(c, containerName) +} + +// UpdateOpts is a structure that holds parameters for updating or creating a +// container's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContainerRead string `h:"X-Container-Read"` + ContainerWrite string `h:"X-Container-Write"` + ContentType string `h:"Content-Type"` + DetectContentType bool `h:"X-Detect-Content-Type"` + RemoveVersionsLocation string `h:"X-Remove-Versions-Location"` + VersionsLocation string `h:"X-Versions-Location"` +} + +// ToContainerUpdateMap formats a CreateOpts into a map of headers. +func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Container-Meta-"+k] = v + } + return h, nil +} + +// Update is a function that creates, updates, or deletes a container's +// metadata. +func Update(c *gophercloud.ServiceClient, containerName string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, containerName, opts) +} + +// Get is a function that retrieves the metadata of a container. To extract just +// the custom metadata, pass the GetResult response to the ExtractMetadata +// function. +func Get(c *gophercloud.ServiceClient, containerName string) os.GetResult { + return os.Get(c, containerName) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/doc.go new file mode 100644 index 000000000..d132a0738 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers/doc.go @@ -0,0 +1,3 @@ +// Package containers provides information and interaction with the Container +// API resource for the Rackspace Cloud Files service. +package containers diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/delegate.go new file mode 100644 index 000000000..94c820ba7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/delegate.go @@ -0,0 +1,94 @@ +package objects + +import ( + "io" + + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects" + "github.com/rackspace/gophercloud/pagination" +) + +// ExtractInfo is a function that takes a page of objects and returns their full information. +func ExtractInfo(page pagination.Page) ([]os.Object, error) { + return os.ExtractInfo(page) +} + +// ExtractNames is a function that takes a page of objects and returns only their names. +func ExtractNames(page pagination.Page) ([]string, error) { + return os.ExtractNames(page) +} + +// List is a function that retrieves objects in the container as +// well as container metadata. It returns a pager which can be iterated with the +// EachPage function. +func List(c *gophercloud.ServiceClient, containerName string, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, containerName, opts) +} + +// Download is a function that retrieves the content and metadata for an object. +// To extract just the content, pass the DownloadResult response to the +// ExtractContent function. +func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DownloadOptsBuilder) os.DownloadResult { + return os.Download(c, containerName, objectName, opts) +} + +// Create is a function that creates a new object or replaces an existing object. +func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.ReadSeeker, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, containerName, objectName, content, opts) +} + +// CopyOpts is a structure that holds parameters for copying one object to +// another. +type CopyOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentLength int `h:"Content-Length"` + ContentType string `h:"Content-Type"` + CopyFrom string `h:"X-Copy_From"` + Destination string `h:"Destination"` + DetectContentType bool `h:"X-Detect-Content-Type"` +} + +// ToObjectCopyMap formats a CopyOpts into a map of headers. +func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + // `Content-Length` is required and a value of "0" is acceptable, but calling `gophercloud.BuildHeaders` + // will remove the `Content-Length` header if it's set to 0 (or equivalently not set). This will add + // the header if it's not already set. + if _, ok := h["Content-Length"]; !ok { + h["Content-Length"] = "0" + } + return h, nil +} + +// Copy is a function that copies one object to another. +func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts os.CopyOptsBuilder) os.CopyResult { + return os.Copy(c, containerName, objectName, opts) +} + +// Delete is a function that deletes an object. +func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DeleteOptsBuilder) os.DeleteResult { + return os.Delete(c, containerName, objectName, opts) +} + +// Get is a function that retrieves the metadata of an object. To extract just the custom +// metadata, pass the GetResult response to the ExtractMetadata function. +func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts os.GetOptsBuilder) os.GetResult { + return os.Get(c, containerName, objectName, opts) +} + +// Update is a function that creates, updates, or deletes an object's metadata. +func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, containerName, objectName, opts) +} + +func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName string, opts os.CreateTempURLOpts) (string, error) { + return os.CreateTempURL(c, containerName, objectName, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/doc.go new file mode 100644 index 000000000..781984bee --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects/doc.go @@ -0,0 +1,3 @@ +// Package objects provides information and interaction with the Object +// API resource for the Rackspace Cloud Files service. +package objects diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/delegate.go new file mode 100644 index 000000000..c834e5c7d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/delegate.go @@ -0,0 +1,11 @@ +package buildinfo + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo" +) + +// Get retreives build info data for the Heat deployment. +func Get(c *gophercloud.ServiceClient) os.GetResult { + return os.Get(c) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/doc.go new file mode 100644 index 000000000..183e8dfa7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo/doc.go @@ -0,0 +1,2 @@ +// Package buildinfo provides build information about heat deployments. +package buildinfo diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/delegate.go new file mode 100644 index 000000000..08675deac --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/delegate.go @@ -0,0 +1,27 @@ +package stackevents + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents" + "github.com/rackspace/gophercloud/pagination" +) + +// Find retreives stack events for the given stack name. +func Find(c *gophercloud.ServiceClient, stackName string) os.FindResult { + return os.Find(c, stackName) +} + +// List makes a request against the API to list resources for the given stack. +func List(c *gophercloud.ServiceClient, stackName, stackID string, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, stackName, stackID, opts) +} + +// ListResourceEvents makes a request against the API to list resources for the given stack. +func ListResourceEvents(c *gophercloud.ServiceClient, stackName, stackID, resourceName string, opts os.ListResourceEventsOptsBuilder) pagination.Pager { + return os.ListResourceEvents(c, stackName, stackID, resourceName, opts) +} + +// Get retreives data for the given stack resource. +func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) os.GetResult { + return os.Get(c, stackName, stackID, resourceName, eventID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/doc.go new file mode 100644 index 000000000..dfd6ef660 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents/doc.go @@ -0,0 +1,3 @@ +// Package stackevents provides operations for finding, listing, and retrieving +// stack events. +package stackevents diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/delegate.go new file mode 100644 index 000000000..cb7be28b7 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/delegate.go @@ -0,0 +1,42 @@ +package stackresources + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources" + "github.com/rackspace/gophercloud/pagination" +) + +// Find retreives stack resources for the given stack name. +func Find(c *gophercloud.ServiceClient, stackName string) os.FindResult { + return os.Find(c, stackName) +} + +// List makes a request against the API to list resources for the given stack. +func List(c *gophercloud.ServiceClient, stackName, stackID string, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, stackName, stackID, opts) +} + +// Get retreives data for the given stack resource. +func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) os.GetResult { + return os.Get(c, stackName, stackID, resourceName) +} + +// Metadata retreives the metadata for the given stack resource. +func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) os.MetadataResult { + return os.Metadata(c, stackName, stackID, resourceName) +} + +// ListTypes makes a request against the API to list resource types. +func ListTypes(c *gophercloud.ServiceClient) pagination.Pager { + return os.ListTypes(c) +} + +// Schema retreives the schema for the given resource type. +func Schema(c *gophercloud.ServiceClient, resourceType string) os.SchemaResult { + return os.Schema(c, resourceType) +} + +// Template retreives the template representation for the given resource type. +func Template(c *gophercloud.ServiceClient, resourceType string) os.TemplateResult { + return os.Template(c, resourceType) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/doc.go new file mode 100644 index 000000000..e4f8b08dc --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources/doc.go @@ -0,0 +1,5 @@ +// Package stackresources provides operations for working with stack resources. +// A resource is a template artifact that represents some component of your +// desired architecture (a Cloud Server, a group of scaled Cloud Servers, a load +// balancer, some configuration management system, and so forth). +package stackresources diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/delegate.go new file mode 100644 index 000000000..f7e387f8f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/delegate.go @@ -0,0 +1,49 @@ +package stacks + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks" + "github.com/rackspace/gophercloud/pagination" +) + +// Create accepts an os.CreateOpts struct and creates a new stack using the values +// provided. +func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult { + return os.Create(c, opts) +} + +// Adopt accepts an os.AdoptOpts struct and creates a new stack from existing stack +// resources using the values provided. +func Adopt(c *gophercloud.ServiceClient, opts os.AdoptOptsBuilder) os.AdoptResult { + return os.Adopt(c, opts) +} + +// List accepts an os.ListOpts struct and lists stacks based on the options provided. +func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager { + return os.List(c, opts) +} + +// Get retreives a stack based on the stack name and stack ID. +func Get(c *gophercloud.ServiceClient, stackName, stackID string) os.GetResult { + return os.Get(c, stackName, stackID) +} + +// Update accepts an os.UpdateOpts struct and updates a stack based on the options provided. +func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts os.UpdateOptsBuilder) os.UpdateResult { + return os.Update(c, stackName, stackID, opts) +} + +// Delete deletes a stack based on the stack name and stack ID provided. +func Delete(c *gophercloud.ServiceClient, stackName, stackID string) os.DeleteResult { + return os.Delete(c, stackName, stackID) +} + +// Preview provides a preview of a stack based on the options provided. +func Preview(c *gophercloud.ServiceClient, opts os.PreviewOptsBuilder) os.PreviewResult { + return os.Preview(c, opts) +} + +// Abandon abandons a stack, keeping the resources available. +func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) os.AbandonResult { + return os.Abandon(c, stackName, stackID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/doc.go new file mode 100644 index 000000000..19231b513 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/doc.go @@ -0,0 +1,8 @@ +// Package stacks provides operation for working with Heat stacks. A stack is a +// group of resources (servers, load balancers, databases, and so forth) +// combined to fulfill a useful purpose. Based on a template, Heat orchestration +// engine creates an instantiated set of resources (a stack) to run the +// application framework or component specified (in the template). A stack is a +// running instance of a template. The result of creating a stack is a deployment +// of the application framework or component. +package stacks diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/fixtures.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/fixtures.go new file mode 100644 index 000000000..c9afeb156 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks/fixtures.go @@ -0,0 +1,32 @@ +package stacks + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks" +) + +// CreateExpected represents the expected object from a Create request. +var CreateExpected = &os.CreatedStack{ + ID: "b663e18a-4767-4cdf-9db5-9c8cc13cc38a", + Links: []gophercloud.Link{ + gophercloud.Link{ + Href: "https://ord.orchestration.api.rackspacecloud.com/v1/864477/stacks/stackcreated/b663e18a-4767-4cdf-9db5-9c8cc13cc38a", + Rel: "self", + }, + }, +} + +// CreateOutput represents the response body from a Create request. +const CreateOutput = ` +{ + "stack": { + "id": "b663e18a-4767-4cdf-9db5-9c8cc13cc38a", + "links": [ + { + "href": "https://ord.orchestration.api.rackspacecloud.com/v1/864477/stacks/stackcreated/b663e18a-4767-4cdf-9db5-9c8cc13cc38a", + "rel": "self" + } + ] + } +} +` diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/delegate.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/delegate.go new file mode 100644 index 000000000..3b5d46e1c --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/delegate.go @@ -0,0 +1,16 @@ +package stacktemplates + +import ( + "github.com/rackspace/gophercloud" + os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates" +) + +// Get retreives data for the given stack template. +func Get(c *gophercloud.ServiceClient, stackName, stackID string) os.GetResult { + return os.Get(c, stackName, stackID) +} + +// Validate validates the given stack template. +func Validate(c *gophercloud.ServiceClient, opts os.ValidateOptsBuilder) os.ValidateResult { + return os.Validate(c, opts) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/doc.go new file mode 100644 index 000000000..5af0bd62a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates/doc.go @@ -0,0 +1,8 @@ +// Package stacktemplates provides operations for working with Heat templates. +// A Cloud Orchestration template is a portable file, written in a user-readable +// language, that describes how a set of resources should be assembled and what +// software should be installed in order to produce a working stack. The template +// specifies what resources should be used, what attributes can be set, and other +// parameters that are critical to the successful, repeatable automation of a +// specific application stack. +package stacktemplates diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/requests.go new file mode 100644 index 000000000..58843030a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/requests.go @@ -0,0 +1,24 @@ +package cloudnetworks + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns all cloud networks that are associated with RackConnect. The ID +// returned for each network is the same as the ID returned by the networks package. +func List(c *gophercloud.ServiceClient) pagination.Pager { + url := listURL(c) + createPage := func(r pagination.PageResult) pagination.Page { + return CloudNetworkPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Get retrieves a specific cloud network (that is associated with RackConnect) +// based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/results.go new file mode 100644 index 000000000..f554a0d75 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/results.go @@ -0,0 +1,113 @@ +package cloudnetworks + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// CloudNetwork represents a network associated with a RackConnect configuration. +type CloudNetwork struct { + // Specifies the ID of the newtork. + ID string `mapstructure:"id"` + // Specifies the user-provided name of the network. + Name string `mapstructure:"name"` + // Specifies the IP range for this network. + CIDR string `mapstructure:"cidr"` + // Specifies the time the network was created. + CreatedAt time.Time `mapstructure:"-"` + // Specifies the time the network was last updated. + UpdatedAt time.Time `mapstructure:"-"` +} + +// CloudNetworkPage is the page returned by a pager when traversing over a +// collection of CloudNetworks. +type CloudNetworkPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a CloudNetworkPage contains no CloudNetworks. +func (r CloudNetworkPage) IsEmpty() (bool, error) { + cns, err := ExtractCloudNetworks(r) + if err != nil { + return true, err + } + return len(cns) == 0, nil +} + +// ExtractCloudNetworks extracts and returns CloudNetworks. It is used while iterating over +// a cloudnetworks.List call. +func ExtractCloudNetworks(page pagination.Page) ([]CloudNetwork, error) { + var res []CloudNetwork + casted := page.(CloudNetworkPage).Body + err := mapstructure.Decode(casted, &res) + + var rawNets []interface{} + switch casted.(type) { + case interface{}: + rawNets = casted.([]interface{}) + default: + return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawNets { + thisNet := (rawNets[i]).(map[string]interface{}) + + if t, ok := thisNet["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CreatedAt = creationTime + } + + if t, ok := thisNet["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].UpdatedAt = updatedTime + } + } + + return res, err +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that extracts a CloudNetwork from a GetResult. +func (r GetResult) Extract() (*CloudNetwork, error) { + if r.Err != nil { + return nil, r.Err + } + var res CloudNetwork + + err := mapstructure.Decode(r.Body, &res) + + b := r.Body.(map[string]interface{}) + + if date, ok := b["created"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.CreatedAt = t + } + + if date, ok := b["updated"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.UpdatedAt = t + } + + return &res, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/urls.go new file mode 100644 index 000000000..bd6b098da --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks/urls.go @@ -0,0 +1,11 @@ +package cloudnetworks + +import "github.com/rackspace/gophercloud" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("cloud_networks") +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("cloud_networks", id) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/doc.go new file mode 100644 index 000000000..3a8279e10 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/doc.go @@ -0,0 +1,4 @@ +// Package rackconnect allows Rackspace cloud accounts to leverage version 3 of +// RackConnect, Rackspace's hybrid connectivity solution connecting dedicated +// and cloud servers. +package rackconnect diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/doc.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/doc.go new file mode 100644 index 000000000..f4319b8ff --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/doc.go @@ -0,0 +1,14 @@ +// Package lbpools provides access to load balancer pools associated with a +// RackConnect configuration. Load Balancer Pools must be configured in advance +// by your Network Security team to be eligible for use with RackConnect. +// If you do not see a pool that you expect to see, contact your Support team +// for further assistance. The Load Balancer Pool id returned by these calls is +// automatically generated by the RackConnect automation and will remain constant +// unless the Load Balancer Pool is renamed on your hardware load balancer. +// All Load Balancer Pools will currently return a status of ACTIVE. Future +// features may introduce additional statuses. +// Node status values are ADDING, ACTIVE, REMOVING, ADD_FAILED, and REMOVE_FAILED. +// The cloud_servers node count will only include Cloud Servers from the specified +// cloud account. Any dedicated servers or cloud servers from another cloud account +// on the same RackConnect Configuration will be counted as external nodes. +package lbpools diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/requests.go new file mode 100644 index 000000000..c300c56c1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/requests.go @@ -0,0 +1,146 @@ +package lbpools + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns all load balancer pools that are associated with RackConnect. +func List(c *gophercloud.ServiceClient) pagination.Pager { + url := listURL(c) + createPage := func(r pagination.PageResult) pagination.Page { + return PoolPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Get retrieves a specific load balancer pool (that is associated with RackConnect) +// based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// ListNodes returns all load balancer pool nodes that are associated with RackConnect +// for the given LB pool ID. +func ListNodes(c *gophercloud.ServiceClient, id string) pagination.Pager { + url := listNodesURL(c, id) + createPage := func(r pagination.PageResult) pagination.Page { + return NodePage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// CreateNode adds the cloud server with the given serverID to the load balancer +// pool with the given poolID. +func CreateNode(c *gophercloud.ServiceClient, poolID, serverID string) CreateNodeResult { + var res CreateNodeResult + reqBody := map[string]interface{}{ + "cloud_server": map[string]string{ + "id": serverID, + }, + } + _, res.Err = c.Post(createNodeURL(c, poolID), reqBody, &res.Body, nil) + return res +} + +// ListNodesDetails returns all load balancer pool nodes that are associated with RackConnect +// for the given LB pool ID with all their details. +func ListNodesDetails(c *gophercloud.ServiceClient, id string) pagination.Pager { + url := listNodesDetailsURL(c, id) + createPage := func(r pagination.PageResult) pagination.Page { + return NodeDetailsPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// GetNode retrieves a specific LB pool node (that is associated with RackConnect) +// based on its unique ID and the LB pool's unique ID. +func GetNode(c *gophercloud.ServiceClient, poolID, nodeID string) GetNodeResult { + var res GetNodeResult + _, res.Err = c.Get(nodeURL(c, poolID, nodeID), &res.Body, nil) + return res +} + +// DeleteNode removes the node with the given nodeID from the LB pool with the +// given poolID. +func DeleteNode(c *gophercloud.ServiceClient, poolID, nodeID string) DeleteNodeResult { + var res DeleteNodeResult + _, res.Err = c.Delete(deleteNodeURL(c, poolID, nodeID), nil) + return res +} + +// GetNodeDetails retrieves a specific LB pool node's details based on its unique +// ID and the LB pool's unique ID. +func GetNodeDetails(c *gophercloud.ServiceClient, poolID, nodeID string) GetNodeDetailsResult { + var res GetNodeDetailsResult + _, res.Err = c.Get(nodeDetailsURL(c, poolID, nodeID), &res.Body, nil) + return res +} + +// NodeOpts are options for bulk adding/deleting nodes to LB pools. +type NodeOpts struct { + ServerID string + PoolID string +} + +// NodesOpts are a slice of NodeOpts, passed as options for bulk operations. +type NodesOpts []NodeOpts + +// ToLBPoolCreateNodesMap serializes a NodesOpts into a map to send in the request. +func (o NodesOpts) ToLBPoolCreateNodesMap() ([]map[string]interface{}, error) { + m := make([]map[string]interface{}, len(o)) + for i := range o { + m[i] = map[string]interface{}{ + "cloud_server": map[string]string{ + "id": o[i].ServerID, + }, + "load_balancer_pool": map[string]string{ + "id": o[i].PoolID, + }, + } + } + return m, nil +} + +// CreateNodes adds the cloud servers with the given serverIDs to the corresponding +// load balancer pools with the given poolIDs. +func CreateNodes(c *gophercloud.ServiceClient, opts NodesOpts) CreateNodesResult { + var res CreateNodesResult + reqBody, err := opts.ToLBPoolCreateNodesMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Post(createNodesURL(c), reqBody, &res.Body, nil) + return res +} + +// DeleteNodes removes the cloud servers with the given serverIDs to the corresponding +// load balancer pools with the given poolIDs. +func DeleteNodes(c *gophercloud.ServiceClient, opts NodesOpts) DeleteNodesResult { + var res DeleteNodesResult + reqBody, err := opts.ToLBPoolCreateNodesMap() + if err != nil { + res.Err = err + return res + } + + _, res.Err = c.Request("DELETE", createNodesURL(c), gophercloud.RequestOpts{ + JSONBody: &reqBody, + OkCodes: []int{204}, + }) + return res +} + +// ListNodesDetailsForServer is similar to ListNodesDetails but only returns nodes +// for the given serverID. +func ListNodesDetailsForServer(c *gophercloud.ServiceClient, serverID string) pagination.Pager { + url := listNodesForServerURL(c, serverID) + createPage := func(r pagination.PageResult) pagination.Page { + return NodeDetailsForServerPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/results.go new file mode 100644 index 000000000..e5e914b1e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/results.go @@ -0,0 +1,505 @@ +package lbpools + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// Pool represents a load balancer pool associated with a RackConnect configuration. +type Pool struct { + // The unique ID of the load balancer pool. + ID string `mapstructure:"id"` + // The name of the load balancer pool. + Name string `mapstructure:"name"` + // The node counts associated witht the load balancer pool. + NodeCounts struct { + // The number of nodes associated with this LB pool for this account. + CloudServers int `mapstructure:"cloud_servers"` + // The number of nodes associated with this LB pool from other accounts. + External int `mapstructure:"external"` + // The total number of nodes associated with this LB pool. + Total int `mapstructure:"total"` + } `mapstructure:"node_counts"` + // The port of the LB pool + Port int `mapstructure:"port"` + // The status of the LB pool + Status string `mapstructure:"status"` + // The details of the status of the LB pool + StatusDetail string `mapstructure:"status_detail"` + // The virtual IP of the LB pool + VirtualIP string `mapstructure:"virtual_ip"` +} + +// PoolPage is the page returned by a pager when traversing over a +// collection of Pools. +type PoolPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a PoolPage contains no Pools. +func (r PoolPage) IsEmpty() (bool, error) { + cns, err := ExtractPools(r) + if err != nil { + return true, err + } + return len(cns) == 0, nil +} + +// ExtractPools extracts and returns Pools. It is used while iterating over +// an lbpools.List call. +func ExtractPools(page pagination.Page) ([]Pool, error) { + var res []Pool + err := mapstructure.Decode(page.(PoolPage).Body, &res) + return res, err +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + gophercloud.Result +} + +// Extract is a function that extracts an LBPool from a GetResult. +func (r GetResult) Extract() (*Pool, error) { + if r.Err != nil { + return nil, r.Err + } + var res Pool + err := mapstructure.Decode(r.Body, &res) + return &res, err +} + +// Node represents a load balancer pool node associated with a RackConnect configuration. +type Node struct { + // The unique ID of the LB node. + ID string `mapstructure:"id"` + // The cloud server (node) of the load balancer pool. + CloudServer struct { + // The cloud server ID. + ID string `mapstructure:"id"` + } `mapstructure:"cloud_server"` + // The load balancer pool. + LoadBalancerPool struct { + // The LB pool ID. + ID string `mapstructure:"id"` + } `mapstructure:"load_balancer_pool"` + // The status of the LB pool. + Status string `mapstructure:"status"` + // The details of the status of the LB pool. + StatusDetail string `mapstructure:"status_detail"` + // The time the LB node was created. + CreatedAt time.Time `mapstructure:"-"` + // The time the LB node was last updated. + UpdatedAt time.Time `mapstructure:"-"` +} + +// NodePage is the page returned by a pager when traversing over a +// collection of Nodes. +type NodePage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a NodePage contains no Nodes. +func (r NodePage) IsEmpty() (bool, error) { + n, err := ExtractNodes(r) + if err != nil { + return true, err + } + return len(n) == 0, nil +} + +// ExtractNodes extracts and returns a slice of Nodes. It is used while iterating over +// an lbpools.ListNodes call. +func ExtractNodes(page pagination.Page) ([]Node, error) { + var res []Node + casted := page.(NodePage).Body + err := mapstructure.Decode(casted, &res) + + var rawNodes []interface{} + switch casted.(type) { + case interface{}: + rawNodes = casted.([]interface{}) + default: + return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawNodes { + thisNode := (rawNodes[i]).(map[string]interface{}) + + if t, ok := thisNode["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CreatedAt = creationTime + } + + if t, ok := thisNode["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].UpdatedAt = updatedTime + } + } + + return res, err +} + +// NodeResult represents a result that can be extracted as a Node. +type NodeResult struct { + gophercloud.Result +} + +// CreateNodeResult represents the result of an CreateNode operation. +type CreateNodeResult struct { + NodeResult +} + +// GetNodeResult represents the result of an GetNode operation. +type GetNodeResult struct { + NodeResult +} + +// Extract is a function that extracts a Node from a NodeResult. +func (r NodeResult) Extract() (*Node, error) { + if r.Err != nil { + return nil, r.Err + } + var res Node + err := mapstructure.Decode(r.Body, &res) + + b := r.Body.(map[string]interface{}) + + if date, ok := b["created"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.CreatedAt = t + } + + if date, ok := b["updated"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.UpdatedAt = t + } + + return &res, err +} + +// NodeDetails represents a load balancer pool node associated with a RackConnect configuration +// with all its details. +type NodeDetails struct { + // The unique ID of the LB node. + ID string `mapstructure:"id"` + // The cloud server (node) of the load balancer pool. + CloudServer struct { + // The cloud server ID. + ID string `mapstructure:"id"` + // The name of the server. + Name string `mapstructure:"name"` + // The cloud network for the cloud server. + CloudNetwork struct { + // The network ID. + ID string `mapstructure:"id"` + // The network name. + Name string `mapstructure:"name"` + // The network's private IPv4 address. + PrivateIPv4 string `mapstructure:"private_ip_v4"` + // The IP range for the network. + CIDR string `mapstructure:"cidr"` + // The datetime the network was created. + CreatedAt time.Time `mapstructure:"-"` + // The last datetime the network was updated. + UpdatedAt time.Time `mapstructure:"-"` + } `mapstructure:"cloud_network"` + // The datetime the server was created. + CreatedAt time.Time `mapstructure:"-"` + // The datetime the server was last updated. + UpdatedAt time.Time `mapstructure:"-"` + } `mapstructure:"cloud_server"` + // The load balancer pool. + LoadBalancerPool Pool `mapstructure:"load_balancer_pool"` + // The status of the LB pool. + Status string `mapstructure:"status"` + // The details of the status of the LB pool. + StatusDetail string `mapstructure:"status_detail"` + // The time the LB node was created. + CreatedAt time.Time `mapstructure:"-"` + // The time the LB node was last updated. + UpdatedAt time.Time `mapstructure:"-"` +} + +// NodeDetailsPage is the page returned by a pager when traversing over a +// collection of NodeDetails. +type NodeDetailsPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a NodeDetailsPage contains no NodeDetails. +func (r NodeDetailsPage) IsEmpty() (bool, error) { + n, err := ExtractNodesDetails(r) + if err != nil { + return true, err + } + return len(n) == 0, nil +} + +// ExtractNodesDetails extracts and returns a slice of NodeDetails. It is used while iterating over +// an lbpools.ListNodesDetails call. +func ExtractNodesDetails(page pagination.Page) ([]NodeDetails, error) { + var res []NodeDetails + casted := page.(NodeDetailsPage).Body + err := mapstructure.Decode(casted, &res) + + var rawNodesDetails []interface{} + switch casted.(type) { + case interface{}: + rawNodesDetails = casted.([]interface{}) + default: + return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawNodesDetails { + thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{}) + + if t, ok := thisNodeDetails["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CreatedAt = creationTime + } + + if t, ok := thisNodeDetails["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].UpdatedAt = updatedTime + } + + if cs, ok := thisNodeDetails["cloud_server"].(map[string]interface{}); ok { + if t, ok := cs["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CreatedAt = creationTime + } + if t, ok := cs["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.UpdatedAt = updatedTime + } + if cn, ok := cs["cloud_network"].(map[string]interface{}); ok { + if t, ok := cn["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CloudNetwork.CreatedAt = creationTime + } + if t, ok := cn["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CloudNetwork.UpdatedAt = updatedTime + } + } + } + } + + return res, err +} + +// GetNodeDetailsResult represents the result of an NodeDetails operation. +type GetNodeDetailsResult struct { + gophercloud.Result +} + +// Extract is a function that extracts a NodeDetails from a NodeDetailsResult. +func (r GetNodeDetailsResult) Extract() (*NodeDetails, error) { + if r.Err != nil { + return nil, r.Err + } + var res NodeDetails + err := mapstructure.Decode(r.Body, &res) + + b := r.Body.(map[string]interface{}) + + if date, ok := b["created"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.CreatedAt = t + } + + if date, ok := b["updated"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.UpdatedAt = t + } + + if cs, ok := b["cloud_server"].(map[string]interface{}); ok { + if t, ok := cs["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CreatedAt = creationTime + } + if t, ok := cs["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.UpdatedAt = updatedTime + } + if cn, ok := cs["cloud_network"].(map[string]interface{}); ok { + if t, ok := cn["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CloudNetwork.CreatedAt = creationTime + } + if t, ok := cn["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CloudNetwork.UpdatedAt = updatedTime + } + } + } + + return &res, err +} + +// DeleteNodeResult represents the result of a DeleteNode operation. +type DeleteNodeResult struct { + gophercloud.ErrResult +} + +// CreateNodesResult represents the result of a CreateNodes operation. +type CreateNodesResult struct { + gophercloud.Result +} + +// Extract is a function that extracts a slice of Nodes from a CreateNodesResult. +func (r CreateNodesResult) Extract() ([]Node, error) { + if r.Err != nil { + return nil, r.Err + } + var res []Node + err := mapstructure.Decode(r.Body, &res) + + b := r.Body.([]interface{}) + for i := range b { + if date, ok := b[i].(map[string]interface{})["created"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res[i].CreatedAt = t + } + if date, ok := b[i].(map[string]interface{})["updated"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res[i].UpdatedAt = t + } + } + + return res, err +} + +// DeleteNodesResult represents the result of a DeleteNodes operation. +type DeleteNodesResult struct { + gophercloud.ErrResult +} + +// NodeDetailsForServer represents a load balancer pool node associated with a RackConnect configuration +// with all its details for a particular server. +type NodeDetailsForServer struct { + // The unique ID of the LB node. + ID string `mapstructure:"id"` + // The load balancer pool. + LoadBalancerPool Pool `mapstructure:"load_balancer_pool"` + // The status of the LB pool. + Status string `mapstructure:"status"` + // The details of the status of the LB pool. + StatusDetail string `mapstructure:"status_detail"` + // The time the LB node was created. + CreatedAt time.Time `mapstructure:"-"` + // The time the LB node was last updated. + UpdatedAt time.Time `mapstructure:"-"` +} + +// NodeDetailsForServerPage is the page returned by a pager when traversing over a +// collection of NodeDetailsForServer. +type NodeDetailsForServerPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a NodeDetailsForServerPage contains no NodeDetailsForServer. +func (r NodeDetailsForServerPage) IsEmpty() (bool, error) { + n, err := ExtractNodesDetailsForServer(r) + if err != nil { + return true, err + } + return len(n) == 0, nil +} + +// ExtractNodesDetailsForServer extracts and returns a slice of NodeDetailsForServer. It is used while iterating over +// an lbpools.ListNodesDetailsForServer call. +func ExtractNodesDetailsForServer(page pagination.Page) ([]NodeDetailsForServer, error) { + var res []NodeDetailsForServer + casted := page.(NodeDetailsForServerPage).Body + err := mapstructure.Decode(casted, &res) + + var rawNodesDetails []interface{} + switch casted.(type) { + case interface{}: + rawNodesDetails = casted.([]interface{}) + default: + return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawNodesDetails { + thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{}) + + if t, ok := thisNodeDetails["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CreatedAt = creationTime + } + + if t, ok := thisNodeDetails["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].UpdatedAt = updatedTime + } + } + + return res, err +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/urls.go new file mode 100644 index 000000000..c238239f6 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools/urls.go @@ -0,0 +1,49 @@ +package lbpools + +import "github.com/rackspace/gophercloud" + +var root = "load_balancer_pools" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(root) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(root, id) +} + +func listNodesURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(root, id, "nodes") +} + +func createNodeURL(c *gophercloud.ServiceClient, id string) string { + return listNodesURL(c, id) +} + +func listNodesDetailsURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(root, id, "nodes", "details") +} + +func nodeURL(c *gophercloud.ServiceClient, poolID, nodeID string) string { + return c.ServiceURL(root, poolID, "nodes", nodeID) +} + +func deleteNodeURL(c *gophercloud.ServiceClient, poolID, nodeID string) string { + return nodeURL(c, poolID, nodeID) +} + +func nodeDetailsURL(c *gophercloud.ServiceClient, poolID, nodeID string) string { + return c.ServiceURL(root, poolID, "nodes", nodeID, "details") +} + +func createNodesURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(root, "nodes") +} + +func deleteNodesURL(c *gophercloud.ServiceClient) string { + return createNodesURL(c) +} + +func listNodesForServerURL(c *gophercloud.ServiceClient, serverID string) string { + return c.ServiceURL(root, "nodes", "details?cloud_server_id="+serverID) +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/requests.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/requests.go new file mode 100644 index 000000000..116426010 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/requests.go @@ -0,0 +1,50 @@ +package publicips + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// List returns all public IPs. +func List(c *gophercloud.ServiceClient) pagination.Pager { + url := listURL(c) + createPage := func(r pagination.PageResult) pagination.Page { + return PublicIPPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Create adds a public IP to the server with the given serverID. +func Create(c *gophercloud.ServiceClient, serverID string) CreateResult { + var res CreateResult + reqBody := map[string]interface{}{ + "cloud_server": map[string]string{ + "id": serverID, + }, + } + _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) + return res +} + +// ListForServer returns all public IPs for the server with the given serverID. +func ListForServer(c *gophercloud.ServiceClient, serverID string) pagination.Pager { + url := listForServerURL(c, serverID) + createPage := func(r pagination.PageResult) pagination.Page { + return PublicIPPage{pagination.SinglePageBase(r)} + } + return pagination.NewPager(c, url, createPage) +} + +// Get retrieves the public IP with the given id. +func Get(c *gophercloud.ServiceClient, id string) GetResult { + var res GetResult + _, res.Err = c.Get(getURL(c, id), &res.Body, nil) + return res +} + +// Delete removes the public IP with the given id. +func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { + var res DeleteResult + _, res.Err = c.Delete(deleteURL(c, id), nil) + return res +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/results.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/results.go new file mode 100644 index 000000000..132cf770a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/results.go @@ -0,0 +1,221 @@ +package publicips + +import ( + "fmt" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/pagination" +) + +// PublicIP represents a public IP address. +type PublicIP struct { + // The unique ID of the public IP. + ID string `mapstructure:"id"` + // The IPv4 address of the public IP. + PublicIPv4 string `mapstructure:"public_ip_v4"` + // The cloud server (node) of the public IP. + CloudServer struct { + // The cloud server ID. + ID string `mapstructure:"id"` + // The name of the server. + Name string `mapstructure:"name"` + // The cloud network for the cloud server. + CloudNetwork struct { + // The network ID. + ID string `mapstructure:"id"` + // The network name. + Name string `mapstructure:"name"` + // The network's private IPv4 address. + PrivateIPv4 string `mapstructure:"private_ip_v4"` + // The IP range for the network. + CIDR string `mapstructure:"cidr"` + // The datetime the network was created. + CreatedAt time.Time `mapstructure:"-"` + // The last datetime the network was updated. + UpdatedAt time.Time `mapstructure:"-"` + } `mapstructure:"cloud_network"` + // The datetime the server was created. + CreatedAt time.Time `mapstructure:"-"` + // The datetime the server was last updated. + UpdatedAt time.Time `mapstructure:"-"` + } `mapstructure:"cloud_server"` + // The status of the public IP. + Status string `mapstructure:"status"` + // The details of the status of the public IP. + StatusDetail string `mapstructure:"status_detail"` + // The time the public IP was created. + CreatedAt time.Time `mapstructure:"-"` + // The time the public IP was last updated. + UpdatedAt time.Time `mapstructure:"-"` +} + +// PublicIPPage is the page returned by a pager when traversing over a +// collection of PublicIPs. +type PublicIPPage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a PublicIPPage contains no PublicIPs. +func (r PublicIPPage) IsEmpty() (bool, error) { + n, err := ExtractPublicIPs(r) + if err != nil { + return true, err + } + return len(n) == 0, nil +} + +// ExtractPublicIPs extracts and returns a slice of PublicIPs. It is used while iterating over +// a publicips.List call. +func ExtractPublicIPs(page pagination.Page) ([]PublicIP, error) { + var res []PublicIP + casted := page.(PublicIPPage).Body + err := mapstructure.Decode(casted, &res) + + var rawNodesDetails []interface{} + switch casted.(type) { + case interface{}: + rawNodesDetails = casted.([]interface{}) + default: + return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted)) + } + + for i := range rawNodesDetails { + thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{}) + + if t, ok := thisNodeDetails["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CreatedAt = creationTime + } + + if t, ok := thisNodeDetails["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].UpdatedAt = updatedTime + } + + if cs, ok := thisNodeDetails["cloud_server"].(map[string]interface{}); ok { + if t, ok := cs["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CreatedAt = creationTime + } + if t, ok := cs["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.UpdatedAt = updatedTime + } + if cn, ok := cs["cloud_network"].(map[string]interface{}); ok { + if t, ok := cn["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CloudNetwork.CreatedAt = creationTime + } + if t, ok := cn["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return res, err + } + res[i].CloudServer.CloudNetwork.UpdatedAt = updatedTime + } + } + } + } + + return res, err +} + +// PublicIPResult represents a result that can be extracted into a PublicIP. +type PublicIPResult struct { + gophercloud.Result +} + +// CreateResult represents the result of a Create operation. +type CreateResult struct { + PublicIPResult +} + +// GetResult represents the result of a Get operation. +type GetResult struct { + PublicIPResult +} + +// Extract is a function that extracts a PublicIP from a PublicIPResult. +func (r PublicIPResult) Extract() (*PublicIP, error) { + if r.Err != nil { + return nil, r.Err + } + var res PublicIP + err := mapstructure.Decode(r.Body, &res) + + b := r.Body.(map[string]interface{}) + + if date, ok := b["created"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.CreatedAt = t + } + + if date, ok := b["updated"]; ok && date != nil { + t, err := time.Parse(time.RFC3339, date.(string)) + if err != nil { + return nil, err + } + res.UpdatedAt = t + } + + if cs, ok := b["cloud_server"].(map[string]interface{}); ok { + if t, ok := cs["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CreatedAt = creationTime + } + if t, ok := cs["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.UpdatedAt = updatedTime + } + if cn, ok := cs["cloud_network"].(map[string]interface{}); ok { + if t, ok := cn["created"].(string); ok && t != "" { + creationTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CloudNetwork.CreatedAt = creationTime + } + if t, ok := cn["updated"].(string); ok && t != "" { + updatedTime, err := time.Parse(time.RFC3339, t) + if err != nil { + return &res, err + } + res.CloudServer.CloudNetwork.UpdatedAt = updatedTime + } + } + } + + return &res, err +} + +// DeleteResult represents the result of a Delete operation. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/urls.go b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/urls.go new file mode 100644 index 000000000..6f310be4e --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips/urls.go @@ -0,0 +1,25 @@ +package publicips + +import "github.com/rackspace/gophercloud" + +var root = "public_ips" + +func listURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(root) +} + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(root) +} + +func listForServerURL(c *gophercloud.ServiceClient, serverID string) string { + return c.ServiceURL(root + "?cloud_server_id=" + serverID) +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(root, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return getURL(c, id) +} diff --git a/vendor/github.com/rackspace/gophercloud/results.go b/vendor/github.com/rackspace/gophercloud/results.go new file mode 100644 index 000000000..27fd1b60f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/results.go @@ -0,0 +1,153 @@ +package gophercloud + +import ( + "encoding/json" + "net/http" + "reflect" + + "github.com/mitchellh/mapstructure" +) + +/* +Result is an internal type to be used by individual resource packages, but its +methods will be available on a wide variety of user-facing embedding types. + +It acts as a base struct that other Result types, returned from request +functions, can embed for convenience. All Results capture basic information +from the HTTP transaction that was performed, including the response body, +HTTP headers, and any errors that happened. + +Generally, each Result type will have an Extract method that can be used to +further interpret the result's payload in a specific context. Extensions or +providers can then provide additional extraction functions to pull out +provider- or extension-specific information as well. +*/ +type Result struct { + // Body is the payload of the HTTP response from the server. In most cases, + // this will be the deserialized JSON structure. + Body interface{} + + // Header contains the HTTP header structure from the original response. + Header http.Header + + // Err is an error that occurred during the operation. It's deferred until + // extraction to make it easier to chain the Extract call. + Err error +} + +// PrettyPrintJSON creates a string containing the full response body as +// pretty-printed JSON. It's useful for capturing test fixtures and for +// debugging extraction bugs. If you include its output in an issue related to +// a buggy extraction function, we will all love you forever. +func (r Result) PrettyPrintJSON() string { + pretty, err := json.MarshalIndent(r.Body, "", " ") + if err != nil { + panic(err.Error()) + } + return string(pretty) +} + +// ErrResult is an internal type to be used by individual resource packages, but +// its methods will be available on a wide variety of user-facing embedding +// types. +// +// It represents results that only contain a potential error and +// nothing else. Usually, if the operation executed successfully, the Err field +// will be nil; otherwise it will be stocked with a relevant error. Use the +// ExtractErr method +// to cleanly pull it out. +type ErrResult struct { + Result +} + +// ExtractErr is a function that extracts error information, or nil, from a result. +func (r ErrResult) ExtractErr() error { + return r.Err +} + +/* +HeaderResult is an internal type to be used by individual resource packages, but +its methods will be available on a wide variety of user-facing embedding types. + +It represents a result that only contains an error (possibly nil) and an +http.Header. This is used, for example, by the objectstorage packages in +openstack, because most of the operations don't return response bodies, but do +have relevant information in headers. +*/ +type HeaderResult struct { + Result +} + +// ExtractHeader will return the http.Header and error from the HeaderResult. +// +// header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader() +func (hr HeaderResult) ExtractHeader() (http.Header, error) { + return hr.Header, hr.Err +} + +// DecodeHeader is a function that decodes a header (usually of type map[string]interface{}) to +// another type (usually a struct). This function is used by the objectstorage package to give +// users access to response headers without having to query a map. A DecodeHookFunction is used, +// because OpenStack-based clients return header values as arrays (Go slices). +func DecodeHeader(from, to interface{}) error { + config := &mapstructure.DecoderConfig{ + DecodeHook: func(from, to reflect.Kind, data interface{}) (interface{}, error) { + if from == reflect.Slice { + return data.([]string)[0], nil + } + return data, nil + }, + Result: to, + WeaklyTypedInput: true, + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return err + } + if err := decoder.Decode(from); err != nil { + return err + } + return nil +} + +// RFC3339Milli describes a common time format used by some API responses. +const RFC3339Milli = "2006-01-02T15:04:05.999999Z" + +// Time format used in cloud orchestration +const STACK_TIME_FMT = "2006-01-02T15:04:05" + +/* +Link is an internal type to be used in packages of collection resources that are +paginated in a certain way. + +It's a response substructure common to many paginated collection results that is +used to point to related pages. Usually, the one we care about is the one with +Rel field set to "next". +*/ +type Link struct { + Href string `mapstructure:"href"` + Rel string `mapstructure:"rel"` +} + +/* +ExtractNextURL is an internal function useful for packages of collection +resources that are paginated in a certain way. + +It attempts attempts to extract the "next" URL from slice of Link structs, or +"" if no such URL is present. +*/ +func ExtractNextURL(links []Link) (string, error) { + var url string + + for _, l := range links { + if l.Rel == "next" { + url = l.Href + } + } + + if url == "" { + return "", nil + } + + return url, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/script/acceptancetest b/vendor/github.com/rackspace/gophercloud/script/acceptancetest new file mode 100644 index 000000000..f9c89f4df --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/script/acceptancetest @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Run the acceptance tests. + +exec go test -p=1 -tags 'acceptance fixtures' github.com/rackspace/gophercloud/acceptance/... $@ diff --git a/vendor/github.com/rackspace/gophercloud/script/bootstrap b/vendor/github.com/rackspace/gophercloud/script/bootstrap new file mode 100644 index 000000000..6bae6e8f1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/script/bootstrap @@ -0,0 +1,26 @@ +#!/bin/bash +# +# This script helps new contributors set up their local workstation for +# gophercloud development and contributions. + +# Create the environment +export GOPATH=$HOME/go/gophercloud +mkdir -p $GOPATH + +# Download gophercloud into that environment +go get github.com/rackspace/gophercloud +cd $GOPATH/src/github.com/rackspace/gophercloud +git checkout master + +# Write out the env.sh convenience file. +cd $GOPATH +cat <env.sh +#!/bin/bash +export GOPATH=$(pwd) +export GOPHERCLOUD=$GOPATH/src/github.com/rackspace/gophercloud +EOF +chmod a+x env.sh + +# Make changes immediately available as a convenience. +. ./env.sh + diff --git a/vendor/github.com/rackspace/gophercloud/script/cibuild b/vendor/github.com/rackspace/gophercloud/script/cibuild new file mode 100644 index 000000000..1cb389e7d --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/script/cibuild @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Test script to be invoked by Travis. + +exec script/unittest -v diff --git a/vendor/github.com/rackspace/gophercloud/script/test b/vendor/github.com/rackspace/gophercloud/script/test new file mode 100644 index 000000000..1e03dff8a --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/script/test @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Run all the tests. + +exec go test -tags 'acceptance fixtures' ./... $@ diff --git a/vendor/github.com/rackspace/gophercloud/script/unittest b/vendor/github.com/rackspace/gophercloud/script/unittest new file mode 100644 index 000000000..d3440a902 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/script/unittest @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Run the unit tests. + +exec go test -tags fixtures ./... $@ diff --git a/vendor/github.com/rackspace/gophercloud/service_client.go b/vendor/github.com/rackspace/gophercloud/service_client.go new file mode 100644 index 000000000..3490da05f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/service_client.go @@ -0,0 +1,32 @@ +package gophercloud + +import "strings" + +// ServiceClient stores details required to interact with a specific service API implemented by a provider. +// Generally, you'll acquire these by calling the appropriate `New` method on a ProviderClient. +type ServiceClient struct { + // ProviderClient is a reference to the provider that implements this service. + *ProviderClient + + // Endpoint is the base URL of the service's API, acquired from a service catalog. + // It MUST end with a /. + Endpoint string + + // ResourceBase is the base URL shared by the resources within a service's API. It should include + // the API version and, like Endpoint, MUST end with a / if set. If not set, the Endpoint is used + // as-is, instead. + ResourceBase string +} + +// ResourceBaseURL returns the base URL of any resources used by this service. It MUST end with a /. +func (client *ServiceClient) ResourceBaseURL() string { + if client.ResourceBase != "" { + return client.ResourceBase + } + return client.Endpoint +} + +// ServiceURL constructs a URL for a resource belonging to this provider. +func (client *ServiceClient) ServiceURL(parts ...string) string { + return client.ResourceBaseURL() + strings.Join(parts, "/") +} diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/client/fake.go b/vendor/github.com/rackspace/gophercloud/testhelper/client/fake.go new file mode 100644 index 000000000..5b69b058f --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/testhelper/client/fake.go @@ -0,0 +1,17 @@ +package client + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/testhelper" +) + +// Fake token to use. +const TokenID = "cbc36478b0bd8e67e89469c7749d4127" + +// ServiceClient returns a generic service client for use in tests. +func ServiceClient() *gophercloud.ServiceClient { + return &gophercloud.ServiceClient{ + ProviderClient: &gophercloud.ProviderClient{TokenID: TokenID}, + Endpoint: testhelper.Endpoint(), + } +} diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go b/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go new file mode 100644 index 000000000..cf33e1ad1 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go @@ -0,0 +1,329 @@ +package testhelper + +import ( + "encoding/json" + "fmt" + "path/filepath" + "reflect" + "runtime" + "strings" + "testing" +) + +const ( + logBodyFmt = "\033[1;31m%s %s\033[0m" + greenCode = "\033[0m\033[1;32m" + yellowCode = "\033[0m\033[1;33m" + resetCode = "\033[0m\033[1;31m" +) + +func prefix(depth int) string { + _, file, line, _ := runtime.Caller(depth) + return fmt.Sprintf("Failure in %s, line %d:", filepath.Base(file), line) +} + +func green(str interface{}) string { + return fmt.Sprintf("%s%#v%s", greenCode, str, resetCode) +} + +func yellow(str interface{}) string { + return fmt.Sprintf("%s%#v%s", yellowCode, str, resetCode) +} + +func logFatal(t *testing.T, str string) { + t.Fatalf(logBodyFmt, prefix(3), str) +} + +func logError(t *testing.T, str string) { + t.Errorf(logBodyFmt, prefix(3), str) +} + +type diffLogger func([]string, interface{}, interface{}) + +type visit struct { + a1 uintptr + a2 uintptr + typ reflect.Type +} + +// Recursively visits the structures of "expected" and "actual". The diffLogger function will be +// invoked with each different value encountered, including the reference path that was followed +// to get there. +func deepDiffEqual(expected, actual reflect.Value, visited map[visit]bool, path []string, logDifference diffLogger) { + defer func() { + // Fall back to the regular reflect.DeepEquals function. + if r := recover(); r != nil { + var e, a interface{} + if expected.IsValid() { + e = expected.Interface() + } + if actual.IsValid() { + a = actual.Interface() + } + + if !reflect.DeepEqual(e, a) { + logDifference(path, e, a) + } + } + }() + + if !expected.IsValid() && actual.IsValid() { + logDifference(path, nil, actual.Interface()) + return + } + if expected.IsValid() && !actual.IsValid() { + logDifference(path, expected.Interface(), nil) + return + } + if !expected.IsValid() && !actual.IsValid() { + return + } + + hard := func(k reflect.Kind) bool { + switch k { + case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct: + return true + } + return false + } + + if expected.CanAddr() && actual.CanAddr() && hard(expected.Kind()) { + addr1 := expected.UnsafeAddr() + addr2 := actual.UnsafeAddr() + + if addr1 > addr2 { + addr1, addr2 = addr2, addr1 + } + + if addr1 == addr2 { + // References are identical. We can short-circuit + return + } + + typ := expected.Type() + v := visit{addr1, addr2, typ} + if visited[v] { + // Already visited. + return + } + + // Remember this visit for later. + visited[v] = true + } + + switch expected.Kind() { + case reflect.Array: + for i := 0; i < expected.Len(); i++ { + hop := append(path, fmt.Sprintf("[%d]", i)) + deepDiffEqual(expected.Index(i), actual.Index(i), visited, hop, logDifference) + } + return + case reflect.Slice: + if expected.IsNil() != actual.IsNil() { + logDifference(path, expected.Interface(), actual.Interface()) + return + } + if expected.Len() == actual.Len() && expected.Pointer() == actual.Pointer() { + return + } + for i := 0; i < expected.Len(); i++ { + hop := append(path, fmt.Sprintf("[%d]", i)) + deepDiffEqual(expected.Index(i), actual.Index(i), visited, hop, logDifference) + } + return + case reflect.Interface: + if expected.IsNil() != actual.IsNil() { + logDifference(path, expected.Interface(), actual.Interface()) + return + } + deepDiffEqual(expected.Elem(), actual.Elem(), visited, path, logDifference) + return + case reflect.Ptr: + deepDiffEqual(expected.Elem(), actual.Elem(), visited, path, logDifference) + return + case reflect.Struct: + for i, n := 0, expected.NumField(); i < n; i++ { + field := expected.Type().Field(i) + hop := append(path, "."+field.Name) + deepDiffEqual(expected.Field(i), actual.Field(i), visited, hop, logDifference) + } + return + case reflect.Map: + if expected.IsNil() != actual.IsNil() { + logDifference(path, expected.Interface(), actual.Interface()) + return + } + if expected.Len() == actual.Len() && expected.Pointer() == actual.Pointer() { + return + } + + var keys []reflect.Value + if expected.Len() >= actual.Len() { + keys = expected.MapKeys() + } else { + keys = actual.MapKeys() + } + + for _, k := range keys { + expectedValue := expected.MapIndex(k) + actualValue := expected.MapIndex(k) + + if !expectedValue.IsValid() { + logDifference(path, nil, actual.Interface()) + return + } + if !actualValue.IsValid() { + logDifference(path, expected.Interface(), nil) + return + } + + hop := append(path, fmt.Sprintf("[%v]", k)) + deepDiffEqual(expectedValue, actualValue, visited, hop, logDifference) + } + return + case reflect.Func: + if expected.IsNil() != actual.IsNil() { + logDifference(path, expected.Interface(), actual.Interface()) + } + return + default: + if expected.Interface() != actual.Interface() { + logDifference(path, expected.Interface(), actual.Interface()) + } + } +} + +func deepDiff(expected, actual interface{}, logDifference diffLogger) { + if expected == nil || actual == nil { + logDifference([]string{}, expected, actual) + return + } + + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + + if expectedValue.Type() != actualValue.Type() { + logDifference([]string{}, expected, actual) + return + } + deepDiffEqual(expectedValue, actualValue, map[visit]bool{}, []string{}, logDifference) +} + +// AssertEquals compares two arbitrary values and performs a comparison. If the +// comparison fails, a fatal error is raised that will fail the test +func AssertEquals(t *testing.T, expected, actual interface{}) { + if expected != actual { + logFatal(t, fmt.Sprintf("expected %s but got %s", green(expected), yellow(actual))) + } +} + +// CheckEquals is similar to AssertEquals, except with a non-fatal error +func CheckEquals(t *testing.T, expected, actual interface{}) { + if expected != actual { + logError(t, fmt.Sprintf("expected %s but got %s", green(expected), yellow(actual))) + } +} + +// AssertDeepEquals - like Equals - performs a comparison - but on more complex +// structures that requires deeper inspection +func AssertDeepEquals(t *testing.T, expected, actual interface{}) { + pre := prefix(2) + + differed := false + deepDiff(expected, actual, func(path []string, expected, actual interface{}) { + differed = true + t.Errorf("\033[1;31m%sat %s expected %s, but got %s\033[0m", + pre, + strings.Join(path, ""), + green(expected), + yellow(actual)) + }) + if differed { + logFatal(t, "The structures were different.") + } +} + +// CheckDeepEquals is similar to AssertDeepEquals, except with a non-fatal error +func CheckDeepEquals(t *testing.T, expected, actual interface{}) { + pre := prefix(2) + + deepDiff(expected, actual, func(path []string, expected, actual interface{}) { + t.Errorf("\033[1;31m%s at %s expected %s, but got %s\033[0m", + pre, + strings.Join(path, ""), + green(expected), + yellow(actual)) + }) +} + +// isJSONEquals is a utility function that implements JSON comparison for AssertJSONEquals and +// CheckJSONEquals. +func isJSONEquals(t *testing.T, expectedJSON string, actual interface{}) bool { + var parsedExpected, parsedActual interface{} + err := json.Unmarshal([]byte(expectedJSON), &parsedExpected) + if err != nil { + t.Errorf("Unable to parse expected value as JSON: %v", err) + return false + } + + jsonActual, err := json.Marshal(actual) + AssertNoErr(t, err) + err = json.Unmarshal(jsonActual, &parsedActual) + AssertNoErr(t, err) + + if !reflect.DeepEqual(parsedExpected, parsedActual) { + prettyExpected, err := json.MarshalIndent(parsedExpected, "", " ") + if err != nil { + t.Logf("Unable to pretty-print expected JSON: %v\n%s", err, expectedJSON) + } else { + // We can't use green() here because %#v prints prettyExpected as a byte array literal, which + // is... unhelpful. Converting it to a string first leaves "\n" uninterpreted for some reason. + t.Logf("Expected JSON:\n%s%s%s", greenCode, prettyExpected, resetCode) + } + + prettyActual, err := json.MarshalIndent(actual, "", " ") + if err != nil { + t.Logf("Unable to pretty-print actual JSON: %v\n%#v", err, actual) + } else { + // We can't use yellow() for the same reason. + t.Logf("Actual JSON:\n%s%s%s", yellowCode, prettyActual, resetCode) + } + + return false + } + return true +} + +// AssertJSONEquals serializes a value as JSON, parses an expected string as JSON, and ensures that +// both are consistent. If they aren't, the expected and actual structures are pretty-printed and +// shown for comparison. +// +// This is useful for comparing structures that are built as nested map[string]interface{} values, +// which are a pain to construct as literals. +func AssertJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { + if !isJSONEquals(t, expectedJSON, actual) { + logFatal(t, "The generated JSON structure differed.") + } +} + +// CheckJSONEquals is similar to AssertJSONEquals, but nonfatal. +func CheckJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { + if !isJSONEquals(t, expectedJSON, actual) { + logError(t, "The generated JSON structure differed.") + } +} + +// AssertNoErr is a convenience function for checking whether an error value is +// an actual error +func AssertNoErr(t *testing.T, e error) { + if e != nil { + logFatal(t, fmt.Sprintf("unexpected error %s", yellow(e.Error()))) + } +} + +// CheckNoErr is similar to AssertNoErr, except with a non-fatal error +func CheckNoErr(t *testing.T, e error) { + if e != nil { + logError(t, fmt.Sprintf("unexpected error %s", yellow(e.Error()))) + } +} diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/doc.go b/vendor/github.com/rackspace/gophercloud/testhelper/doc.go new file mode 100644 index 000000000..25b4dfebb --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/testhelper/doc.go @@ -0,0 +1,4 @@ +/* +Package testhelper container methods that are useful for writing unit tests. +*/ +package testhelper diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/fixture/helper.go b/vendor/github.com/rackspace/gophercloud/testhelper/fixture/helper.go new file mode 100644 index 000000000..d54355d75 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/testhelper/fixture/helper.go @@ -0,0 +1,31 @@ +package fixture + +import ( + "fmt" + "net/http" + "testing" + + th "github.com/rackspace/gophercloud/testhelper" + "github.com/rackspace/gophercloud/testhelper/client" +) + +func SetupHandler(t *testing.T, url, method, requestBody, responseBody string, status int) { + th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, method) + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + if requestBody != "" { + th.TestJSONRequest(t, r, requestBody) + } + + if responseBody != "" { + w.Header().Add("Content-Type", "application/json") + } + + w.WriteHeader(status) + + if responseBody != "" { + fmt.Fprintf(w, responseBody) + } + }) +} diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/http_responses.go b/vendor/github.com/rackspace/gophercloud/testhelper/http_responses.go new file mode 100644 index 000000000..e1f1f9ac0 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/testhelper/http_responses.go @@ -0,0 +1,91 @@ +package testhelper + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "reflect" + "testing" +) + +var ( + // Mux is a multiplexer that can be used to register handlers. + Mux *http.ServeMux + + // Server is an in-memory HTTP server for testing. + Server *httptest.Server +) + +// SetupHTTP prepares the Mux and Server. +func SetupHTTP() { + Mux = http.NewServeMux() + Server = httptest.NewServer(Mux) +} + +// TeardownHTTP releases HTTP-related resources. +func TeardownHTTP() { + Server.Close() +} + +// Endpoint returns a fake endpoint that will actually target the Mux. +func Endpoint() string { + return Server.URL + "/" +} + +// TestFormValues ensures that all the URL parameters given to the http.Request are the same as values. +func TestFormValues(t *testing.T, r *http.Request, values map[string]string) { + want := url.Values{} + for k, v := range values { + want.Add(k, v) + } + + r.ParseForm() + if !reflect.DeepEqual(want, r.Form) { + t.Errorf("Request parameters = %v, want %v", r.Form, want) + } +} + +// TestMethod checks that the Request has the expected method (e.g. GET, POST). +func TestMethod(t *testing.T, r *http.Request, expected string) { + if expected != r.Method { + t.Errorf("Request method = %v, expected %v", r.Method, expected) + } +} + +// TestHeader checks that the header on the http.Request matches the expected value. +func TestHeader(t *testing.T, r *http.Request, header string, expected string) { + if actual := r.Header.Get(header); expected != actual { + t.Errorf("Header %s = %s, expected %s", header, actual, expected) + } +} + +// TestBody verifies that the request body matches an expected body. +func TestBody(t *testing.T, r *http.Request, expected string) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Unable to read body: %v", err) + } + str := string(b) + if expected != str { + t.Errorf("Body = %s, expected %s", str, expected) + } +} + +// TestJSONRequest verifies that the JSON payload of a request matches an expected structure, without asserting things about +// whitespace or ordering. +func TestJSONRequest(t *testing.T, r *http.Request, expected string) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Unable to read request body: %v", err) + } + + var actualJSON interface{} + err = json.Unmarshal(b, &actualJSON) + if err != nil { + t.Errorf("Unable to parse request body as JSON: %v", err) + } + + CheckJSONEquals(t, expected, actualJSON) +} diff --git a/vendor/github.com/rackspace/gophercloud/util.go b/vendor/github.com/rackspace/gophercloud/util.go new file mode 100644 index 000000000..3d6a4e490 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/util.go @@ -0,0 +1,82 @@ +package gophercloud + +import ( + "errors" + "net/url" + "path/filepath" + "strings" + "time" +) + +// WaitFor polls a predicate function, once per second, up to a timeout limit. +// It usually does this to wait for a resource to transition to a certain state. +// Resource packages will wrap this in a more convenient function that's +// specific to a certain resource, but it can also be useful on its own. +func WaitFor(timeout int, predicate func() (bool, error)) error { + start := time.Now().Second() + for { + // Force a 1s sleep + time.Sleep(1 * time.Second) + + // If a timeout is set, and that's been exceeded, shut it down + if timeout >= 0 && time.Now().Second()-start >= timeout { + return errors.New("A timeout occurred") + } + + // Execute the function + satisfied, err := predicate() + if err != nil { + return err + } + if satisfied { + return nil + } + } +} + +// NormalizeURL is an internal function to be used by provider clients. +// +// It ensures that each endpoint URL has a closing `/`, as expected by +// ServiceClient's methods. +func NormalizeURL(url string) string { + if !strings.HasSuffix(url, "/") { + return url + "/" + } + return url +} + +// NormalizePathURL is used to convert rawPath to a fqdn, using basePath as +// a reference in the filesystem, if necessary. basePath is assumed to contain +// either '.' when first used, or the file:// type fqdn of the parent resource. +// e.g. myFavScript.yaml => file://opt/lib/myFavScript.yaml +func NormalizePathURL(basePath, rawPath string) (string, error) { + u, err := url.Parse(rawPath) + if err != nil { + return "", err + } + // if a scheme is defined, it must be a fqdn already + if u.Scheme != "" { + return u.String(), nil + } + // if basePath is a url, then child resources are assumed to be relative to it + bu, err := url.Parse(basePath) + if err != nil { + return "", err + } + var basePathSys, absPathSys string + if bu.Scheme != "" { + basePathSys = filepath.FromSlash(bu.Path) + absPathSys = filepath.Join(basePathSys, rawPath) + bu.Path = filepath.ToSlash(absPathSys) + return bu.String(), nil + } + + absPathSys = filepath.Join(basePath, rawPath) + u.Path = filepath.ToSlash(absPathSys) + if err != nil { + return "", err + } + u.Scheme = "file" + return u.String(), nil + +} diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml new file mode 100644 index 000000000..2199ce904 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/.travis.yml @@ -0,0 +1,11 @@ +language: go +go: + - 1.0 + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 +sudo: false +notifications: + email: false diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE new file mode 100644 index 000000000..6a1fb910d --- /dev/null +++ b/vendor/github.com/satori/go.uuid/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013-2015 by Maxim Bublis + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md new file mode 100644 index 000000000..48d4937f4 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/README.md @@ -0,0 +1,66 @@ +# UUID package for Go language + +[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) +[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) + +This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. + +With 100% test coverage and benchmarks out of box. + +Supported versions: +* Version 1, based on timestamp and MAC address (RFC 4122) +* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) +* Version 3, based on MD5 hashing (RFC 4122) +* Version 4, based on random numbers (RFC 4122) +* Version 5, based on SHA-1 hashing (RFC 4122) + +## Installation + +Use the `go` command: + + $ go get github.com/satori/go.uuid + +## Requirements + +UUID package requires any stable version of Go Programming Language. + +It is tested against following versions of Go: 1.0-1.5 + +## Example + +```go +package main + +import ( + "fmt" + "github.com/satori/go.uuid" +) + +func main() { + // Creating UUID Version 4 + u1 := uuid.NewV4() + fmt.Printf("UUIDv4: %s\n", u1) + + // Parsing UUID from string input + u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + fmt.Printf("Something gone wrong: %s", err) + } + fmt.Printf("Successfully parsed: %s", u2) +} +``` + +## Documentation + +[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. + +## Links +* [RFC 4122](http://tools.ietf.org/html/rfc4122) +* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) + +## Copyright + +Copyright (C) 2013-2015 by Maxim Bublis . + +UUID package released under MIT License. +See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go new file mode 100644 index 000000000..03841d86e --- /dev/null +++ b/vendor/github.com/satori/go.uuid/uuid.go @@ -0,0 +1,435 @@ +// Copyright (C) 2013-2015 by Maxim Bublis +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Package uuid provides implementation of Universally Unique Identifier (UUID). +// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and +// version 2 (as specified in DCE 1.1). +package uuid + +import ( + "bytes" + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "database/sql/driver" + "encoding/binary" + "encoding/hex" + "fmt" + "hash" + "net" + "os" + "sync" + "time" +) + +// UUID layout variants. +const ( + VariantNCS = iota + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// UUID DCE domains. +const ( + DomainPerson = iota + DomainGroup + DomainOrg +) + +// Difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). +const epochStart = 122192928000000000 + +// Used in string method conversion +const dash byte = '-' + +// UUID v1/v2 storage. +var ( + storageMutex sync.Mutex + storageOnce sync.Once + epochFunc = unixTimeFunc + clockSequence uint16 + lastTime uint64 + hardwareAddr [6]byte + posixUID = uint32(os.Getuid()) + posixGID = uint32(os.Getgid()) +) + +// String parse helpers. +var ( + urnPrefix = []byte("urn:uuid:") + byteGroups = []int{8, 4, 4, 4, 12} +) + +func initClockSequence() { + buf := make([]byte, 2) + safeRandom(buf) + clockSequence = binary.BigEndian.Uint16(buf) +} + +func initHardwareAddr() { + interfaces, err := net.Interfaces() + if err == nil { + for _, iface := range interfaces { + if len(iface.HardwareAddr) >= 6 { + copy(hardwareAddr[:], iface.HardwareAddr) + return + } + } + } + + // Initialize hardwareAddr randomly in case + // of real network interfaces absence + safeRandom(hardwareAddr[:]) + + // Set multicast bit as recommended in RFC 4122 + hardwareAddr[0] |= 0x01 +} + +func initStorage() { + initClockSequence() + initHardwareAddr() +} + +func safeRandom(dest []byte) { + if _, err := rand.Read(dest); err != nil { + panic(err) + } +} + +// Returns difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and current time. +// This is default epoch calculation function. +func unixTimeFunc() uint64 { + return epochStart + uint64(time.Now().UnixNano()/100) +} + +// UUID representation compliant with specification +// described in RFC 4122. +type UUID [16]byte + +// The nil UUID is special form of UUID that is specified to have all +// 128 bits set to zero. +var Nil = UUID{} + +// Predefined namespace UUIDs. +var ( + NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") + NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") + NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +) + +// And returns result of binary AND of two UUIDs. +func And(u1 UUID, u2 UUID) UUID { + u := UUID{} + for i := 0; i < 16; i++ { + u[i] = u1[i] & u2[i] + } + return u +} + +// Or returns result of binary OR of two UUIDs. +func Or(u1 UUID, u2 UUID) UUID { + u := UUID{} + for i := 0; i < 16; i++ { + u[i] = u1[i] | u2[i] + } + return u +} + +// Equal returns true if u1 and u2 equals, otherwise returns false. +func Equal(u1 UUID, u2 UUID) bool { + return bytes.Equal(u1[:], u2[:]) +} + +// Version returns algorithm version used to generate UUID. +func (u UUID) Version() uint { + return uint(u[6] >> 4) +} + +// Variant returns UUID layout variant. +func (u UUID) Variant() uint { + switch { + case (u[8] & 0x80) == 0x00: + return VariantNCS + case (u[8]&0xc0)|0x80 == 0x80: + return VariantRFC4122 + case (u[8]&0xe0)|0xc0 == 0xc0: + return VariantMicrosoft + } + return VariantFuture +} + +// Bytes returns bytes slice representation of UUID. +func (u UUID) Bytes() []byte { + return u[:] +} + +// Returns canonical string representation of UUID: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +func (u UUID) String() string { + buf := make([]byte, 36) + + hex.Encode(buf[0:8], u[0:4]) + buf[8] = dash + hex.Encode(buf[9:13], u[4:6]) + buf[13] = dash + hex.Encode(buf[14:18], u[6:8]) + buf[18] = dash + hex.Encode(buf[19:23], u[8:10]) + buf[23] = dash + hex.Encode(buf[24:], u[10:]) + + return string(buf) +} + +// SetVersion sets version bits. +func (u *UUID) SetVersion(v byte) { + u[6] = (u[6] & 0x0f) | (v << 4) +} + +// SetVariant sets variant bits as described in RFC 4122. +func (u *UUID) SetVariant() { + u[8] = (u[8] & 0xbf) | 0x80 +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The encoding is the same as returned by String. +func (u UUID) MarshalText() (text []byte, err error) { + text = []byte(u.String()) + return +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Following formats are supported: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +func (u *UUID) UnmarshalText(text []byte) (err error) { + if len(text) < 32 { + err = fmt.Errorf("uuid: invalid UUID string: %s", text) + return + } + + if bytes.Equal(text[:9], urnPrefix) { + text = text[9:] + } else if text[0] == '{' { + text = text[1:] + } + + b := u[:] + + for _, byteGroup := range byteGroups { + if text[0] == '-' { + text = text[1:] + } + + _, err = hex.Decode(b[:byteGroup/2], text[:byteGroup]) + + if err != nil { + return + } + + text = text[byteGroup:] + b = b[byteGroup/2:] + } + + return +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (u UUID) MarshalBinary() (data []byte, err error) { + data = u.Bytes() + return +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It will return error if the slice isn't 16 bytes long. +func (u *UUID) UnmarshalBinary(data []byte) (err error) { + if len(data) != 16 { + err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) + return + } + copy(u[:], data) + + return +} + +// Value implements the driver.Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.String(), nil +} + +// Scan implements the sql.Scanner interface. +// A 16-byte slice is handled by UnmarshalBinary, while +// a longer byte slice or a string is handled by UnmarshalText. +func (u *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + if len(src) == 16 { + return u.UnmarshalBinary(src) + } + return u.UnmarshalText(src) + + case string: + return u.UnmarshalText([]byte(src)) + } + + return fmt.Errorf("uuid: cannot convert %T to UUID", src) +} + +// FromBytes returns UUID converted from raw byte slice input. +// It will return error if the slice isn't 16 bytes long. +func FromBytes(input []byte) (u UUID, err error) { + err = u.UnmarshalBinary(input) + return +} + +// FromBytesOrNil returns UUID converted from raw byte slice input. +// Same behavior as FromBytes, but returns a Nil UUID on error. +func FromBytesOrNil(input []byte) UUID { + uuid, err := FromBytes(input) + if err != nil { + return Nil + } + return uuid +} + +// FromString returns UUID parsed from string input. +// Input is expected in a form accepted by UnmarshalText. +func FromString(input string) (u UUID, err error) { + err = u.UnmarshalText([]byte(input)) + return +} + +// FromStringOrNil returns UUID parsed from string input. +// Same behavior as FromString, but returns a Nil UUID on error. +func FromStringOrNil(input string) UUID { + uuid, err := FromString(input) + if err != nil { + return Nil + } + return uuid +} + +// Returns UUID v1/v2 storage state. +// Returns epoch timestamp, clock sequence, and hardware address. +func getStorage() (uint64, uint16, []byte) { + storageOnce.Do(initStorage) + + storageMutex.Lock() + defer storageMutex.Unlock() + + timeNow := epochFunc() + // Clock changed backwards since last UUID generation. + // Should increase clock sequence. + if timeNow <= lastTime { + clockSequence++ + } + lastTime = timeNow + + return timeNow, clockSequence, hardwareAddr[:] +} + +// NewV1 returns UUID based on current timestamp and MAC address. +func NewV1() UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := getStorage() + + binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + + copy(u[10:], hardwareAddr) + + u.SetVersion(1) + u.SetVariant() + + return u +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func NewV2(domain byte) UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := getStorage() + + switch domain { + case DomainPerson: + binary.BigEndian.PutUint32(u[0:], posixUID) + case DomainGroup: + binary.BigEndian.PutUint32(u[0:], posixGID) + } + + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + u[9] = domain + + copy(u[10:], hardwareAddr) + + u.SetVersion(2) + u.SetVariant() + + return u +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func NewV3(ns UUID, name string) UUID { + u := newFromHash(md5.New(), ns, name) + u.SetVersion(3) + u.SetVariant() + + return u +} + +// NewV4 returns random generated UUID. +func NewV4() UUID { + u := UUID{} + safeRandom(u[:]) + u.SetVersion(4) + u.SetVariant() + + return u +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func NewV5(ns UUID, name string) UUID { + u := newFromHash(sha1.New(), ns, name) + u.SetVersion(5) + u.SetVariant() + + return u +} + +// Returns UUID based on hashing of namespace UUID and name. +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} diff --git a/vendor/github.com/tent/http-link-go/.gitignore b/vendor/github.com/tent/http-link-go/.gitignore new file mode 100644 index 000000000..9ed3b07ce --- /dev/null +++ b/vendor/github.com/tent/http-link-go/.gitignore @@ -0,0 +1 @@ +*.test diff --git a/vendor/github.com/tent/http-link-go/.travis.yml b/vendor/github.com/tent/http-link-go/.travis.yml new file mode 100644 index 000000000..7362f08e4 --- /dev/null +++ b/vendor/github.com/tent/http-link-go/.travis.yml @@ -0,0 +1,6 @@ +language: go +go: + - 1.1 + - tip +before_install: + - go get launchpad.net/gocheck diff --git a/vendor/github.com/tent/http-link-go/LICENSE b/vendor/github.com/tent/http-link-go/LICENSE new file mode 100644 index 000000000..88dcd4afd --- /dev/null +++ b/vendor/github.com/tent/http-link-go/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Tent.is, LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Tent.is, LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/tent/http-link-go/README.md b/vendor/github.com/tent/http-link-go/README.md new file mode 100644 index 000000000..07d470e4d --- /dev/null +++ b/vendor/github.com/tent/http-link-go/README.md @@ -0,0 +1,12 @@ +# http-link-go [![Build Status](https://travis-ci.org/tent/http-link-go.png?branch=master)](https://travis-ci.org/tent/http-link-go) + +http-link-go implements parsing and serialization of Link header values as +defined in [RFC 5988](https://tools.ietf.org/html/rfc5988). + +[**Documentation**](http://godoc.org/github.com/tent/http-link-go) + +## Installation + +```text +go get github.com/tent/http-link-go +``` diff --git a/vendor/github.com/tent/http-link-go/link.go b/vendor/github.com/tent/http-link-go/link.go new file mode 100644 index 000000000..584dfd051 --- /dev/null +++ b/vendor/github.com/tent/http-link-go/link.go @@ -0,0 +1,185 @@ +// Package link implements parsing and serialization of Link header values as +// defined in RFC 5988. +package link + +import ( + "bytes" + "errors" + "sort" + "unicode" +) + +type Link struct { + URI string + Rel string + Params map[string]string +} + +// Format serializes a slice of Links into a header value. It does not currently +// implement RFC 2231 handling of non-ASCII character encoding and language +// information. +func Format(links []Link) string { + buf := &bytes.Buffer{} + for i, link := range links { + if i > 0 { + buf.Write([]byte(", ")) + } + buf.WriteByte('<') + buf.WriteString(link.URI) + buf.WriteByte('>') + + writeParam(buf, "rel", link.Rel) + + keys := make([]string, 0, len(link.Params)) + for k := range link.Params { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + writeParam(buf, k, link.Params[k]) + } + } + + return buf.String() +} + +func writeParam(buf *bytes.Buffer, key, value string) { + buf.Write([]byte("; ")) + buf.WriteString(key) + buf.Write([]byte(`="`)) + buf.WriteString(value) + buf.WriteByte('"') +} + +// Parse parses a Link header value into a slice of Links. It does not currently +// implement RFC 2231 handling of non-ASCII character encoding and language +// information. +func Parse(l string) ([]Link, error) { + v := []byte(l) + v = bytes.TrimSpace(v) + if len(v) == 0 { + return nil, nil + } + + links := make([]Link, 0, 1) + for len(v) > 0 { + if v[0] != '<' { + return nil, errors.New("link: does not start with <") + } + lend := bytes.IndexByte(v, '>') + if lend == -1 { + return nil, errors.New("link: does not contain ending >") + } + + params := make(map[string]string) + link := Link{URI: string(v[1:lend]), Params: params} + links = append(links, link) + + // trim off parsed url + v = v[lend+1:] + if len(v) == 0 { + break + } + v = bytes.TrimLeftFunc(v, unicode.IsSpace) + + for len(v) > 0 { + if v[0] != ';' && v[0] != ',' { + return nil, errors.New(`link: expected ";" or "'", got "` + string(v[0:1]) + `"`) + } + var next bool + if v[0] == ',' { + next = true + } + v = bytes.TrimLeftFunc(v[1:], unicode.IsSpace) + if next || len(v) == 0 { + break + } + var key, value []byte + key, value, v = consumeParam(v) + if key == nil || value == nil { + return nil, errors.New("link: malformed param") + } + if k := string(key); k == "rel" { + if links[len(links)-1].Rel == "" { + links[len(links)-1].Rel = string(value) + } + } else { + params[k] = string(value) + } + v = bytes.TrimLeftFunc(v, unicode.IsSpace) + } + } + + return links, nil +} + +func isTokenChar(r rune) bool { + return r > 0x20 && r < 0x7f && r != '"' && r != ',' && r != '=' && r != ';' +} + +func isNotTokenChar(r rune) bool { return !isTokenChar(r) } + +func consumeToken(v []byte) (token, rest []byte) { + notPos := bytes.IndexFunc(v, isNotTokenChar) + if notPos == -1 { + return v, nil + } + if notPos == 0 { + return nil, v + } + return v[0:notPos], v[notPos:] +} + +func consumeValue(v []byte) (value, rest []byte) { + if v[0] != '"' { + return nil, v + } + + rest = v[1:] + buffer := &bytes.Buffer{} + var nextIsLiteral bool + for idx, r := range string(rest) { + switch { + case nextIsLiteral: + buffer.WriteRune(r) + nextIsLiteral = false + case r == '"': + return buffer.Bytes(), rest[idx+1:] + case r == '\\': + nextIsLiteral = true + case r != '\r' && r != '\n': + buffer.WriteRune(r) + default: + return nil, v + } + } + return nil, v +} + +func consumeParam(v []byte) (param, value, rest []byte) { + param, rest = consumeToken(v) + param = bytes.ToLower(param) + if param == nil { + return nil, nil, v + } + + rest = bytes.TrimLeftFunc(rest, unicode.IsSpace) + if len(rest) == 0 || rest[0] != '=' { + return nil, nil, v + } + rest = rest[1:] // consume equals sign + rest = bytes.TrimLeftFunc(rest, unicode.IsSpace) + if len(rest) == 0 { + return nil, nil, v + } + if rest[0] != '"' { + value, rest = consumeToken(rest) + } else { + value, rest = consumeValue(rest) + } + if value == nil { + return nil, nil, v + } + return param, value, rest +} diff --git a/vendor/github.com/ugorji/go/LICENSE b/vendor/github.com/ugorji/go/LICENSE new file mode 100644 index 000000000..95a0f0541 --- /dev/null +++ b/vendor/github.com/ugorji/go/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2012-2015 Ugorji Nwoke. +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/ugorji/go/codec/0doc.go b/vendor/github.com/ugorji/go/codec/0doc.go new file mode 100644 index 000000000..bd7361c87 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/0doc.go @@ -0,0 +1,199 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +/* +High Performance, Feature-Rich Idiomatic Go codec/encoding library for +binc, msgpack, cbor, json. + +Supported Serialization formats are: + + - msgpack: https://github.com/msgpack/msgpack + - binc: http://github.com/ugorji/binc + - cbor: http://cbor.io http://tools.ietf.org/html/rfc7049 + - json: http://json.org http://tools.ietf.org/html/rfc7159 + - simple: + +To install: + + go get github.com/ugorji/go/codec + +This package understands the 'unsafe' tag, to allow using unsafe semantics: + + - When decoding into a struct, you need to read the field name as a string + so you can find the struct field it is mapped to. + Using `unsafe` will bypass the allocation and copying overhead of []byte->string conversion. + +To install using unsafe, pass the 'unsafe' tag: + + go get -tags=unsafe github.com/ugorji/go/codec + +For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer . + +The idiomatic Go support is as seen in other encoding packages in +the standard library (ie json, xml, gob, etc). + +Rich Feature Set includes: + + - Simple but extremely powerful and feature-rich API + - Very High Performance. + Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X. + - Multiple conversions: + Package coerces types where appropriate + e.g. decode an int in the stream into a float, etc. + - Corner Cases: + Overflows, nil maps/slices, nil values in streams are handled correctly + - Standard field renaming via tags + - Support for omitting empty fields during an encoding + - Encoding from any value and decoding into pointer to any value + (struct, slice, map, primitives, pointers, interface{}, etc) + - Extensions to support efficient encoding/decoding of any named types + - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces + - Decoding without a schema (into a interface{}). + Includes Options to configure what specific map or slice type to use + when decoding an encoded list or map into a nil interface{} + - Encode a struct as an array, and decode struct from an array in the data stream + - Comprehensive support for anonymous fields + - Fast (no-reflection) encoding/decoding of common maps and slices + - Code-generation for faster performance. + - Support binary (e.g. messagepack, cbor) and text (e.g. json) formats + - Support indefinite-length formats to enable true streaming + (for formats which support it e.g. json, cbor) + - Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes. + This mostly applies to maps, where iteration order is non-deterministic. + - NIL in data stream decoded as zero value + - Never silently skip data when decoding. + User decides whether to return an error or silently skip data when keys or indexes + in the data stream do not map to fields in the struct. + - Detect and error when encoding a cyclic reference (instead of stack overflow shutdown) + - Encode/Decode from/to chan types (for iterative streaming support) + - Drop-in replacement for encoding/json. `json:` key in struct tag supported. + - Provides a RPC Server and Client Codec for net/rpc communication protocol. + - Handle unique idiosynchracies of codecs e.g. + - For messagepack, configure how ambiguities in handling raw bytes are resolved + - For messagepack, provide rpc server/client codec to support + msgpack-rpc protocol defined at: + https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md + +Extension Support + +Users can register a function to handle the encoding or decoding of +their custom types. + +There are no restrictions on what the custom type can be. Some examples: + + type BisSet []int + type BitSet64 uint64 + type UUID string + type MyStructWithUnexportedFields struct { a int; b bool; c []int; } + type GifImage struct { ... } + +As an illustration, MyStructWithUnexportedFields would normally be +encoded as an empty map because it has no exported fields, while UUID +would be encoded as a string. However, with extension support, you can +encode any of these however you like. + +RPC + +RPC Client and Server Codecs are implemented, so the codecs can be used +with the standard net/rpc package. + +Usage + +The Handle is SAFE for concurrent READ, but NOT SAFE for concurrent modification. + +The Encoder and Decoder are NOT safe for concurrent use. + +Consequently, the usage model is basically: + + - Create and initialize the Handle before any use. + Once created, DO NOT modify it. + - Multiple Encoders or Decoders can now use the Handle concurrently. + They only read information off the Handle (never write). + - However, each Encoder or Decoder MUST not be used concurrently + - To re-use an Encoder/Decoder, call Reset(...) on it first. + This allows you use state maintained on the Encoder/Decoder. + +Sample usage model: + + // create and configure Handle + var ( + bh codec.BincHandle + mh codec.MsgpackHandle + ch codec.CborHandle + ) + + mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) + + // configure extensions + // e.g. for msgpack, define functions and enable Time support for tag 1 + // mh.SetExt(reflect.TypeOf(time.Time{}), 1, myExt) + + // create and use decoder/encoder + var ( + r io.Reader + w io.Writer + b []byte + h = &bh // or mh to use msgpack + ) + + dec = codec.NewDecoder(r, h) + dec = codec.NewDecoderBytes(b, h) + err = dec.Decode(&v) + + enc = codec.NewEncoder(w, h) + enc = codec.NewEncoderBytes(&b, h) + err = enc.Encode(v) + + //RPC Server + go func() { + for { + conn, err := listener.Accept() + rpcCodec := codec.GoRpc.ServerCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) + rpc.ServeCodec(rpcCodec) + } + }() + + //RPC Communication (client side) + conn, err = net.Dial("tcp", "localhost:5555") + rpcCodec := codec.GoRpc.ClientCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) + client := rpc.NewClientWithCodec(rpcCodec) + +*/ +package codec + +// Benefits of go-codec: +// +// - encoding/json always reads whole file into memory first. +// This makes it unsuitable for parsing very large files. +// - encoding/xml cannot parse into a map[string]interface{} +// I found this out on reading https://github.com/clbanning/mxj + +// TODO: +// +// - optimization for codecgen: +// if len of entity is <= 3 words, then support a value receiver for encode. +// - (En|De)coder should store an error when it occurs. +// Until reset, subsequent calls return that error that was stored. +// This means that free panics must go away. +// All errors must be raised through errorf method. +// - Decoding using a chan is good, but incurs concurrency costs. +// This is because there's no fast way to use a channel without it +// having to switch goroutines constantly. +// Callback pattern is still the best. Maybe cnsider supporting something like: +// type X struct { +// Name string +// Ys []Y +// Ys chan <- Y +// Ys func(Y) -> call this function for each entry +// } +// - Consider adding a isZeroer interface { isZero() bool } +// It is used within isEmpty, for omitEmpty support. +// - Consider making Handle used AS-IS within the encoding/decoding session. +// This means that we don't cache Handle information within the (En|De)coder, +// except we really need it at Reset(...) +// - Consider adding math/big support +// - Consider reducing the size of the generated functions: +// Maybe use one loop, and put the conditionals in the loop. +// for ... { if cLen > 0 { if j == cLen { break } } else if dd.CheckBreak() { break } } diff --git a/vendor/github.com/ugorji/go/codec/README.md b/vendor/github.com/ugorji/go/codec/README.md new file mode 100644 index 000000000..a790a52bb --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/README.md @@ -0,0 +1,148 @@ +# Codec + +High Performance, Feature-Rich Idiomatic Go codec/encoding library for +binc, msgpack, cbor, json. + +Supported Serialization formats are: + + - msgpack: https://github.com/msgpack/msgpack + - binc: http://github.com/ugorji/binc + - cbor: http://cbor.io http://tools.ietf.org/html/rfc7049 + - json: http://json.org http://tools.ietf.org/html/rfc7159 + - simple: + +To install: + + go get github.com/ugorji/go/codec + +This package understands the `unsafe` tag, to allow using unsafe semantics: + + - When decoding into a struct, you need to read the field name as a string + so you can find the struct field it is mapped to. + Using `unsafe` will bypass the allocation and copying overhead of `[]byte->string` conversion. + +To use it, you must pass the `unsafe` tag during install: + +``` +go install -tags=unsafe github.com/ugorji/go/codec +``` + +Online documentation: http://godoc.org/github.com/ugorji/go/codec +Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer + +The idiomatic Go support is as seen in other encoding packages in +the standard library (ie json, xml, gob, etc). + +Rich Feature Set includes: + + - Simple but extremely powerful and feature-rich API + - Very High Performance. + Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X. + - Multiple conversions: + Package coerces types where appropriate + e.g. decode an int in the stream into a float, etc. + - Corner Cases: + Overflows, nil maps/slices, nil values in streams are handled correctly + - Standard field renaming via tags + - Support for omitting empty fields during an encoding + - Encoding from any value and decoding into pointer to any value + (struct, slice, map, primitives, pointers, interface{}, etc) + - Extensions to support efficient encoding/decoding of any named types + - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces + - Decoding without a schema (into a interface{}). + Includes Options to configure what specific map or slice type to use + when decoding an encoded list or map into a nil interface{} + - Encode a struct as an array, and decode struct from an array in the data stream + - Comprehensive support for anonymous fields + - Fast (no-reflection) encoding/decoding of common maps and slices + - Code-generation for faster performance. + - Support binary (e.g. messagepack, cbor) and text (e.g. json) formats + - Support indefinite-length formats to enable true streaming + (for formats which support it e.g. json, cbor) + - Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes. + This mostly applies to maps, where iteration order is non-deterministic. + - NIL in data stream decoded as zero value + - Never silently skip data when decoding. + User decides whether to return an error or silently skip data when keys or indexes + in the data stream do not map to fields in the struct. + - Encode/Decode from/to chan types (for iterative streaming support) + - Drop-in replacement for encoding/json. `json:` key in struct tag supported. + - Provides a RPC Server and Client Codec for net/rpc communication protocol. + - Handle unique idiosynchracies of codecs e.g. + - For messagepack, configure how ambiguities in handling raw bytes are resolved + - For messagepack, provide rpc server/client codec to support + msgpack-rpc protocol defined at: + https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md + +## Extension Support + +Users can register a function to handle the encoding or decoding of +their custom types. + +There are no restrictions on what the custom type can be. Some examples: + + type BisSet []int + type BitSet64 uint64 + type UUID string + type MyStructWithUnexportedFields struct { a int; b bool; c []int; } + type GifImage struct { ... } + +As an illustration, MyStructWithUnexportedFields would normally be +encoded as an empty map because it has no exported fields, while UUID +would be encoded as a string. However, with extension support, you can +encode any of these however you like. + +## RPC + +RPC Client and Server Codecs are implemented, so the codecs can be used +with the standard net/rpc package. + +## Usage + +Typical usage model: + + // create and configure Handle + var ( + bh codec.BincHandle + mh codec.MsgpackHandle + ch codec.CborHandle + ) + + mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) + + // configure extensions + // e.g. for msgpack, define functions and enable Time support for tag 1 + // mh.SetExt(reflect.TypeOf(time.Time{}), 1, myExt) + + // create and use decoder/encoder + var ( + r io.Reader + w io.Writer + b []byte + h = &bh // or mh to use msgpack + ) + + dec = codec.NewDecoder(r, h) + dec = codec.NewDecoderBytes(b, h) + err = dec.Decode(&v) + + enc = codec.NewEncoder(w, h) + enc = codec.NewEncoderBytes(&b, h) + err = enc.Encode(v) + + //RPC Server + go func() { + for { + conn, err := listener.Accept() + rpcCodec := codec.GoRpc.ServerCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) + rpc.ServeCodec(rpcCodec) + } + }() + + //RPC Communication (client side) + conn, err = net.Dial("tcp", "localhost:5555") + rpcCodec := codec.GoRpc.ClientCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) + client := rpc.NewClientWithCodec(rpcCodec) + diff --git a/vendor/github.com/ugorji/go/codec/binc.go b/vendor/github.com/ugorji/go/codec/binc.go new file mode 100644 index 000000000..766d26cf6 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/binc.go @@ -0,0 +1,922 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "math" + "reflect" + "time" +) + +const bincDoPrune = true // No longer needed. Needed before as C lib did not support pruning. + +// vd as low 4 bits (there are 16 slots) +const ( + bincVdSpecial byte = iota + bincVdPosInt + bincVdNegInt + bincVdFloat + + bincVdString + bincVdByteArray + bincVdArray + bincVdMap + + bincVdTimestamp + bincVdSmallInt + bincVdUnicodeOther + bincVdSymbol + + bincVdDecimal + _ // open slot + _ // open slot + bincVdCustomExt = 0x0f +) + +const ( + bincSpNil byte = iota + bincSpFalse + bincSpTrue + bincSpNan + bincSpPosInf + bincSpNegInf + bincSpZeroFloat + bincSpZero + bincSpNegOne +) + +const ( + bincFlBin16 byte = iota + bincFlBin32 + _ // bincFlBin32e + bincFlBin64 + _ // bincFlBin64e + // others not currently supported +) + +type bincEncDriver struct { + e *Encoder + w encWriter + m map[string]uint16 // symbols + b [scratchByteArrayLen]byte + s uint16 // symbols sequencer + encNoSeparator +} + +func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool { + return rt == timeTypId +} + +func (e *bincEncDriver) EncodeBuiltin(rt uintptr, v interface{}) { + if rt == timeTypId { + var bs []byte + switch x := v.(type) { + case time.Time: + bs = encodeTime(x) + case *time.Time: + bs = encodeTime(*x) + default: + e.e.errorf("binc error encoding builtin: expect time.Time, received %T", v) + } + e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs))) + e.w.writeb(bs) + } +} + +func (e *bincEncDriver) EncodeNil() { + e.w.writen1(bincVdSpecial<<4 | bincSpNil) +} + +func (e *bincEncDriver) EncodeBool(b bool) { + if b { + e.w.writen1(bincVdSpecial<<4 | bincSpTrue) + } else { + e.w.writen1(bincVdSpecial<<4 | bincSpFalse) + } +} + +func (e *bincEncDriver) EncodeFloat32(f float32) { + if f == 0 { + e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat) + return + } + e.w.writen1(bincVdFloat<<4 | bincFlBin32) + bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f)) +} + +func (e *bincEncDriver) EncodeFloat64(f float64) { + if f == 0 { + e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat) + return + } + bigen.PutUint64(e.b[:8], math.Float64bits(f)) + if bincDoPrune { + i := 7 + for ; i >= 0 && (e.b[i] == 0); i-- { + } + i++ + if i <= 6 { + e.w.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64) + e.w.writen1(byte(i)) + e.w.writeb(e.b[:i]) + return + } + } + e.w.writen1(bincVdFloat<<4 | bincFlBin64) + e.w.writeb(e.b[:8]) +} + +func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) { + if lim == 4 { + bigen.PutUint32(e.b[:lim], uint32(v)) + } else { + bigen.PutUint64(e.b[:lim], v) + } + if bincDoPrune { + i := pruneSignExt(e.b[:lim], pos) + e.w.writen1(bd | lim - 1 - byte(i)) + e.w.writeb(e.b[i:lim]) + } else { + e.w.writen1(bd | lim - 1) + e.w.writeb(e.b[:lim]) + } +} + +func (e *bincEncDriver) EncodeInt(v int64) { + const nbd byte = bincVdNegInt << 4 + if v >= 0 { + e.encUint(bincVdPosInt<<4, true, uint64(v)) + } else if v == -1 { + e.w.writen1(bincVdSpecial<<4 | bincSpNegOne) + } else { + e.encUint(bincVdNegInt<<4, false, uint64(-v)) + } +} + +func (e *bincEncDriver) EncodeUint(v uint64) { + e.encUint(bincVdPosInt<<4, true, v) +} + +func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) { + if v == 0 { + e.w.writen1(bincVdSpecial<<4 | bincSpZero) + } else if pos && v >= 1 && v <= 16 { + e.w.writen1(bincVdSmallInt<<4 | byte(v-1)) + } else if v <= math.MaxUint8 { + e.w.writen2(bd|0x0, byte(v)) + } else if v <= math.MaxUint16 { + e.w.writen1(bd | 0x01) + bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v)) + } else if v <= math.MaxUint32 { + e.encIntegerPrune(bd, pos, v, 4) + } else { + e.encIntegerPrune(bd, pos, v, 8) + } +} + +func (e *bincEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, _ *Encoder) { + bs := ext.WriteExt(rv) + if bs == nil { + e.EncodeNil() + return + } + e.encodeExtPreamble(uint8(xtag), len(bs)) + e.w.writeb(bs) +} + +func (e *bincEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) { + e.encodeExtPreamble(uint8(re.Tag), len(re.Data)) + e.w.writeb(re.Data) +} + +func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) { + e.encLen(bincVdCustomExt<<4, uint64(length)) + e.w.writen1(xtag) +} + +func (e *bincEncDriver) EncodeArrayStart(length int) { + e.encLen(bincVdArray<<4, uint64(length)) +} + +func (e *bincEncDriver) EncodeMapStart(length int) { + e.encLen(bincVdMap<<4, uint64(length)) +} + +func (e *bincEncDriver) EncodeString(c charEncoding, v string) { + l := uint64(len(v)) + e.encBytesLen(c, l) + if l > 0 { + e.w.writestr(v) + } +} + +func (e *bincEncDriver) EncodeSymbol(v string) { + // if WriteSymbolsNoRefs { + // e.encodeString(c_UTF8, v) + // return + // } + + //symbols only offer benefit when string length > 1. + //This is because strings with length 1 take only 2 bytes to store + //(bd with embedded length, and single byte for string val). + + l := len(v) + if l == 0 { + e.encBytesLen(c_UTF8, 0) + return + } else if l == 1 { + e.encBytesLen(c_UTF8, 1) + e.w.writen1(v[0]) + return + } + if e.m == nil { + e.m = make(map[string]uint16, 16) + } + ui, ok := e.m[v] + if ok { + if ui <= math.MaxUint8 { + e.w.writen2(bincVdSymbol<<4, byte(ui)) + } else { + e.w.writen1(bincVdSymbol<<4 | 0x8) + bigenHelper{e.b[:2], e.w}.writeUint16(ui) + } + } else { + e.s++ + ui = e.s + //ui = uint16(atomic.AddUint32(&e.s, 1)) + e.m[v] = ui + var lenprec uint8 + if l <= math.MaxUint8 { + // lenprec = 0 + } else if l <= math.MaxUint16 { + lenprec = 1 + } else if int64(l) <= math.MaxUint32 { + lenprec = 2 + } else { + lenprec = 3 + } + if ui <= math.MaxUint8 { + e.w.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui)) + } else { + e.w.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec) + bigenHelper{e.b[:2], e.w}.writeUint16(ui) + } + if lenprec == 0 { + e.w.writen1(byte(l)) + } else if lenprec == 1 { + bigenHelper{e.b[:2], e.w}.writeUint16(uint16(l)) + } else if lenprec == 2 { + bigenHelper{e.b[:4], e.w}.writeUint32(uint32(l)) + } else { + bigenHelper{e.b[:8], e.w}.writeUint64(uint64(l)) + } + e.w.writestr(v) + } +} + +func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) { + l := uint64(len(v)) + e.encBytesLen(c, l) + if l > 0 { + e.w.writeb(v) + } +} + +func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) { + //TODO: support bincUnicodeOther (for now, just use string or bytearray) + if c == c_RAW { + e.encLen(bincVdByteArray<<4, length) + } else { + e.encLen(bincVdString<<4, length) + } +} + +func (e *bincEncDriver) encLen(bd byte, l uint64) { + if l < 12 { + e.w.writen1(bd | uint8(l+4)) + } else { + e.encLenNumber(bd, l) + } +} + +func (e *bincEncDriver) encLenNumber(bd byte, v uint64) { + if v <= math.MaxUint8 { + e.w.writen2(bd, byte(v)) + } else if v <= math.MaxUint16 { + e.w.writen1(bd | 0x01) + bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v)) + } else if v <= math.MaxUint32 { + e.w.writen1(bd | 0x02) + bigenHelper{e.b[:4], e.w}.writeUint32(uint32(v)) + } else { + e.w.writen1(bd | 0x03) + bigenHelper{e.b[:8], e.w}.writeUint64(uint64(v)) + } +} + +//------------------------------------ + +type bincDecSymbol struct { + s string + b []byte + i uint16 +} + +type bincDecDriver struct { + d *Decoder + h *BincHandle + r decReader + br bool // bytes reader + bdRead bool + bd byte + vd byte + vs byte + noStreamingCodec + decNoSeparator + b [scratchByteArrayLen]byte + + // linear searching on this slice is ok, + // because we typically expect < 32 symbols in each stream. + s []bincDecSymbol +} + +func (d *bincDecDriver) readNextBd() { + d.bd = d.r.readn1() + d.vd = d.bd >> 4 + d.vs = d.bd & 0x0f + d.bdRead = true +} + +func (d *bincDecDriver) ContainerType() (vt valueType) { + if d.vd == bincVdSpecial && d.vs == bincSpNil { + return valueTypeNil + } else if d.vd == bincVdByteArray { + return valueTypeBytes + } else if d.vd == bincVdString { + return valueTypeString + } else if d.vd == bincVdArray { + return valueTypeArray + } else if d.vd == bincVdMap { + return valueTypeMap + } else { + // d.d.errorf("isContainerType: unsupported parameter: %v", vt) + } + return valueTypeUnset +} + +func (d *bincDecDriver) TryDecodeAsNil() bool { + if !d.bdRead { + d.readNextBd() + } + if d.bd == bincVdSpecial<<4|bincSpNil { + d.bdRead = false + return true + } + return false +} + +func (d *bincDecDriver) IsBuiltinType(rt uintptr) bool { + return rt == timeTypId +} + +func (d *bincDecDriver) DecodeBuiltin(rt uintptr, v interface{}) { + if !d.bdRead { + d.readNextBd() + } + if rt == timeTypId { + if d.vd != bincVdTimestamp { + d.d.errorf("Invalid d.vd. Expecting 0x%x. Received: 0x%x", bincVdTimestamp, d.vd) + return + } + tt, err := decodeTime(d.r.readx(int(d.vs))) + if err != nil { + panic(err) + } + var vt *time.Time = v.(*time.Time) + *vt = tt + d.bdRead = false + } +} + +func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) { + if vs&0x8 == 0 { + d.r.readb(d.b[0:defaultLen]) + } else { + l := d.r.readn1() + if l > 8 { + d.d.errorf("At most 8 bytes used to represent float. Received: %v bytes", l) + return + } + for i := l; i < 8; i++ { + d.b[i] = 0 + } + d.r.readb(d.b[0:l]) + } +} + +func (d *bincDecDriver) decFloat() (f float64) { + //if true { f = math.Float64frombits(bigen.Uint64(d.r.readx(8))); break; } + if x := d.vs & 0x7; x == bincFlBin32 { + d.decFloatPre(d.vs, 4) + f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4]))) + } else if x == bincFlBin64 { + d.decFloatPre(d.vs, 8) + f = math.Float64frombits(bigen.Uint64(d.b[0:8])) + } else { + d.d.errorf("only float32 and float64 are supported. d.vd: 0x%x, d.vs: 0x%x", d.vd, d.vs) + return + } + return +} + +func (d *bincDecDriver) decUint() (v uint64) { + // need to inline the code (interface conversion and type assertion expensive) + switch d.vs { + case 0: + v = uint64(d.r.readn1()) + case 1: + d.r.readb(d.b[6:8]) + v = uint64(bigen.Uint16(d.b[6:8])) + case 2: + d.b[4] = 0 + d.r.readb(d.b[5:8]) + v = uint64(bigen.Uint32(d.b[4:8])) + case 3: + d.r.readb(d.b[4:8]) + v = uint64(bigen.Uint32(d.b[4:8])) + case 4, 5, 6: + lim := int(7 - d.vs) + d.r.readb(d.b[lim:8]) + for i := 0; i < lim; i++ { + d.b[i] = 0 + } + v = uint64(bigen.Uint64(d.b[:8])) + case 7: + d.r.readb(d.b[:8]) + v = uint64(bigen.Uint64(d.b[:8])) + default: + d.d.errorf("unsigned integers with greater than 64 bits of precision not supported") + return + } + return +} + +func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) { + if !d.bdRead { + d.readNextBd() + } + vd, vs := d.vd, d.vs + if vd == bincVdPosInt { + ui = d.decUint() + } else if vd == bincVdNegInt { + ui = d.decUint() + neg = true + } else if vd == bincVdSmallInt { + ui = uint64(d.vs) + 1 + } else if vd == bincVdSpecial { + if vs == bincSpZero { + //i = 0 + } else if vs == bincSpNegOne { + neg = true + ui = 1 + } else { + d.d.errorf("numeric decode fails for special value: d.vs: 0x%x", d.vs) + return + } + } else { + d.d.errorf("number can only be decoded from uint or int values. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd) + return + } + return +} + +func (d *bincDecDriver) DecodeInt(bitsize uint8) (i int64) { + ui, neg := d.decCheckInteger() + i, overflow := chkOvf.SignedInt(ui) + if overflow { + d.d.errorf("simple: overflow converting %v to signed integer", ui) + return + } + if neg { + i = -i + } + if chkOvf.Int(i, bitsize) { + d.d.errorf("binc: overflow integer: %v", i) + return + } + d.bdRead = false + return +} + +func (d *bincDecDriver) DecodeUint(bitsize uint8) (ui uint64) { + ui, neg := d.decCheckInteger() + if neg { + d.d.errorf("Assigning negative signed value to unsigned type") + return + } + if chkOvf.Uint(ui, bitsize) { + d.d.errorf("binc: overflow integer: %v", ui) + return + } + d.bdRead = false + return +} + +func (d *bincDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) { + if !d.bdRead { + d.readNextBd() + } + vd, vs := d.vd, d.vs + if vd == bincVdSpecial { + d.bdRead = false + if vs == bincSpNan { + return math.NaN() + } else if vs == bincSpPosInf { + return math.Inf(1) + } else if vs == bincSpZeroFloat || vs == bincSpZero { + return + } else if vs == bincSpNegInf { + return math.Inf(-1) + } else { + d.d.errorf("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs) + return + } + } else if vd == bincVdFloat { + f = d.decFloat() + } else { + f = float64(d.DecodeInt(64)) + } + if chkOverflow32 && chkOvf.Float32(f) { + d.d.errorf("binc: float32 overflow: %v", f) + return + } + d.bdRead = false + return +} + +// bool can be decoded from bool only (single byte). +func (d *bincDecDriver) DecodeBool() (b bool) { + if !d.bdRead { + d.readNextBd() + } + if bd := d.bd; bd == (bincVdSpecial | bincSpFalse) { + // b = false + } else if bd == (bincVdSpecial | bincSpTrue) { + b = true + } else { + d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + return + } + d.bdRead = false + return +} + +func (d *bincDecDriver) ReadMapStart() (length int) { + if d.vd != bincVdMap { + d.d.errorf("Invalid d.vd for map. Expecting 0x%x. Got: 0x%x", bincVdMap, d.vd) + return + } + length = d.decLen() + d.bdRead = false + return +} + +func (d *bincDecDriver) ReadArrayStart() (length int) { + if d.vd != bincVdArray { + d.d.errorf("Invalid d.vd for array. Expecting 0x%x. Got: 0x%x", bincVdArray, d.vd) + return + } + length = d.decLen() + d.bdRead = false + return +} + +func (d *bincDecDriver) decLen() int { + if d.vs > 3 { + return int(d.vs - 4) + } + return int(d.decLenNumber()) +} + +func (d *bincDecDriver) decLenNumber() (v uint64) { + if x := d.vs; x == 0 { + v = uint64(d.r.readn1()) + } else if x == 1 { + d.r.readb(d.b[6:8]) + v = uint64(bigen.Uint16(d.b[6:8])) + } else if x == 2 { + d.r.readb(d.b[4:8]) + v = uint64(bigen.Uint32(d.b[4:8])) + } else { + d.r.readb(d.b[:8]) + v = bigen.Uint64(d.b[:8]) + } + return +} + +func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (bs2 []byte, s string) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == bincVdSpecial<<4|bincSpNil { + d.bdRead = false + return + } + var slen int = -1 + // var ok bool + switch d.vd { + case bincVdString, bincVdByteArray: + slen = d.decLen() + if zerocopy { + if d.br { + bs2 = d.r.readx(slen) + } else if len(bs) == 0 { + bs2 = decByteSlice(d.r, slen, d.b[:]) + } else { + bs2 = decByteSlice(d.r, slen, bs) + } + } else { + bs2 = decByteSlice(d.r, slen, bs) + } + if withString { + s = string(bs2) + } + case bincVdSymbol: + // zerocopy doesn't apply for symbols, + // as the values must be stored in a table for later use. + // + //from vs: extract numSymbolBytes, containsStringVal, strLenPrecision, + //extract symbol + //if containsStringVal, read it and put in map + //else look in map for string value + var symbol uint16 + vs := d.vs + if vs&0x8 == 0 { + symbol = uint16(d.r.readn1()) + } else { + symbol = uint16(bigen.Uint16(d.r.readx(2))) + } + if d.s == nil { + d.s = make([]bincDecSymbol, 0, 16) + } + + if vs&0x4 == 0 { + for i := range d.s { + j := &d.s[i] + if j.i == symbol { + bs2 = j.b + if withString { + if j.s == "" && bs2 != nil { + j.s = string(bs2) + } + s = j.s + } + break + } + } + } else { + switch vs & 0x3 { + case 0: + slen = int(d.r.readn1()) + case 1: + slen = int(bigen.Uint16(d.r.readx(2))) + case 2: + slen = int(bigen.Uint32(d.r.readx(4))) + case 3: + slen = int(bigen.Uint64(d.r.readx(8))) + } + // since using symbols, do not store any part of + // the parameter bs in the map, as it might be a shared buffer. + // bs2 = decByteSlice(d.r, slen, bs) + bs2 = decByteSlice(d.r, slen, nil) + if withString { + s = string(bs2) + } + d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2}) + } + default: + d.d.errorf("Invalid d.vd. Expecting string:0x%x, bytearray:0x%x or symbol: 0x%x. Got: 0x%x", + bincVdString, bincVdByteArray, bincVdSymbol, d.vd) + return + } + d.bdRead = false + return +} + +func (d *bincDecDriver) DecodeString() (s string) { + // DecodeBytes does not accomodate symbols, whose impl stores string version in map. + // Use decStringAndBytes directly. + // return string(d.DecodeBytes(d.b[:], true, true)) + _, s = d.decStringAndBytes(d.b[:], true, true) + return +} + +func (d *bincDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) { + if isstring { + bsOut, _ = d.decStringAndBytes(bs, false, zerocopy) + return + } + if !d.bdRead { + d.readNextBd() + } + if d.bd == bincVdSpecial<<4|bincSpNil { + d.bdRead = false + return nil + } + var clen int + if d.vd == bincVdString || d.vd == bincVdByteArray { + clen = d.decLen() + } else { + d.d.errorf("Invalid d.vd for bytes. Expecting string:0x%x or bytearray:0x%x. Got: 0x%x", + bincVdString, bincVdByteArray, d.vd) + return + } + d.bdRead = false + if zerocopy { + if d.br { + return d.r.readx(clen) + } else if len(bs) == 0 { + bs = d.b[:] + } + } + return decByteSlice(d.r, clen, bs) +} + +func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { + if xtag > 0xff { + d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag) + return + } + realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag)) + realxtag = uint64(realxtag1) + if ext == nil { + re := rv.(*RawExt) + re.Tag = realxtag + re.Data = detachZeroCopyBytes(d.br, re.Data, xbs) + } else { + ext.ReadExt(rv, xbs) + } + return +} + +func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + if !d.bdRead { + d.readNextBd() + } + if d.vd == bincVdCustomExt { + l := d.decLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + return + } + xbs = d.r.readx(l) + } else if d.vd == bincVdByteArray { + xbs = d.DecodeBytes(nil, false, true) + } else { + d.d.errorf("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.vd) + return + } + d.bdRead = false + return +} + +func (d *bincDecDriver) DecodeNaked() { + if !d.bdRead { + d.readNextBd() + } + + n := &d.d.n + var decodeFurther bool + + switch d.vd { + case bincVdSpecial: + switch d.vs { + case bincSpNil: + n.v = valueTypeNil + case bincSpFalse: + n.v = valueTypeBool + n.b = false + case bincSpTrue: + n.v = valueTypeBool + n.b = true + case bincSpNan: + n.v = valueTypeFloat + n.f = math.NaN() + case bincSpPosInf: + n.v = valueTypeFloat + n.f = math.Inf(1) + case bincSpNegInf: + n.v = valueTypeFloat + n.f = math.Inf(-1) + case bincSpZeroFloat: + n.v = valueTypeFloat + n.f = float64(0) + case bincSpZero: + n.v = valueTypeUint + n.u = uint64(0) // int8(0) + case bincSpNegOne: + n.v = valueTypeInt + n.i = int64(-1) // int8(-1) + default: + d.d.errorf("decodeNaked: Unrecognized special value 0x%x", d.vs) + } + case bincVdSmallInt: + n.v = valueTypeUint + n.u = uint64(int8(d.vs)) + 1 // int8(d.vs) + 1 + case bincVdPosInt: + n.v = valueTypeUint + n.u = d.decUint() + case bincVdNegInt: + n.v = valueTypeInt + n.i = -(int64(d.decUint())) + case bincVdFloat: + n.v = valueTypeFloat + n.f = d.decFloat() + case bincVdSymbol: + n.v = valueTypeSymbol + n.s = d.DecodeString() + case bincVdString: + n.v = valueTypeString + n.s = d.DecodeString() + case bincVdByteArray: + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + case bincVdTimestamp: + n.v = valueTypeTimestamp + tt, err := decodeTime(d.r.readx(int(d.vs))) + if err != nil { + panic(err) + } + n.t = tt + case bincVdCustomExt: + n.v = valueTypeExt + l := d.decLen() + n.u = uint64(d.r.readn1()) + n.l = d.r.readx(l) + case bincVdArray: + n.v = valueTypeArray + decodeFurther = true + case bincVdMap: + n.v = valueTypeMap + decodeFurther = true + default: + d.d.errorf("decodeNaked: Unrecognized d.vd: 0x%x", d.vd) + } + + if !decodeFurther { + d.bdRead = false + } + if n.v == valueTypeUint && d.h.SignedInteger { + n.v = valueTypeInt + n.i = int64(n.u) + } + return +} + +//------------------------------------ + +//BincHandle is a Handle for the Binc Schema-Free Encoding Format +//defined at https://github.com/ugorji/binc . +// +//BincHandle currently supports all Binc features with the following EXCEPTIONS: +// - only integers up to 64 bits of precision are supported. +// big integers are unsupported. +// - Only IEEE 754 binary32 and binary64 floats are supported (ie Go float32 and float64 types). +// extended precision and decimal IEEE 754 floats are unsupported. +// - Only UTF-8 strings supported. +// Unicode_Other Binc types (UTF16, UTF32) are currently unsupported. +// +//Note that these EXCEPTIONS are temporary and full support is possible and may happen soon. +type BincHandle struct { + BasicHandle + binaryEncodingType +} + +func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) { + return h.SetExt(rt, tag, &setExtWrapper{b: ext}) +} + +func (h *BincHandle) newEncDriver(e *Encoder) encDriver { + return &bincEncDriver{e: e, w: e.w} +} + +func (h *BincHandle) newDecDriver(d *Decoder) decDriver { + return &bincDecDriver{d: d, r: d.r, h: h, br: d.bytes} +} + +func (e *bincEncDriver) reset() { + e.w = e.e.w + e.s = 0 + e.m = nil +} + +func (d *bincDecDriver) reset() { + d.r = d.d.r + d.s = nil + d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0 +} + +var _ decDriver = (*bincDecDriver)(nil) +var _ encDriver = (*bincEncDriver)(nil) diff --git a/vendor/github.com/ugorji/go/codec/cbor.go b/vendor/github.com/ugorji/go/codec/cbor.go new file mode 100644 index 000000000..a224cd3a7 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/cbor.go @@ -0,0 +1,585 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "math" + "reflect" +) + +const ( + cborMajorUint byte = iota + cborMajorNegInt + cborMajorBytes + cborMajorText + cborMajorArray + cborMajorMap + cborMajorTag + cborMajorOther +) + +const ( + cborBdFalse byte = 0xf4 + iota + cborBdTrue + cborBdNil + cborBdUndefined + cborBdExt + cborBdFloat16 + cborBdFloat32 + cborBdFloat64 +) + +const ( + cborBdIndefiniteBytes byte = 0x5f + cborBdIndefiniteString = 0x7f + cborBdIndefiniteArray = 0x9f + cborBdIndefiniteMap = 0xbf + cborBdBreak = 0xff +) + +const ( + CborStreamBytes byte = 0x5f + CborStreamString = 0x7f + CborStreamArray = 0x9f + CborStreamMap = 0xbf + CborStreamBreak = 0xff +) + +const ( + cborBaseUint byte = 0x00 + cborBaseNegInt = 0x20 + cborBaseBytes = 0x40 + cborBaseString = 0x60 + cborBaseArray = 0x80 + cborBaseMap = 0xa0 + cborBaseTag = 0xc0 + cborBaseSimple = 0xe0 +) + +// ------------------- + +type cborEncDriver struct { + noBuiltInTypes + encNoSeparator + e *Encoder + w encWriter + h *CborHandle + x [8]byte +} + +func (e *cborEncDriver) EncodeNil() { + e.w.writen1(cborBdNil) +} + +func (e *cborEncDriver) EncodeBool(b bool) { + if b { + e.w.writen1(cborBdTrue) + } else { + e.w.writen1(cborBdFalse) + } +} + +func (e *cborEncDriver) EncodeFloat32(f float32) { + e.w.writen1(cborBdFloat32) + bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f)) +} + +func (e *cborEncDriver) EncodeFloat64(f float64) { + e.w.writen1(cborBdFloat64) + bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f)) +} + +func (e *cborEncDriver) encUint(v uint64, bd byte) { + if v <= 0x17 { + e.w.writen1(byte(v) + bd) + } else if v <= math.MaxUint8 { + e.w.writen2(bd+0x18, uint8(v)) + } else if v <= math.MaxUint16 { + e.w.writen1(bd + 0x19) + bigenHelper{e.x[:2], e.w}.writeUint16(uint16(v)) + } else if v <= math.MaxUint32 { + e.w.writen1(bd + 0x1a) + bigenHelper{e.x[:4], e.w}.writeUint32(uint32(v)) + } else { // if v <= math.MaxUint64 { + e.w.writen1(bd + 0x1b) + bigenHelper{e.x[:8], e.w}.writeUint64(v) + } +} + +func (e *cborEncDriver) EncodeInt(v int64) { + if v < 0 { + e.encUint(uint64(-1-v), cborBaseNegInt) + } else { + e.encUint(uint64(v), cborBaseUint) + } +} + +func (e *cborEncDriver) EncodeUint(v uint64) { + e.encUint(v, cborBaseUint) +} + +func (e *cborEncDriver) encLen(bd byte, length int) { + e.encUint(uint64(length), bd) +} + +func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) { + e.encUint(uint64(xtag), cborBaseTag) + if v := ext.ConvertExt(rv); v == nil { + e.EncodeNil() + } else { + en.encode(v) + } +} + +func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) { + e.encUint(uint64(re.Tag), cborBaseTag) + if re.Data != nil { + en.encode(re.Data) + } else if re.Value == nil { + e.EncodeNil() + } else { + en.encode(re.Value) + } +} + +func (e *cborEncDriver) EncodeArrayStart(length int) { + e.encLen(cborBaseArray, length) +} + +func (e *cborEncDriver) EncodeMapStart(length int) { + e.encLen(cborBaseMap, length) +} + +func (e *cborEncDriver) EncodeString(c charEncoding, v string) { + e.encLen(cborBaseString, len(v)) + e.w.writestr(v) +} + +func (e *cborEncDriver) EncodeSymbol(v string) { + e.EncodeString(c_UTF8, v) +} + +func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) { + if c == c_RAW { + e.encLen(cborBaseBytes, len(v)) + } else { + e.encLen(cborBaseString, len(v)) + } + e.w.writeb(v) +} + +// ---------------------- + +type cborDecDriver struct { + d *Decoder + h *CborHandle + r decReader + b [scratchByteArrayLen]byte + br bool // bytes reader + bdRead bool + bd byte + noBuiltInTypes + decNoSeparator +} + +func (d *cborDecDriver) readNextBd() { + d.bd = d.r.readn1() + d.bdRead = true +} + +func (d *cborDecDriver) ContainerType() (vt valueType) { + if d.bd == cborBdNil { + return valueTypeNil + } else if d.bd == cborBdIndefiniteBytes || (d.bd >= cborBaseBytes && d.bd < cborBaseString) { + return valueTypeBytes + } else if d.bd == cborBdIndefiniteString || (d.bd >= cborBaseString && d.bd < cborBaseArray) { + return valueTypeString + } else if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) { + return valueTypeArray + } else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) { + return valueTypeMap + } else { + // d.d.errorf("isContainerType: unsupported parameter: %v", vt) + } + return valueTypeUnset +} + +func (d *cborDecDriver) TryDecodeAsNil() bool { + if !d.bdRead { + d.readNextBd() + } + // treat Nil and Undefined as nil values + if d.bd == cborBdNil || d.bd == cborBdUndefined { + d.bdRead = false + return true + } + return false +} + +func (d *cborDecDriver) CheckBreak() bool { + if !d.bdRead { + d.readNextBd() + } + if d.bd == cborBdBreak { + d.bdRead = false + return true + } + return false +} + +func (d *cborDecDriver) decUint() (ui uint64) { + v := d.bd & 0x1f + if v <= 0x17 { + ui = uint64(v) + } else { + if v == 0x18 { + ui = uint64(d.r.readn1()) + } else if v == 0x19 { + ui = uint64(bigen.Uint16(d.r.readx(2))) + } else if v == 0x1a { + ui = uint64(bigen.Uint32(d.r.readx(4))) + } else if v == 0x1b { + ui = uint64(bigen.Uint64(d.r.readx(8))) + } else { + d.d.errorf("decUint: Invalid descriptor: %v", d.bd) + return + } + } + return +} + +func (d *cborDecDriver) decCheckInteger() (neg bool) { + if !d.bdRead { + d.readNextBd() + } + major := d.bd >> 5 + if major == cborMajorUint { + } else if major == cborMajorNegInt { + neg = true + } else { + d.d.errorf("invalid major: %v (bd: %v)", major, d.bd) + return + } + return +} + +func (d *cborDecDriver) DecodeInt(bitsize uint8) (i int64) { + neg := d.decCheckInteger() + ui := d.decUint() + // check if this number can be converted to an int without overflow + var overflow bool + if neg { + if i, overflow = chkOvf.SignedInt(ui + 1); overflow { + d.d.errorf("cbor: overflow converting %v to signed integer", ui+1) + return + } + i = -i + } else { + if i, overflow = chkOvf.SignedInt(ui); overflow { + d.d.errorf("cbor: overflow converting %v to signed integer", ui) + return + } + } + if chkOvf.Int(i, bitsize) { + d.d.errorf("cbor: overflow integer: %v", i) + return + } + d.bdRead = false + return +} + +func (d *cborDecDriver) DecodeUint(bitsize uint8) (ui uint64) { + if d.decCheckInteger() { + d.d.errorf("Assigning negative signed value to unsigned type") + return + } + ui = d.decUint() + if chkOvf.Uint(ui, bitsize) { + d.d.errorf("cbor: overflow integer: %v", ui) + return + } + d.bdRead = false + return +} + +func (d *cborDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) { + if !d.bdRead { + d.readNextBd() + } + if bd := d.bd; bd == cborBdFloat16 { + f = float64(math.Float32frombits(halfFloatToFloatBits(bigen.Uint16(d.r.readx(2))))) + } else if bd == cborBdFloat32 { + f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4)))) + } else if bd == cborBdFloat64 { + f = math.Float64frombits(bigen.Uint64(d.r.readx(8))) + } else if bd >= cborBaseUint && bd < cborBaseBytes { + f = float64(d.DecodeInt(64)) + } else { + d.d.errorf("Float only valid from float16/32/64: Invalid descriptor: %v", bd) + return + } + if chkOverflow32 && chkOvf.Float32(f) { + d.d.errorf("cbor: float32 overflow: %v", f) + return + } + d.bdRead = false + return +} + +// bool can be decoded from bool only (single byte). +func (d *cborDecDriver) DecodeBool() (b bool) { + if !d.bdRead { + d.readNextBd() + } + if bd := d.bd; bd == cborBdTrue { + b = true + } else if bd == cborBdFalse { + } else { + d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + return + } + d.bdRead = false + return +} + +func (d *cborDecDriver) ReadMapStart() (length int) { + d.bdRead = false + if d.bd == cborBdIndefiniteMap { + return -1 + } + return d.decLen() +} + +func (d *cborDecDriver) ReadArrayStart() (length int) { + d.bdRead = false + if d.bd == cborBdIndefiniteArray { + return -1 + } + return d.decLen() +} + +func (d *cborDecDriver) decLen() int { + return int(d.decUint()) +} + +func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte { + d.bdRead = false + for { + if d.CheckBreak() { + break + } + if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText { + d.d.errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, d.bd) + return nil + } + n := d.decLen() + oldLen := len(bs) + newLen := oldLen + n + if newLen > cap(bs) { + bs2 := make([]byte, newLen, 2*cap(bs)+n) + copy(bs2, bs) + bs = bs2 + } else { + bs = bs[:newLen] + } + d.r.readb(bs[oldLen:newLen]) + // bs = append(bs, d.r.readn()...) + d.bdRead = false + } + d.bdRead = false + return bs +} + +func (d *cborDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == cborBdNil || d.bd == cborBdUndefined { + d.bdRead = false + return nil + } + if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString { + if bs == nil { + return d.decAppendIndefiniteBytes(nil) + } + return d.decAppendIndefiniteBytes(bs[:0]) + } + clen := d.decLen() + d.bdRead = false + if zerocopy { + if d.br { + return d.r.readx(clen) + } else if len(bs) == 0 { + bs = d.b[:] + } + } + return decByteSlice(d.r, clen, bs) +} + +func (d *cborDecDriver) DecodeString() (s string) { + return string(d.DecodeBytes(d.b[:], true, true)) +} + +func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { + if !d.bdRead { + d.readNextBd() + } + u := d.decUint() + d.bdRead = false + realxtag = u + if ext == nil { + re := rv.(*RawExt) + re.Tag = realxtag + d.d.decode(&re.Value) + } else if xtag != realxtag { + d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", realxtag, xtag) + return + } else { + var v interface{} + d.d.decode(&v) + ext.UpdateExt(rv, v) + } + d.bdRead = false + return +} + +func (d *cborDecDriver) DecodeNaked() { + if !d.bdRead { + d.readNextBd() + } + + n := &d.d.n + var decodeFurther bool + + switch d.bd { + case cborBdNil: + n.v = valueTypeNil + case cborBdFalse: + n.v = valueTypeBool + n.b = false + case cborBdTrue: + n.v = valueTypeBool + n.b = true + case cborBdFloat16, cborBdFloat32: + n.v = valueTypeFloat + n.f = d.DecodeFloat(true) + case cborBdFloat64: + n.v = valueTypeFloat + n.f = d.DecodeFloat(false) + case cborBdIndefiniteBytes: + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + case cborBdIndefiniteString: + n.v = valueTypeString + n.s = d.DecodeString() + case cborBdIndefiniteArray: + n.v = valueTypeArray + decodeFurther = true + case cborBdIndefiniteMap: + n.v = valueTypeMap + decodeFurther = true + default: + switch { + case d.bd >= cborBaseUint && d.bd < cborBaseNegInt: + if d.h.SignedInteger { + n.v = valueTypeInt + n.i = d.DecodeInt(64) + } else { + n.v = valueTypeUint + n.u = d.DecodeUint(64) + } + case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes: + n.v = valueTypeInt + n.i = d.DecodeInt(64) + case d.bd >= cborBaseBytes && d.bd < cborBaseString: + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + case d.bd >= cborBaseString && d.bd < cborBaseArray: + n.v = valueTypeString + n.s = d.DecodeString() + case d.bd >= cborBaseArray && d.bd < cborBaseMap: + n.v = valueTypeArray + decodeFurther = true + case d.bd >= cborBaseMap && d.bd < cborBaseTag: + n.v = valueTypeMap + decodeFurther = true + case d.bd >= cborBaseTag && d.bd < cborBaseSimple: + n.v = valueTypeExt + n.u = d.decUint() + n.l = nil + // d.bdRead = false + // d.d.decode(&re.Value) // handled by decode itself. + // decodeFurther = true + default: + d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd) + return + } + } + + if !decodeFurther { + d.bdRead = false + } + return +} + +// ------------------------- + +// CborHandle is a Handle for the CBOR encoding format, +// defined at http://tools.ietf.org/html/rfc7049 and documented further at http://cbor.io . +// +// CBOR is comprehensively supported, including support for: +// - indefinite-length arrays/maps/bytes/strings +// - (extension) tags in range 0..0xffff (0 .. 65535) +// - half, single and double-precision floats +// - all numbers (1, 2, 4 and 8-byte signed and unsigned integers) +// - nil, true, false, ... +// - arrays and maps, bytes and text strings +// +// None of the optional extensions (with tags) defined in the spec are supported out-of-the-box. +// Users can implement them as needed (using SetExt), including spec-documented ones: +// - timestamp, BigNum, BigFloat, Decimals, Encoded Text (e.g. URL, regexp, base64, MIME Message), etc. +// +// To encode with indefinite lengths (streaming), users will use +// (Must)Encode methods of *Encoder, along with writing CborStreamXXX constants. +// +// For example, to encode "one-byte" as an indefinite length string: +// var buf bytes.Buffer +// e := NewEncoder(&buf, new(CborHandle)) +// buf.WriteByte(CborStreamString) +// e.MustEncode("one-") +// e.MustEncode("byte") +// buf.WriteByte(CborStreamBreak) +// encodedBytes := buf.Bytes() +// var vv interface{} +// NewDecoderBytes(buf.Bytes(), new(CborHandle)).MustDecode(&vv) +// // Now, vv contains the same string "one-byte" +// +type CborHandle struct { + binaryEncodingType + BasicHandle +} + +func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) { + return h.SetExt(rt, tag, &setExtWrapper{i: ext}) +} + +func (h *CborHandle) newEncDriver(e *Encoder) encDriver { + return &cborEncDriver{e: e, w: e.w, h: h} +} + +func (h *CborHandle) newDecDriver(d *Decoder) decDriver { + return &cborDecDriver{d: d, r: d.r, h: h, br: d.bytes} +} + +func (e *cborEncDriver) reset() { + e.w = e.e.w +} + +func (d *cborDecDriver) reset() { + d.r = d.d.r + d.bd, d.bdRead = 0, false +} + +var _ decDriver = (*cborDecDriver)(nil) +var _ encDriver = (*cborEncDriver)(nil) diff --git a/vendor/github.com/ugorji/go/codec/codecgen/README.md b/vendor/github.com/ugorji/go/codec/codecgen/README.md new file mode 100644 index 000000000..3ae8a056f --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/codecgen/README.md @@ -0,0 +1,36 @@ +# codecgen tool + +Generate is given a list of *.go files to parse, and an output file (fout), +codecgen will create an output file __file.go__ which +contains `codec.Selfer` implementations for the named types found +in the files parsed. + +Using codecgen is very straightforward. + +**Download and install the tool** + +`go get -u github.com/ugorji/go/codec/codecgen` + +**Run the tool on your files** + +The command line format is: + +`codecgen [options] (-o outfile) (infile ...)` + +```sh +% codecgen -? +Usage of codecgen: + -c="github.com/ugorji/go/codec": codec path + -o="": out file + -r=".*": regex for type name to match + -rt="": tags for go run + -t="": build tag to put in file + -u=false: Use unsafe, e.g. to avoid unnecessary allocation on []byte->string + -x=false: keep temp file + +% codecgen -o values_codecgen.go values.go values2.go moretypedefs.go +``` + +Please see the [blog article](http://ugorji.net/blog/go-codecgen) +for more information on how to use the tool. + diff --git a/vendor/github.com/ugorji/go/codec/codecgen/gen.go b/vendor/github.com/ugorji/go/codec/codecgen/gen.go new file mode 100644 index 000000000..f370b4c79 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/codecgen/gen.go @@ -0,0 +1,273 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +// codecgen generates codec.Selfer implementations for a set of types. +package main + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "go/ast" + "go/build" + "go/parser" + "go/token" + "math/rand" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "text/template" + "time" +) + +const genCodecPkg = "codec1978" // keep this in sync with codec.genCodecPkg + +const genFrunMainTmpl = `//+build ignore + +package main +{{ if .Types }}import "{{ .ImportPath }}"{{ end }} +func main() { + {{ $.PackageName }}.CodecGenTempWrite{{ .RandString }}() +} +` + +// const genFrunPkgTmpl = `//+build codecgen +const genFrunPkgTmpl = ` +package {{ $.PackageName }} + +import ( + {{ if not .CodecPkgFiles }}{{ .CodecPkgName }} "{{ .CodecImportPath }}"{{ end }} + "os" + "reflect" + "bytes" + "strings" + "go/format" +) + +func CodecGenTempWrite{{ .RandString }}() { + fout, err := os.Create("{{ .OutFile }}") + if err != nil { + panic(err) + } + defer fout.Close() + var out bytes.Buffer + + var typs []reflect.Type +{{ range $index, $element := .Types }} + var t{{ $index }} {{ . }} + typs = append(typs, reflect.TypeOf(t{{ $index }})) +{{ end }} + {{ if not .CodecPkgFiles }}{{ .CodecPkgName }}.{{ end }}Gen(&out, "{{ .BuildTag }}", "{{ .PackageName }}", "{{ .RandString }}", {{ .UseUnsafe }}, {{ if not .CodecPkgFiles }}{{ .CodecPkgName }}.{{ end }}NewTypeInfos(strings.Split("{{ .StructTags }}", ",")), typs...) + bout, err := format.Source(out.Bytes()) + if err != nil { + fout.Write(out.Bytes()) + panic(err) + } + fout.Write(bout) +} + +` + +// Generate is given a list of *.go files to parse, and an output file (fout). +// +// It finds all types T in the files, and it creates 2 tmp files (frun). +// - main package file passed to 'go run' +// - package level file which calls *genRunner.Selfer to write Selfer impls for each T. +// We use a package level file so that it can reference unexported types in the package being worked on. +// Tool then executes: "go run __frun__" which creates fout. +// fout contains Codec(En|De)codeSelf implementations for every type T. +// +func Generate(outfile, buildTag, codecPkgPath string, uid int64, useUnsafe bool, goRunTag string, + st string, regexName *regexp.Regexp, deleteTempFile bool, infiles ...string) (err error) { + // For each file, grab AST, find each type, and write a call to it. + if len(infiles) == 0 { + return + } + if outfile == "" || codecPkgPath == "" { + err = errors.New("outfile and codec package path cannot be blank") + return + } + if uid < 0 { + uid = -uid + } + if uid == 0 { + rr := rand.New(rand.NewSource(time.Now().UnixNano())) + uid = 101 + rr.Int63n(9777) + } + // We have to parse dir for package, before opening the temp file for writing (else ImportDir fails). + // Also, ImportDir(...) must take an absolute path. + lastdir := filepath.Dir(outfile) + absdir, err := filepath.Abs(lastdir) + if err != nil { + return + } + pkg, err := build.Default.ImportDir(absdir, build.AllowBinary) + if err != nil { + return + } + type tmplT struct { + CodecPkgName string + CodecImportPath string + ImportPath string + OutFile string + PackageName string + RandString string + BuildTag string + StructTags string + Types []string + CodecPkgFiles bool + UseUnsafe bool + } + tv := tmplT{ + CodecPkgName: genCodecPkg, + OutFile: outfile, + CodecImportPath: codecPkgPath, + BuildTag: buildTag, + UseUnsafe: useUnsafe, + RandString: strconv.FormatInt(uid, 10), + StructTags: st, + } + tv.ImportPath = pkg.ImportPath + if tv.ImportPath == tv.CodecImportPath { + tv.CodecPkgFiles = true + tv.CodecPkgName = "codec" + } + astfiles := make([]*ast.File, len(infiles)) + for i, infile := range infiles { + if filepath.Dir(infile) != lastdir { + err = errors.New("in files must all be in same directory as outfile") + return + } + fset := token.NewFileSet() + astfiles[i], err = parser.ParseFile(fset, infile, nil, 0) + if err != nil { + return + } + if i == 0 { + tv.PackageName = astfiles[i].Name.Name + if tv.PackageName == "main" { + // codecgen cannot be run on types in the 'main' package. + // A temporary 'main' package must be created, and should reference the fully built + // package containing the types. + // Also, the temporary main package will conflict with the main package which already has a main method. + err = errors.New("codecgen cannot be run on types in the 'main' package") + return + } + } + } + + for _, f := range astfiles { + for _, d := range f.Decls { + if gd, ok := d.(*ast.GenDecl); ok { + for _, dd := range gd.Specs { + if td, ok := dd.(*ast.TypeSpec); ok { + // if len(td.Name.Name) == 0 || td.Name.Name[0] > 'Z' || td.Name.Name[0] < 'A' { + if len(td.Name.Name) == 0 { + continue + } + + // only generate for: + // struct: StructType + // primitives (numbers, bool, string): Ident + // map: MapType + // slice, array: ArrayType + // chan: ChanType + // do not generate: + // FuncType, InterfaceType, StarExpr (ptr), etc + switch td.Type.(type) { + case *ast.StructType, *ast.Ident, *ast.MapType, *ast.ArrayType, *ast.ChanType: + if regexName.FindStringIndex(td.Name.Name) != nil { + tv.Types = append(tv.Types, td.Name.Name) + } + } + } + } + } + } + } + + if len(tv.Types) == 0 { + return + } + + // we cannot use ioutil.TempFile, because we cannot guarantee the file suffix (.go). + // Also, we cannot create file in temp directory, + // because go run will not work (as it needs to see the types here). + // Consequently, create the temp file in the current directory, and remove when done. + + // frun, err = ioutil.TempFile("", "codecgen-") + // frunName := filepath.Join(os.TempDir(), "codecgen-"+strconv.FormatInt(time.Now().UnixNano(), 10)+".go") + + frunMainName := "codecgen-main-" + tv.RandString + ".generated.go" + frunPkgName := "codecgen-pkg-" + tv.RandString + ".generated.go" + if deleteTempFile { + defer os.Remove(frunMainName) + defer os.Remove(frunPkgName) + } + // var frunMain, frunPkg *os.File + if _, err = gen1(frunMainName, genFrunMainTmpl, &tv); err != nil { + return + } + if _, err = gen1(frunPkgName, genFrunPkgTmpl, &tv); err != nil { + return + } + + // remove outfile, so "go run ..." will not think that types in outfile already exist. + os.Remove(outfile) + + // execute go run frun + cmd := exec.Command("go", "run", "-tags="+goRunTag, frunMainName) //, frunPkg.Name()) + var buf bytes.Buffer + cmd.Stdout = &buf + cmd.Stderr = &buf + if err = cmd.Run(); err != nil { + err = fmt.Errorf("error running 'go run %s': %v, console: %s", + frunMainName, err, buf.Bytes()) + return + } + os.Stdout.Write(buf.Bytes()) + return +} + +func gen1(frunName, tmplStr string, tv interface{}) (frun *os.File, err error) { + os.Remove(frunName) + if frun, err = os.Create(frunName); err != nil { + return + } + defer frun.Close() + + t := template.New("") + if t, err = t.Parse(tmplStr); err != nil { + return + } + bw := bufio.NewWriter(frun) + if err = t.Execute(bw, tv); err != nil { + return + } + if err = bw.Flush(); err != nil { + return + } + return +} + +func main() { + o := flag.String("o", "", "out file") + c := flag.String("c", genCodecPath, "codec path") + t := flag.String("t", "", "build tag to put in file") + r := flag.String("r", ".*", "regex for type name to match") + rt := flag.String("rt", "", "tags for go run") + st := flag.String("st", "codec,json", "struct tag keys to introspect") + x := flag.Bool("x", false, "keep temp file") + u := flag.Bool("u", false, "Use unsafe, e.g. to avoid unnecessary allocation on []byte->string") + d := flag.Int64("d", 0, "random identifier for use in generated code") + flag.Parse() + if err := Generate(*o, *t, *c, *d, *u, *rt, *st, + regexp.MustCompile(*r), !*x, flag.Args()...); err != nil { + fmt.Fprintf(os.Stderr, "codecgen error: %v\n", err) + os.Exit(1) + } +} diff --git a/vendor/github.com/ugorji/go/codec/codecgen/z.go b/vendor/github.com/ugorji/go/codec/codecgen/z.go new file mode 100644 index 000000000..e120a4eb9 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/codecgen/z.go @@ -0,0 +1,3 @@ +package main + +const genCodecPath = "github.com/ugorji/go/codec" diff --git a/vendor/github.com/ugorji/go/codec/decode.go b/vendor/github.com/ugorji/go/codec/decode.go new file mode 100644 index 000000000..7e56f1eca --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/decode.go @@ -0,0 +1,2019 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "encoding" + "errors" + "fmt" + "io" + "reflect" + "time" +) + +// Some tagging information for error messages. +const ( + msgBadDesc = "Unrecognized descriptor byte" + msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v" +) + +var ( + onlyMapOrArrayCanDecodeIntoStructErr = errors.New("only encoded map or array can be decoded into a struct") + cannotDecodeIntoNilErr = errors.New("cannot decode into nil") +) + +// decReader abstracts the reading source, allowing implementations that can +// read from an io.Reader or directly off a byte slice with zero-copying. +type decReader interface { + unreadn1() + + // readx will use the implementation scratch buffer if possible i.e. n < len(scratchbuf), OR + // just return a view of the []byte being decoded from. + // Ensure you call detachZeroCopyBytes later if this needs to be sent outside codec control. + readx(n int) []byte + readb([]byte) + readn1() uint8 + readn1eof() (v uint8, eof bool) + numread() int // number of bytes read + track() + stopTrack() []byte +} + +type decReaderByteScanner interface { + io.Reader + io.ByteScanner +} + +type decDriver interface { + // this will check if the next token is a break. + CheckBreak() bool + TryDecodeAsNil() bool + // vt is one of: Bytes, String, Nil, Slice or Map. Return unSet if not known. + ContainerType() (vt valueType) + IsBuiltinType(rt uintptr) bool + DecodeBuiltin(rt uintptr, v interface{}) + + // DecodeNaked will decode primitives (number, bool, string, []byte) and RawExt. + // For maps and arrays, it will not do the decoding in-band, but will signal + // the decoder, so that is done later, by setting the decNaked.valueType field. + // + // Note: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types). + // for extensions, DecodeNaked must read the tag and the []byte if it exists. + // if the []byte is not read, then kInterfaceNaked will treat it as a Handle + // that stores the subsequent value in-band, and complete reading the RawExt. + // + // extensions should also use readx to decode them, for efficiency. + // kInterface will extract the detached byte slice if it has to pass it outside its realm. + DecodeNaked() + DecodeInt(bitsize uint8) (i int64) + DecodeUint(bitsize uint8) (ui uint64) + DecodeFloat(chkOverflow32 bool) (f float64) + DecodeBool() (b bool) + // DecodeString can also decode symbols. + // It looks redundant as DecodeBytes is available. + // However, some codecs (e.g. binc) support symbols and can + // return a pre-stored string value, meaning that it can bypass + // the cost of []byte->string conversion. + DecodeString() (s string) + + // DecodeBytes may be called directly, without going through reflection. + // Consequently, it must be designed to handle possible nil. + DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) + + // decodeExt will decode into a *RawExt or into an extension. + DecodeExt(v interface{}, xtag uint64, ext Ext) (realxtag uint64) + // decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) + ReadMapStart() int + ReadArrayStart() int + + reset() + uncacheRead() +} + +type decNoSeparator struct{} + +func (_ decNoSeparator) ReadEnd() {} +func (_ decNoSeparator) uncacheRead() {} + +type DecodeOptions struct { + // MapType specifies type to use during schema-less decoding of a map in the stream. + // If nil, we use map[interface{}]interface{} + MapType reflect.Type + + // SliceType specifies type to use during schema-less decoding of an array in the stream. + // If nil, we use []interface{} + SliceType reflect.Type + + // MaxInitLen defines the initial length that we "make" a collection (slice, chan or map) with. + // If 0 or negative, we default to a sensible value based on the size of an element in the collection. + // + // For example, when decoding, a stream may say that it has MAX_UINT elements. + // We should not auto-matically provision a slice of that length, to prevent Out-Of-Memory crash. + // Instead, we provision up to MaxInitLen, fill that up, and start appending after that. + MaxInitLen int + + // If ErrorIfNoField, return an error when decoding a map + // from a codec stream into a struct, and no matching struct field is found. + ErrorIfNoField bool + + // If ErrorIfNoArrayExpand, return an error when decoding a slice/array that cannot be expanded. + // For example, the stream contains an array of 8 items, but you are decoding into a [4]T array, + // or you are decoding into a slice of length 4 which is non-addressable (and so cannot be set). + ErrorIfNoArrayExpand bool + + // If SignedInteger, use the int64 during schema-less decoding of unsigned values (not uint64). + SignedInteger bool + + // MapValueReset controls how we decode into a map value. + // + // By default, we MAY retrieve the mapping for a key, and then decode into that. + // However, especially with big maps, that retrieval may be expensive and unnecessary + // if the stream already contains all that is necessary to recreate the value. + // + // If true, we will never retrieve the previous mapping, + // but rather decode into a new value and set that in the map. + // + // If false, we will retrieve the previous mapping if necessary e.g. + // the previous mapping is a pointer, or is a struct or array with pre-set state, + // or is an interface. + MapValueReset bool + + // InterfaceReset controls how we decode into an interface. + // + // By default, when we see a field that is an interface{...}, + // or a map with interface{...} value, we will attempt decoding into the + // "contained" value. + // + // However, this prevents us from reading a string into an interface{} + // that formerly contained a number. + // + // If true, we will decode into a new "blank" value, and set that in the interface. + // If false, we will decode into whatever is contained in the interface. + InterfaceReset bool + + // InternString controls interning of strings during decoding. + // + // Some handles, e.g. json, typically will read map keys as strings. + // If the set of keys are finite, it may help reduce allocation to + // look them up from a map (than to allocate them afresh). + // + // Note: Handles will be smart when using the intern functionality. + // So everything will not be interned. + InternString bool +} + +// ------------------------------------ + +// ioDecByteScanner implements Read(), ReadByte(...), UnreadByte(...) methods +// of io.Reader, io.ByteScanner. +type ioDecByteScanner struct { + r io.Reader + l byte // last byte + ls byte // last byte status. 0: init-canDoNothing, 1: canRead, 2: canUnread + b [1]byte // tiny buffer for reading single bytes +} + +func (z *ioDecByteScanner) Read(p []byte) (n int, err error) { + var firstByte bool + if z.ls == 1 { + z.ls = 2 + p[0] = z.l + if len(p) == 1 { + n = 1 + return + } + firstByte = true + p = p[1:] + } + n, err = z.r.Read(p) + if n > 0 { + if err == io.EOF && n == len(p) { + err = nil // read was successful, so postpone EOF (till next time) + } + z.l = p[n-1] + z.ls = 2 + } + if firstByte { + n++ + } + return +} + +func (z *ioDecByteScanner) ReadByte() (c byte, err error) { + n, err := z.Read(z.b[:]) + if n == 1 { + c = z.b[0] + if err == io.EOF { + err = nil // read was successful, so postpone EOF (till next time) + } + } + return +} + +func (z *ioDecByteScanner) UnreadByte() (err error) { + x := z.ls + if x == 0 { + err = errors.New("cannot unread - nothing has been read") + } else if x == 1 { + err = errors.New("cannot unread - last byte has not been read") + } else if x == 2 { + z.ls = 1 + } + return +} + +// ioDecReader is a decReader that reads off an io.Reader +type ioDecReader struct { + br decReaderByteScanner + // temp byte array re-used internally for efficiency during read. + // shares buffer with Decoder, so we keep size of struct within 8 words. + x *[scratchByteArrayLen]byte + bs ioDecByteScanner + n int // num read + tr []byte // tracking bytes read + trb bool +} + +func (z *ioDecReader) numread() int { + return z.n +} + +func (z *ioDecReader) readx(n int) (bs []byte) { + if n <= 0 { + return + } + if n < len(z.x) { + bs = z.x[:n] + } else { + bs = make([]byte, n) + } + if _, err := io.ReadAtLeast(z.br, bs, n); err != nil { + panic(err) + } + z.n += len(bs) + if z.trb { + z.tr = append(z.tr, bs...) + } + return +} + +func (z *ioDecReader) readb(bs []byte) { + if len(bs) == 0 { + return + } + n, err := io.ReadAtLeast(z.br, bs, len(bs)) + z.n += n + if err != nil { + panic(err) + } + if z.trb { + z.tr = append(z.tr, bs...) + } +} + +func (z *ioDecReader) readn1() (b uint8) { + b, err := z.br.ReadByte() + if err != nil { + panic(err) + } + z.n++ + if z.trb { + z.tr = append(z.tr, b) + } + return b +} + +func (z *ioDecReader) readn1eof() (b uint8, eof bool) { + b, err := z.br.ReadByte() + if err == nil { + z.n++ + if z.trb { + z.tr = append(z.tr, b) + } + } else if err == io.EOF { + eof = true + } else { + panic(err) + } + return +} + +func (z *ioDecReader) unreadn1() { + err := z.br.UnreadByte() + if err != nil { + panic(err) + } + z.n-- + if z.trb { + if l := len(z.tr) - 1; l >= 0 { + z.tr = z.tr[:l] + } + } +} + +func (z *ioDecReader) track() { + if z.tr != nil { + z.tr = z.tr[:0] + } + z.trb = true +} + +func (z *ioDecReader) stopTrack() (bs []byte) { + z.trb = false + return z.tr +} + +// ------------------------------------ + +var bytesDecReaderCannotUnreadErr = errors.New("cannot unread last byte read") + +// bytesDecReader is a decReader that reads off a byte slice with zero copying +type bytesDecReader struct { + b []byte // data + c int // cursor + a int // available + t int // track start +} + +func (z *bytesDecReader) reset(in []byte) { + z.b = in + z.a = len(in) + z.c = 0 + z.t = 0 +} + +func (z *bytesDecReader) numread() int { + return z.c +} + +func (z *bytesDecReader) unreadn1() { + if z.c == 0 || len(z.b) == 0 { + panic(bytesDecReaderCannotUnreadErr) + } + z.c-- + z.a++ + return +} + +func (z *bytesDecReader) readx(n int) (bs []byte) { + // slicing from a non-constant start position is more expensive, + // as more computation is required to decipher the pointer start position. + // However, we do it only once, and it's better than reslicing both z.b and return value. + + if n <= 0 { + } else if z.a == 0 { + panic(io.EOF) + } else if n > z.a { + panic(io.ErrUnexpectedEOF) + } else { + c0 := z.c + z.c = c0 + n + z.a = z.a - n + bs = z.b[c0:z.c] + } + return +} + +func (z *bytesDecReader) readn1() (v uint8) { + if z.a == 0 { + panic(io.EOF) + } + v = z.b[z.c] + z.c++ + z.a-- + return +} + +func (z *bytesDecReader) readn1eof() (v uint8, eof bool) { + if z.a == 0 { + eof = true + return + } + v = z.b[z.c] + z.c++ + z.a-- + return +} + +func (z *bytesDecReader) readb(bs []byte) { + copy(bs, z.readx(len(bs))) +} + +func (z *bytesDecReader) track() { + z.t = z.c +} + +func (z *bytesDecReader) stopTrack() (bs []byte) { + return z.b[z.t:z.c] +} + +// ------------------------------------ + +type decFnInfo struct { + d *Decoder + ti *typeInfo + xfFn Ext + xfTag uint64 + seq seqType +} + +// ---------------------------------------- + +type decFn struct { + i decFnInfo + f func(*decFnInfo, reflect.Value) +} + +func (f *decFnInfo) builtin(rv reflect.Value) { + f.d.d.DecodeBuiltin(f.ti.rtid, rv.Addr().Interface()) +} + +func (f *decFnInfo) rawExt(rv reflect.Value) { + f.d.d.DecodeExt(rv.Addr().Interface(), 0, nil) +} + +func (f *decFnInfo) ext(rv reflect.Value) { + f.d.d.DecodeExt(rv.Addr().Interface(), f.xfTag, f.xfFn) +} + +func (f *decFnInfo) getValueForUnmarshalInterface(rv reflect.Value, indir int8) (v interface{}) { + if indir == -1 { + v = rv.Addr().Interface() + } else if indir == 0 { + v = rv.Interface() + } else { + for j := int8(0); j < indir; j++ { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + rv = rv.Elem() + } + v = rv.Interface() + } + return +} + +func (f *decFnInfo) selferUnmarshal(rv reflect.Value) { + f.getValueForUnmarshalInterface(rv, f.ti.csIndir).(Selfer).CodecDecodeSelf(f.d) +} + +func (f *decFnInfo) binaryUnmarshal(rv reflect.Value) { + bm := f.getValueForUnmarshalInterface(rv, f.ti.bunmIndir).(encoding.BinaryUnmarshaler) + xbs := f.d.d.DecodeBytes(nil, false, true) + if fnerr := bm.UnmarshalBinary(xbs); fnerr != nil { + panic(fnerr) + } +} + +func (f *decFnInfo) textUnmarshal(rv reflect.Value) { + tm := f.getValueForUnmarshalInterface(rv, f.ti.tunmIndir).(encoding.TextUnmarshaler) + fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true)) + if fnerr != nil { + panic(fnerr) + } +} + +func (f *decFnInfo) jsonUnmarshal(rv reflect.Value) { + tm := f.getValueForUnmarshalInterface(rv, f.ti.junmIndir).(jsonUnmarshaler) + // bs := f.d.d.DecodeBytes(f.d.b[:], true, true) + // grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself. + fnerr := tm.UnmarshalJSON(f.d.nextValueBytes()) + if fnerr != nil { + panic(fnerr) + } +} + +func (f *decFnInfo) kErr(rv reflect.Value) { + f.d.errorf("no decoding function defined for kind %v", rv.Kind()) +} + +func (f *decFnInfo) kString(rv reflect.Value) { + rv.SetString(f.d.d.DecodeString()) +} + +func (f *decFnInfo) kBool(rv reflect.Value) { + rv.SetBool(f.d.d.DecodeBool()) +} + +func (f *decFnInfo) kInt(rv reflect.Value) { + rv.SetInt(f.d.d.DecodeInt(intBitsize)) +} + +func (f *decFnInfo) kInt64(rv reflect.Value) { + rv.SetInt(f.d.d.DecodeInt(64)) +} + +func (f *decFnInfo) kInt32(rv reflect.Value) { + rv.SetInt(f.d.d.DecodeInt(32)) +} + +func (f *decFnInfo) kInt8(rv reflect.Value) { + rv.SetInt(f.d.d.DecodeInt(8)) +} + +func (f *decFnInfo) kInt16(rv reflect.Value) { + rv.SetInt(f.d.d.DecodeInt(16)) +} + +func (f *decFnInfo) kFloat32(rv reflect.Value) { + rv.SetFloat(f.d.d.DecodeFloat(true)) +} + +func (f *decFnInfo) kFloat64(rv reflect.Value) { + rv.SetFloat(f.d.d.DecodeFloat(false)) +} + +func (f *decFnInfo) kUint8(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(8)) +} + +func (f *decFnInfo) kUint64(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(64)) +} + +func (f *decFnInfo) kUint(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(uintBitsize)) +} + +func (f *decFnInfo) kUintptr(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(uintBitsize)) +} + +func (f *decFnInfo) kUint32(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(32)) +} + +func (f *decFnInfo) kUint16(rv reflect.Value) { + rv.SetUint(f.d.d.DecodeUint(16)) +} + +// func (f *decFnInfo) kPtr(rv reflect.Value) { +// debugf(">>>>>>> ??? decode kPtr called - shouldn't get called") +// if rv.IsNil() { +// rv.Set(reflect.New(rv.Type().Elem())) +// } +// f.d.decodeValue(rv.Elem()) +// } + +// var kIntfCtr uint64 + +func (f *decFnInfo) kInterfaceNaked() (rvn reflect.Value) { + // nil interface: + // use some hieristics to decode it appropriately + // based on the detected next value in the stream. + d := f.d + d.d.DecodeNaked() + n := &d.n + if n.v == valueTypeNil { + return + } + // We cannot decode non-nil stream value into nil interface with methods (e.g. io.Reader). + // if num := f.ti.rt.NumMethod(); num > 0 { + if f.ti.numMeth > 0 { + d.errorf("cannot decode non-nil codec value into nil %v (%v methods)", f.ti.rt, f.ti.numMeth) + return + } + // var useRvn bool + switch n.v { + case valueTypeMap: + // if d.h.MapType == nil || d.h.MapType == mapIntfIntfTyp { + // } else if d.h.MapType == mapStrIntfTyp { // for json performance + // } + if d.mtid == 0 || d.mtid == mapIntfIntfTypId { + l := len(n.ms) + n.ms = append(n.ms, nil) + var v2 interface{} = &n.ms[l] + d.decode(v2) + rvn = reflect.ValueOf(v2).Elem() + n.ms = n.ms[:l] + } else if d.mtid == mapStrIntfTypId { // for json performance + l := len(n.ns) + n.ns = append(n.ns, nil) + var v2 interface{} = &n.ns[l] + d.decode(v2) + rvn = reflect.ValueOf(v2).Elem() + n.ns = n.ns[:l] + } else { + rvn = reflect.New(d.h.MapType).Elem() + d.decodeValue(rvn, nil) + } + case valueTypeArray: + // if d.h.SliceType == nil || d.h.SliceType == intfSliceTyp { + if d.stid == 0 || d.stid == intfSliceTypId { + l := len(n.ss) + n.ss = append(n.ss, nil) + var v2 interface{} = &n.ss[l] + d.decode(v2) + rvn = reflect.ValueOf(v2).Elem() + n.ss = n.ss[:l] + } else { + rvn = reflect.New(d.h.SliceType).Elem() + d.decodeValue(rvn, nil) + } + case valueTypeExt: + var v interface{} + tag, bytes := n.u, n.l // calling decode below might taint the values + if bytes == nil { + l := len(n.is) + n.is = append(n.is, nil) + v2 := &n.is[l] + d.decode(v2) + v = *v2 + n.is = n.is[:l] + } + bfn := d.h.getExtForTag(tag) + if bfn == nil { + var re RawExt + re.Tag = tag + re.Data = detachZeroCopyBytes(d.bytes, nil, bytes) + rvn = reflect.ValueOf(re) + } else { + rvnA := reflect.New(bfn.rt) + rvn = rvnA.Elem() + if bytes != nil { + bfn.ext.ReadExt(rvnA.Interface(), bytes) + } else { + bfn.ext.UpdateExt(rvnA.Interface(), v) + } + } + case valueTypeNil: + // no-op + case valueTypeInt: + rvn = reflect.ValueOf(&n.i).Elem() + case valueTypeUint: + rvn = reflect.ValueOf(&n.u).Elem() + case valueTypeFloat: + rvn = reflect.ValueOf(&n.f).Elem() + case valueTypeBool: + rvn = reflect.ValueOf(&n.b).Elem() + case valueTypeString, valueTypeSymbol: + rvn = reflect.ValueOf(&n.s).Elem() + case valueTypeBytes: + rvn = reflect.ValueOf(&n.l).Elem() + case valueTypeTimestamp: + rvn = reflect.ValueOf(&n.t).Elem() + default: + panic(fmt.Errorf("kInterfaceNaked: unexpected valueType: %d", n.v)) + } + return +} + +func (f *decFnInfo) kInterface(rv reflect.Value) { + // debugf("\t===> kInterface") + + // Note: + // A consequence of how kInterface works, is that + // if an interface already contains something, we try + // to decode into what was there before. + // We do not replace with a generic value (as got from decodeNaked). + + var rvn reflect.Value + if rv.IsNil() { + rvn = f.kInterfaceNaked() + if rvn.IsValid() { + rv.Set(rvn) + } + } else if f.d.h.InterfaceReset { + rvn = f.kInterfaceNaked() + if rvn.IsValid() { + rv.Set(rvn) + } else { + // reset to zero value based on current type in there. + rv.Set(reflect.Zero(rv.Elem().Type())) + } + } else { + rvn = rv.Elem() + // Note: interface{} is settable, but underlying type may not be. + // Consequently, we have to set the reflect.Value directly. + // if underlying type is settable (e.g. ptr or interface), + // we just decode into it. + // Else we create a settable value, decode into it, and set on the interface. + if rvn.CanSet() { + f.d.decodeValue(rvn, nil) + } else { + rvn2 := reflect.New(rvn.Type()).Elem() + rvn2.Set(rvn) + f.d.decodeValue(rvn2, nil) + rv.Set(rvn2) + } + } +} + +func (f *decFnInfo) kStruct(rv reflect.Value) { + fti := f.ti + d := f.d + dd := d.d + cr := d.cr + ctyp := dd.ContainerType() + if ctyp == valueTypeMap { + containerLen := dd.ReadMapStart() + if containerLen == 0 { + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return + } + tisfi := fti.sfi + hasLen := containerLen >= 0 + if hasLen { + for j := 0; j < containerLen; j++ { + // rvkencname := dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapKey) + } + rvkencname := stringView(dd.DecodeBytes(f.d.b[:], true, true)) + // rvksi := ti.getForEncName(rvkencname) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if k := fti.indexForEncName(rvkencname); k > -1 { + si := tisfi[k] + if dd.TryDecodeAsNil() { + si.setToZeroValue(rv) + } else { + d.decodeValue(si.field(rv, true), nil) + } + } else { + d.structFieldNotFound(-1, rvkencname) + } + } + } else { + for j := 0; !dd.CheckBreak(); j++ { + // rvkencname := dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapKey) + } + rvkencname := stringView(dd.DecodeBytes(f.d.b[:], true, true)) + // rvksi := ti.getForEncName(rvkencname) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if k := fti.indexForEncName(rvkencname); k > -1 { + si := tisfi[k] + if dd.TryDecodeAsNil() { + si.setToZeroValue(rv) + } else { + d.decodeValue(si.field(rv, true), nil) + } + } else { + d.structFieldNotFound(-1, rvkencname) + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + } else if ctyp == valueTypeArray { + containerLen := dd.ReadArrayStart() + if containerLen == 0 { + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } + return + } + // Not much gain from doing it two ways for array. + // Arrays are not used as much for structs. + hasLen := containerLen >= 0 + for j, si := range fti.sfip { + if hasLen { + if j == containerLen { + break + } + } else if dd.CheckBreak() { + break + } + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + if dd.TryDecodeAsNil() { + si.setToZeroValue(rv) + } else { + d.decodeValue(si.field(rv, true), nil) + } + } + if containerLen > len(fti.sfip) { + // read remaining values and throw away + for j := len(fti.sfip); j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + d.structFieldNotFound(j, "") + } + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } + } else { + f.d.error(onlyMapOrArrayCanDecodeIntoStructErr) + return + } +} + +func (f *decFnInfo) kSlice(rv reflect.Value) { + // A slice can be set from a map or array in stream. + // This way, the order can be kept (as order is lost with map). + ti := f.ti + d := f.d + dd := d.d + rtelem0 := ti.rt.Elem() + ctyp := dd.ContainerType() + if ctyp == valueTypeBytes || ctyp == valueTypeString { + // you can only decode bytes or string in the stream into a slice or array of bytes + if !(ti.rtid == uint8SliceTypId || rtelem0.Kind() == reflect.Uint8) { + f.d.errorf("bytes or string in the stream must be decoded into a slice or array of bytes, not %v", ti.rt) + } + if f.seq == seqTypeChan { + bs2 := dd.DecodeBytes(nil, false, true) + ch := rv.Interface().(chan<- byte) + for _, b := range bs2 { + ch <- b + } + } else { + rvbs := rv.Bytes() + bs2 := dd.DecodeBytes(rvbs, false, false) + if rvbs == nil && bs2 != nil || rvbs != nil && bs2 == nil || len(bs2) != len(rvbs) { + if rv.CanSet() { + rv.SetBytes(bs2) + } else { + copy(rvbs, bs2) + } + } + } + return + } + + // array := f.seq == seqTypeChan + + slh, containerLenS := d.decSliceHelperStart() // only expects valueType(Array|Map) + + // // an array can never return a nil slice. so no need to check f.array here. + if containerLenS == 0 { + if f.seq == seqTypeSlice { + if rv.IsNil() { + rv.Set(reflect.MakeSlice(ti.rt, 0, 0)) + } else { + rv.SetLen(0) + } + } else if f.seq == seqTypeChan { + if rv.IsNil() { + rv.Set(reflect.MakeChan(ti.rt, 0)) + } + } + slh.End() + return + } + + rtelem := rtelem0 + for rtelem.Kind() == reflect.Ptr { + rtelem = rtelem.Elem() + } + fn := d.getDecFn(rtelem, true, true) + + var rv0, rv9 reflect.Value + rv0 = rv + rvChanged := false + + // for j := 0; j < containerLenS; j++ { + var rvlen int + if containerLenS > 0 { // hasLen + if f.seq == seqTypeChan { + if rv.IsNil() { + rvlen, _ = decInferLen(containerLenS, f.d.h.MaxInitLen, int(rtelem0.Size())) + rv.Set(reflect.MakeChan(ti.rt, rvlen)) + } + // handle chan specially: + for j := 0; j < containerLenS; j++ { + rv9 = reflect.New(rtelem0).Elem() + slh.ElemContainerState(j) + d.decodeValue(rv9, fn) + rv.Send(rv9) + } + } else { // slice or array + var truncated bool // says len of sequence is not same as expected number of elements + numToRead := containerLenS // if truncated, reset numToRead + + rvcap := rv.Cap() + rvlen = rv.Len() + if containerLenS > rvcap { + if f.seq == seqTypeArray { + d.arrayCannotExpand(rvlen, containerLenS) + } else { + oldRvlenGtZero := rvlen > 0 + rvlen, truncated = decInferLen(containerLenS, f.d.h.MaxInitLen, int(rtelem0.Size())) + if truncated { + if rvlen <= rvcap { + rv.SetLen(rvlen) + } else { + rv = reflect.MakeSlice(ti.rt, rvlen, rvlen) + rvChanged = true + } + } else { + rv = reflect.MakeSlice(ti.rt, rvlen, rvlen) + rvChanged = true + } + if rvChanged && oldRvlenGtZero && !isImmutableKind(rtelem0.Kind()) { + reflect.Copy(rv, rv0) // only copy up to length NOT cap i.e. rv0.Slice(0, rvcap) + } + rvcap = rvlen + } + numToRead = rvlen + } else if containerLenS != rvlen { + if f.seq == seqTypeSlice { + rv.SetLen(containerLenS) + rvlen = containerLenS + } + } + j := 0 + // we read up to the numToRead + for ; j < numToRead; j++ { + slh.ElemContainerState(j) + d.decodeValue(rv.Index(j), fn) + } + + // if slice, expand and read up to containerLenS (or EOF) iff truncated + // if array, swallow all the rest. + + if f.seq == seqTypeArray { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } else if truncated { // slice was truncated, as chan NOT in this block + for ; j < containerLenS; j++ { + rv = expandSliceValue(rv, 1) + rv9 = rv.Index(j) + if resetSliceElemToZeroValue { + rv9.Set(reflect.Zero(rtelem0)) + } + slh.ElemContainerState(j) + d.decodeValue(rv9, fn) + } + } + } + } else { + rvlen = rv.Len() + j := 0 + for ; !dd.CheckBreak(); j++ { + if f.seq == seqTypeChan { + slh.ElemContainerState(j) + rv9 = reflect.New(rtelem0).Elem() + d.decodeValue(rv9, fn) + rv.Send(rv9) + } else { + // if indefinite, etc, then expand the slice if necessary + var decodeIntoBlank bool + if j >= rvlen { + if f.seq == seqTypeArray { + d.arrayCannotExpand(rvlen, j+1) + decodeIntoBlank = true + } else { // if f.seq == seqTypeSlice + // rv = reflect.Append(rv, reflect.Zero(rtelem0)) // uses append logic, plus varargs + rv = expandSliceValue(rv, 1) + rv9 = rv.Index(j) + // rv.Index(rv.Len() - 1).Set(reflect.Zero(rtelem0)) + if resetSliceElemToZeroValue { + rv9.Set(reflect.Zero(rtelem0)) + } + rvlen++ + rvChanged = true + } + } else { // slice or array + rv9 = rv.Index(j) + } + slh.ElemContainerState(j) + if decodeIntoBlank { + d.swallow() + } else { // seqTypeSlice + d.decodeValue(rv9, fn) + } + } + } + if f.seq == seqTypeSlice { + if j < rvlen { + rv.SetLen(j) + } else if j == 0 && rv.IsNil() { + rv = reflect.MakeSlice(ti.rt, 0, 0) + rvChanged = true + } + } + } + slh.End() + + if rvChanged { + rv0.Set(rv) + } +} + +func (f *decFnInfo) kArray(rv reflect.Value) { + // f.d.decodeValue(rv.Slice(0, rv.Len())) + f.kSlice(rv.Slice(0, rv.Len())) +} + +func (f *decFnInfo) kMap(rv reflect.Value) { + d := f.d + dd := d.d + containerLen := dd.ReadMapStart() + cr := d.cr + ti := f.ti + if rv.IsNil() { + rv.Set(reflect.MakeMap(ti.rt)) + } + + if containerLen == 0 { + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return + } + + ktype, vtype := ti.rt.Key(), ti.rt.Elem() + ktypeId := reflect.ValueOf(ktype).Pointer() + vtypeKind := vtype.Kind() + var keyFn, valFn *decFn + var xtyp reflect.Type + for xtyp = ktype; xtyp.Kind() == reflect.Ptr; xtyp = xtyp.Elem() { + } + keyFn = d.getDecFn(xtyp, true, true) + for xtyp = vtype; xtyp.Kind() == reflect.Ptr; xtyp = xtyp.Elem() { + } + valFn = d.getDecFn(xtyp, true, true) + var mapGet, mapSet bool + if !f.d.h.MapValueReset { + // if pointer, mapGet = true + // if interface, mapGet = true if !DecodeNakedAlways (else false) + // if builtin, mapGet = false + // else mapGet = true + if vtypeKind == reflect.Ptr { + mapGet = true + } else if vtypeKind == reflect.Interface { + if !f.d.h.InterfaceReset { + mapGet = true + } + } else if !isImmutableKind(vtypeKind) { + mapGet = true + } + } + + var rvk, rvv, rvz reflect.Value + + // for j := 0; j < containerLen; j++ { + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + rvk = reflect.New(ktype).Elem() + if cr != nil { + cr.sendContainerState(containerMapKey) + } + d.decodeValue(rvk, keyFn) + + // special case if a byte array. + if ktypeId == intfTypId { + rvk = rvk.Elem() + if rvk.Type() == uint8SliceTyp { + rvk = reflect.ValueOf(d.string(rvk.Bytes())) + } + } + mapSet = true // set to false if u do a get, and its a pointer, and exists + if mapGet { + rvv = rv.MapIndex(rvk) + if rvv.IsValid() { + if vtypeKind == reflect.Ptr { + mapSet = false + } + } else { + if rvz.IsValid() { + rvz.Set(reflect.Zero(vtype)) + } else { + rvz = reflect.New(vtype).Elem() + } + rvv = rvz + } + } else { + if rvz.IsValid() { + rvz.Set(reflect.Zero(vtype)) + } else { + rvz = reflect.New(vtype).Elem() + } + rvv = rvz + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + d.decodeValue(rvv, valFn) + if mapSet { + rv.SetMapIndex(rvk, rvv) + } + } + } else { + for j := 0; !dd.CheckBreak(); j++ { + rvk = reflect.New(ktype).Elem() + if cr != nil { + cr.sendContainerState(containerMapKey) + } + d.decodeValue(rvk, keyFn) + + // special case if a byte array. + if ktypeId == intfTypId { + rvk = rvk.Elem() + if rvk.Type() == uint8SliceTyp { + rvk = reflect.ValueOf(d.string(rvk.Bytes())) + } + } + mapSet = true // set to false if u do a get, and its a pointer, and exists + if mapGet { + rvv = rv.MapIndex(rvk) + if rvv.IsValid() { + if vtypeKind == reflect.Ptr { + mapSet = false + } + } else { + if rvz.IsValid() { + rvz.Set(reflect.Zero(vtype)) + } else { + rvz = reflect.New(vtype).Elem() + } + rvv = rvz + } + } else { + if rvz.IsValid() { + rvz.Set(reflect.Zero(vtype)) + } else { + rvz = reflect.New(vtype).Elem() + } + rvv = rvz + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + d.decodeValue(rvv, valFn) + if mapSet { + rv.SetMapIndex(rvk, rvv) + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +type decRtidFn struct { + rtid uintptr + fn decFn +} + +// decNaked is used to keep track of the primitives decoded. +// Without it, we would have to decode each primitive and wrap it +// in an interface{}, causing an allocation. +// In this model, the primitives are decoded in a "pseudo-atomic" fashion, +// so we can rest assured that no other decoding happens while these +// primitives are being decoded. +// +// maps and arrays are not handled by this mechanism. +// However, RawExt is, and we accomodate for extensions that decode +// RawExt from DecodeNaked, but need to decode the value subsequently. +// kInterfaceNaked and swallow, which call DecodeNaked, handle this caveat. +// +// However, decNaked also keeps some arrays of default maps and slices +// used in DecodeNaked. This way, we can get a pointer to it +// without causing a new heap allocation. +// +// kInterfaceNaked will ensure that there is no allocation for the common +// uses. +type decNaked struct { + // r RawExt // used for RawExt, uint, []byte. + u uint64 + i int64 + f float64 + l []byte + s string + t time.Time + b bool + v valueType + + // stacks for reducing allocation + is []interface{} + ms []map[interface{}]interface{} + ns []map[string]interface{} + ss [][]interface{} + // rs []RawExt + + // keep arrays at the bottom? Chance is that they are not used much. + ia [4]interface{} + ma [4]map[interface{}]interface{} + na [4]map[string]interface{} + sa [4][]interface{} + // ra [2]RawExt +} + +func (n *decNaked) reset() { + if n.ss != nil { + n.ss = n.ss[:0] + } + if n.is != nil { + n.is = n.is[:0] + } + if n.ms != nil { + n.ms = n.ms[:0] + } + if n.ns != nil { + n.ns = n.ns[:0] + } +} + +// A Decoder reads and decodes an object from an input stream in the codec format. +type Decoder struct { + // hopefully, reduce derefencing cost by laying the decReader inside the Decoder. + // Try to put things that go together to fit within a cache line (8 words). + + d decDriver + // NOTE: Decoder shouldn't call it's read methods, + // as the handler MAY need to do some coordination. + r decReader + // sa [initCollectionCap]decRtidFn + h *BasicHandle + hh Handle + + be bool // is binary encoding + bytes bool // is bytes reader + js bool // is json handle + + rb bytesDecReader + ri ioDecReader + cr containerStateRecv + + s []decRtidFn + f map[uintptr]*decFn + + // _ uintptr // for alignment purposes, so next one starts from a cache line + + // cache the mapTypeId and sliceTypeId for faster comparisons + mtid uintptr + stid uintptr + + n decNaked + b [scratchByteArrayLen]byte + is map[string]string // used for interning strings +} + +// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader. +// +// For efficiency, Users are encouraged to pass in a memory buffered reader +// (eg bufio.Reader, bytes.Buffer). +func NewDecoder(r io.Reader, h Handle) *Decoder { + d := newDecoder(h) + d.Reset(r) + return d +} + +// NewDecoderBytes returns a Decoder which efficiently decodes directly +// from a byte slice with zero copying. +func NewDecoderBytes(in []byte, h Handle) *Decoder { + d := newDecoder(h) + d.ResetBytes(in) + return d +} + +func newDecoder(h Handle) *Decoder { + d := &Decoder{hh: h, h: h.getBasicHandle(), be: h.isBinary()} + n := &d.n + // n.rs = n.ra[:0] + n.ms = n.ma[:0] + n.is = n.ia[:0] + n.ns = n.na[:0] + n.ss = n.sa[:0] + _, d.js = h.(*JsonHandle) + if d.h.InternString { + d.is = make(map[string]string, 32) + } + d.d = h.newDecDriver(d) + d.cr, _ = d.d.(containerStateRecv) + // d.d = h.newDecDriver(decReaderT{true, &d.rb, &d.ri}) + return d +} + +func (d *Decoder) resetCommon() { + d.n.reset() + d.d.reset() + // reset all things which were cached from the Handle, + // but could be changed. + d.mtid, d.stid = 0, 0 + if d.h.MapType != nil { + d.mtid = reflect.ValueOf(d.h.MapType).Pointer() + } + if d.h.SliceType != nil { + d.stid = reflect.ValueOf(d.h.SliceType).Pointer() + } +} + +func (d *Decoder) Reset(r io.Reader) { + d.ri.x = &d.b + // d.s = d.sa[:0] + d.ri.bs.r = r + var ok bool + d.ri.br, ok = r.(decReaderByteScanner) + if !ok { + d.ri.br = &d.ri.bs + } + d.r = &d.ri + d.resetCommon() +} + +func (d *Decoder) ResetBytes(in []byte) { + // d.s = d.sa[:0] + d.rb.reset(in) + d.r = &d.rb + d.resetCommon() +} + +// func (d *Decoder) sendContainerState(c containerState) { +// if d.cr != nil { +// d.cr.sendContainerState(c) +// } +// } + +// Decode decodes the stream from reader and stores the result in the +// value pointed to by v. v cannot be a nil pointer. v can also be +// a reflect.Value of a pointer. +// +// Note that a pointer to a nil interface is not a nil pointer. +// If you do not know what type of stream it is, pass in a pointer to a nil interface. +// We will decode and store a value in that nil interface. +// +// Sample usages: +// // Decoding into a non-nil typed value +// var f float32 +// err = codec.NewDecoder(r, handle).Decode(&f) +// +// // Decoding into nil interface +// var v interface{} +// dec := codec.NewDecoder(r, handle) +// err = dec.Decode(&v) +// +// When decoding into a nil interface{}, we will decode into an appropriate value based +// on the contents of the stream: +// - Numbers are decoded as float64, int64 or uint64. +// - Other values are decoded appropriately depending on the type: +// bool, string, []byte, time.Time, etc +// - Extensions are decoded as RawExt (if no ext function registered for the tag) +// Configurations exist on the Handle to override defaults +// (e.g. for MapType, SliceType and how to decode raw bytes). +// +// When decoding into a non-nil interface{} value, the mode of encoding is based on the +// type of the value. When a value is seen: +// - If an extension is registered for it, call that extension function +// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error +// - Else decode it based on its reflect.Kind +// +// There are some special rules when decoding into containers (slice/array/map/struct). +// Decode will typically use the stream contents to UPDATE the container. +// - A map can be decoded from a stream map, by updating matching keys. +// - A slice can be decoded from a stream array, +// by updating the first n elements, where n is length of the stream. +// - A slice can be decoded from a stream map, by decoding as if +// it contains a sequence of key-value pairs. +// - A struct can be decoded from a stream map, by updating matching fields. +// - A struct can be decoded from a stream array, +// by updating fields as they occur in the struct (by index). +// +// When decoding a stream map or array with length of 0 into a nil map or slice, +// we reset the destination map or slice to a zero-length value. +// +// However, when decoding a stream nil, we reset the destination container +// to its "zero" value (e.g. nil for slice/map, etc). +// +func (d *Decoder) Decode(v interface{}) (err error) { + defer panicToErr(&err) + d.decode(v) + return +} + +// this is not a smart swallow, as it allocates objects and does unnecessary work. +func (d *Decoder) swallowViaHammer() { + var blank interface{} + d.decodeValue(reflect.ValueOf(&blank).Elem(), nil) +} + +func (d *Decoder) swallow() { + // smarter decode that just swallows the content + dd := d.d + if dd.TryDecodeAsNil() { + return + } + cr := d.cr + switch dd.ContainerType() { + case valueTypeMap: + containerLen := dd.ReadMapStart() + clenGtEqualZero := containerLen >= 0 + for j := 0; ; j++ { + if clenGtEqualZero { + if j >= containerLen { + break + } + } else if dd.CheckBreak() { + break + } + if cr != nil { + cr.sendContainerState(containerMapKey) + } + d.swallow() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + d.swallow() + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + case valueTypeArray: + containerLenS := dd.ReadArrayStart() + clenGtEqualZero := containerLenS >= 0 + for j := 0; ; j++ { + if clenGtEqualZero { + if j >= containerLenS { + break + } + } else if dd.CheckBreak() { + break + } + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + d.swallow() + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } + case valueTypeBytes: + dd.DecodeBytes(d.b[:], false, true) + case valueTypeString: + dd.DecodeBytes(d.b[:], true, true) + // dd.DecodeStringAsBytes(d.b[:]) + default: + // these are all primitives, which we can get from decodeNaked + // if RawExt using Value, complete the processing. + dd.DecodeNaked() + if n := &d.n; n.v == valueTypeExt && n.l == nil { + l := len(n.is) + n.is = append(n.is, nil) + v2 := &n.is[l] + d.decode(v2) + n.is = n.is[:l] + } + } +} + +// MustDecode is like Decode, but panics if unable to Decode. +// This provides insight to the code location that triggered the error. +func (d *Decoder) MustDecode(v interface{}) { + d.decode(v) +} + +func (d *Decoder) decode(iv interface{}) { + // if ics, ok := iv.(Selfer); ok { + // ics.CodecDecodeSelf(d) + // return + // } + + if d.d.TryDecodeAsNil() { + switch v := iv.(type) { + case nil: + case *string: + *v = "" + case *bool: + *v = false + case *int: + *v = 0 + case *int8: + *v = 0 + case *int16: + *v = 0 + case *int32: + *v = 0 + case *int64: + *v = 0 + case *uint: + *v = 0 + case *uint8: + *v = 0 + case *uint16: + *v = 0 + case *uint32: + *v = 0 + case *uint64: + *v = 0 + case *float32: + *v = 0 + case *float64: + *v = 0 + case *[]uint8: + *v = nil + case reflect.Value: + if v.Kind() != reflect.Ptr || v.IsNil() { + d.errNotValidPtrValue(v) + } + // d.chkPtrValue(v) + v = v.Elem() + if v.IsValid() { + v.Set(reflect.Zero(v.Type())) + } + default: + rv := reflect.ValueOf(iv) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + d.errNotValidPtrValue(rv) + } + // d.chkPtrValue(rv) + rv = rv.Elem() + if rv.IsValid() { + rv.Set(reflect.Zero(rv.Type())) + } + } + return + } + + switch v := iv.(type) { + case nil: + d.error(cannotDecodeIntoNilErr) + return + + case Selfer: + v.CodecDecodeSelf(d) + + case reflect.Value: + if v.Kind() != reflect.Ptr || v.IsNil() { + d.errNotValidPtrValue(v) + } + // d.chkPtrValue(v) + d.decodeValueNotNil(v.Elem(), nil) + + case *string: + + *v = d.d.DecodeString() + case *bool: + *v = d.d.DecodeBool() + case *int: + *v = int(d.d.DecodeInt(intBitsize)) + case *int8: + *v = int8(d.d.DecodeInt(8)) + case *int16: + *v = int16(d.d.DecodeInt(16)) + case *int32: + *v = int32(d.d.DecodeInt(32)) + case *int64: + *v = d.d.DecodeInt(64) + case *uint: + *v = uint(d.d.DecodeUint(uintBitsize)) + case *uint8: + *v = uint8(d.d.DecodeUint(8)) + case *uint16: + *v = uint16(d.d.DecodeUint(16)) + case *uint32: + *v = uint32(d.d.DecodeUint(32)) + case *uint64: + *v = d.d.DecodeUint(64) + case *float32: + *v = float32(d.d.DecodeFloat(true)) + case *float64: + *v = d.d.DecodeFloat(false) + case *[]uint8: + *v = d.d.DecodeBytes(*v, false, false) + + case *interface{}: + d.decodeValueNotNil(reflect.ValueOf(iv).Elem(), nil) + + default: + if !fastpathDecodeTypeSwitch(iv, d) { + d.decodeI(iv, true, false, false, false) + } + } +} + +func (d *Decoder) preDecodeValue(rv reflect.Value, tryNil bool) (rv2 reflect.Value, proceed bool) { + if tryNil && d.d.TryDecodeAsNil() { + // No need to check if a ptr, recursively, to determine + // whether to set value to nil. + // Just always set value to its zero type. + if rv.IsValid() { // rv.CanSet() // always settable, except it's invalid + rv.Set(reflect.Zero(rv.Type())) + } + return + } + + // If stream is not containing a nil value, then we can deref to the base + // non-pointer value, and decode into that. + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + rv = rv.Elem() + } + return rv, true +} + +func (d *Decoder) decodeI(iv interface{}, checkPtr, tryNil, checkFastpath, checkCodecSelfer bool) { + rv := reflect.ValueOf(iv) + if checkPtr { + if rv.Kind() != reflect.Ptr || rv.IsNil() { + d.errNotValidPtrValue(rv) + } + // d.chkPtrValue(rv) + } + rv, proceed := d.preDecodeValue(rv, tryNil) + if proceed { + fn := d.getDecFn(rv.Type(), checkFastpath, checkCodecSelfer) + fn.f(&fn.i, rv) + } +} + +func (d *Decoder) decodeValue(rv reflect.Value, fn *decFn) { + if rv, proceed := d.preDecodeValue(rv, true); proceed { + if fn == nil { + fn = d.getDecFn(rv.Type(), true, true) + } + fn.f(&fn.i, rv) + } +} + +func (d *Decoder) decodeValueNotNil(rv reflect.Value, fn *decFn) { + if rv, proceed := d.preDecodeValue(rv, false); proceed { + if fn == nil { + fn = d.getDecFn(rv.Type(), true, true) + } + fn.f(&fn.i, rv) + } +} + +func (d *Decoder) getDecFn(rt reflect.Type, checkFastpath, checkCodecSelfer bool) (fn *decFn) { + rtid := reflect.ValueOf(rt).Pointer() + + // retrieve or register a focus'ed function for this type + // to eliminate need to do the retrieval multiple times + + // if d.f == nil && d.s == nil { debugf("---->Creating new dec f map for type: %v\n", rt) } + var ok bool + if useMapForCodecCache { + fn, ok = d.f[rtid] + } else { + for i := range d.s { + v := &(d.s[i]) + if v.rtid == rtid { + fn, ok = &(v.fn), true + break + } + } + } + if ok { + return + } + + if useMapForCodecCache { + if d.f == nil { + d.f = make(map[uintptr]*decFn, initCollectionCap) + } + fn = new(decFn) + d.f[rtid] = fn + } else { + if d.s == nil { + d.s = make([]decRtidFn, 0, initCollectionCap) + } + d.s = append(d.s, decRtidFn{rtid: rtid}) + fn = &(d.s[len(d.s)-1]).fn + } + + // debugf("\tCreating new dec fn for type: %v\n", rt) + ti := d.h.getTypeInfo(rtid, rt) + fi := &(fn.i) + fi.d = d + fi.ti = ti + + // An extension can be registered for any type, regardless of the Kind + // (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc. + // + // We can't check if it's an extension byte here first, because the user may have + // registered a pointer or non-pointer type, meaning we may have to recurse first + // before matching a mapped type, even though the extension byte is already detected. + // + // NOTE: if decoding into a nil interface{}, we return a non-nil + // value except even if the container registers a length of 0. + if checkCodecSelfer && ti.cs { + fn.f = (*decFnInfo).selferUnmarshal + } else if rtid == rawExtTypId { + fn.f = (*decFnInfo).rawExt + } else if d.d.IsBuiltinType(rtid) { + fn.f = (*decFnInfo).builtin + } else if xfFn := d.h.getExt(rtid); xfFn != nil { + fi.xfTag, fi.xfFn = xfFn.tag, xfFn.ext + fn.f = (*decFnInfo).ext + } else if supportMarshalInterfaces && d.be && ti.bunm { + fn.f = (*decFnInfo).binaryUnmarshal + } else if supportMarshalInterfaces && !d.be && d.js && ti.junm { + //If JSON, we should check JSONUnmarshal before textUnmarshal + fn.f = (*decFnInfo).jsonUnmarshal + } else if supportMarshalInterfaces && !d.be && ti.tunm { + fn.f = (*decFnInfo).textUnmarshal + } else { + rk := rt.Kind() + if fastpathEnabled && checkFastpath && (rk == reflect.Map || rk == reflect.Slice) { + if rt.PkgPath() == "" { + if idx := fastpathAV.index(rtid); idx != -1 { + fn.f = fastpathAV[idx].decfn + } + } else { + // use mapping for underlying type if there + ok = false + var rtu reflect.Type + if rk == reflect.Map { + rtu = reflect.MapOf(rt.Key(), rt.Elem()) + } else { + rtu = reflect.SliceOf(rt.Elem()) + } + rtuid := reflect.ValueOf(rtu).Pointer() + if idx := fastpathAV.index(rtuid); idx != -1 { + xfnf := fastpathAV[idx].decfn + xrt := fastpathAV[idx].rt + fn.f = func(xf *decFnInfo, xrv reflect.Value) { + // xfnf(xf, xrv.Convert(xrt)) + xfnf(xf, xrv.Addr().Convert(reflect.PtrTo(xrt)).Elem()) + } + } + } + } + if fn.f == nil { + switch rk { + case reflect.String: + fn.f = (*decFnInfo).kString + case reflect.Bool: + fn.f = (*decFnInfo).kBool + case reflect.Int: + fn.f = (*decFnInfo).kInt + case reflect.Int64: + fn.f = (*decFnInfo).kInt64 + case reflect.Int32: + fn.f = (*decFnInfo).kInt32 + case reflect.Int8: + fn.f = (*decFnInfo).kInt8 + case reflect.Int16: + fn.f = (*decFnInfo).kInt16 + case reflect.Float32: + fn.f = (*decFnInfo).kFloat32 + case reflect.Float64: + fn.f = (*decFnInfo).kFloat64 + case reflect.Uint8: + fn.f = (*decFnInfo).kUint8 + case reflect.Uint64: + fn.f = (*decFnInfo).kUint64 + case reflect.Uint: + fn.f = (*decFnInfo).kUint + case reflect.Uint32: + fn.f = (*decFnInfo).kUint32 + case reflect.Uint16: + fn.f = (*decFnInfo).kUint16 + // case reflect.Ptr: + // fn.f = (*decFnInfo).kPtr + case reflect.Uintptr: + fn.f = (*decFnInfo).kUintptr + case reflect.Interface: + fn.f = (*decFnInfo).kInterface + case reflect.Struct: + fn.f = (*decFnInfo).kStruct + case reflect.Chan: + fi.seq = seqTypeChan + fn.f = (*decFnInfo).kSlice + case reflect.Slice: + fi.seq = seqTypeSlice + fn.f = (*decFnInfo).kSlice + case reflect.Array: + fi.seq = seqTypeArray + fn.f = (*decFnInfo).kArray + case reflect.Map: + fn.f = (*decFnInfo).kMap + default: + fn.f = (*decFnInfo).kErr + } + } + } + + return +} + +func (d *Decoder) structFieldNotFound(index int, rvkencname string) { + if d.h.ErrorIfNoField { + if index >= 0 { + d.errorf("no matching struct field found when decoding stream array at index %v", index) + return + } else if rvkencname != "" { + d.errorf("no matching struct field found when decoding stream map with key %s", rvkencname) + return + } + } + d.swallow() +} + +func (d *Decoder) arrayCannotExpand(sliceLen, streamLen int) { + if d.h.ErrorIfNoArrayExpand { + d.errorf("cannot expand array len during decode from %v to %v", sliceLen, streamLen) + } +} + +func (d *Decoder) chkPtrValue(rv reflect.Value) { + // We can only decode into a non-nil pointer + if rv.Kind() == reflect.Ptr && !rv.IsNil() { + return + } + d.errNotValidPtrValue(rv) +} + +func (d *Decoder) errNotValidPtrValue(rv reflect.Value) { + if !rv.IsValid() { + d.error(cannotDecodeIntoNilErr) + return + } + if !rv.CanInterface() { + d.errorf("cannot decode into a value without an interface: %v", rv) + return + } + rvi := rv.Interface() + d.errorf("cannot decode into non-pointer or nil pointer. Got: %v, %T, %v", rv.Kind(), rvi, rvi) +} + +func (d *Decoder) error(err error) { + panic(err) +} + +func (d *Decoder) errorf(format string, params ...interface{}) { + params2 := make([]interface{}, len(params)+1) + params2[0] = d.r.numread() + copy(params2[1:], params) + err := fmt.Errorf("[pos %d]: "+format, params2...) + panic(err) +} + +func (d *Decoder) string(v []byte) (s string) { + if d.is != nil { + s, ok := d.is[string(v)] // no allocation here. + if !ok { + s = string(v) + d.is[s] = s + } + return s + } + return string(v) // don't return stringView, as we need a real string here. +} + +func (d *Decoder) intern(s string) { + if d.is != nil { + d.is[s] = s + } +} + +// nextValueBytes returns the next value in the stream as a set of bytes. +func (d *Decoder) nextValueBytes() []byte { + d.d.uncacheRead() + d.r.track() + d.swallow() + return d.r.stopTrack() +} + +// -------------------------------------------------- + +// decSliceHelper assists when decoding into a slice, from a map or an array in the stream. +// A slice can be set from a map or array in stream. This supports the MapBySlice interface. +type decSliceHelper struct { + d *Decoder + // ct valueType + array bool +} + +func (d *Decoder) decSliceHelperStart() (x decSliceHelper, clen int) { + dd := d.d + ctyp := dd.ContainerType() + if ctyp == valueTypeArray { + x.array = true + clen = dd.ReadArrayStart() + } else if ctyp == valueTypeMap { + clen = dd.ReadMapStart() * 2 + } else { + d.errorf("only encoded map or array can be decoded into a slice (%d)", ctyp) + } + // x.ct = ctyp + x.d = d + return +} + +func (x decSliceHelper) End() { + cr := x.d.cr + if cr == nil { + return + } + if x.array { + cr.sendContainerState(containerArrayEnd) + } else { + cr.sendContainerState(containerMapEnd) + } +} + +func (x decSliceHelper) ElemContainerState(index int) { + cr := x.d.cr + if cr == nil { + return + } + if x.array { + cr.sendContainerState(containerArrayElem) + } else { + if index%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } +} + +func decByteSlice(r decReader, clen int, bs []byte) (bsOut []byte) { + if clen == 0 { + return zeroByteSlice + } + if len(bs) == clen { + bsOut = bs + } else if cap(bs) >= clen { + bsOut = bs[:clen] + } else { + bsOut = make([]byte, clen) + } + r.readb(bsOut) + return +} + +func detachZeroCopyBytes(isBytesReader bool, dest []byte, in []byte) (out []byte) { + if xlen := len(in); xlen > 0 { + if isBytesReader || xlen <= scratchByteArrayLen { + if cap(dest) >= xlen { + out = dest[:xlen] + } else { + out = make([]byte, xlen) + } + copy(out, in) + return + } + } + return in +} + +// decInferLen will infer a sensible length, given the following: +// - clen: length wanted. +// - maxlen: max length to be returned. +// if <= 0, it is unset, and we infer it based on the unit size +// - unit: number of bytes for each element of the collection +func decInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) { + // handle when maxlen is not set i.e. <= 0 + if clen <= 0 { + return + } + if maxlen <= 0 { + // no maxlen defined. Use maximum of 256K memory, with a floor of 4K items. + // maxlen = 256 * 1024 / unit + // if maxlen < (4 * 1024) { + // maxlen = 4 * 1024 + // } + if unit < (256 / 4) { + maxlen = 256 * 1024 / unit + } else { + maxlen = 4 * 1024 + } + } + if clen > maxlen { + rvlen = maxlen + truncated = true + } else { + rvlen = clen + } + return + // if clen <= 0 { + // rvlen = 0 + // } else if maxlen > 0 && clen > maxlen { + // rvlen = maxlen + // truncated = true + // } else { + // rvlen = clen + // } + // return +} + +// // implement overall decReader wrapping both, for possible use inline: +// type decReaderT struct { +// bytes bool +// rb *bytesDecReader +// ri *ioDecReader +// } +// +// // implement *Decoder as a decReader. +// // Using decReaderT (defined just above) caused performance degradation +// // possibly because of constant copying the value, +// // and some value->interface conversion causing allocation. +// func (d *Decoder) unreadn1() { +// if d.bytes { +// d.rb.unreadn1() +// } else { +// d.ri.unreadn1() +// } +// } +// ... for other methods of decReader. +// Testing showed that performance improvement was negligible. diff --git a/vendor/github.com/ugorji/go/codec/encode.go b/vendor/github.com/ugorji/go/codec/encode.go new file mode 100644 index 000000000..a874c744b --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/encode.go @@ -0,0 +1,1419 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "encoding" + "fmt" + "io" + "reflect" + "sort" + "sync" +) + +const ( + defEncByteBufSize = 1 << 6 // 4:16, 6:64, 8:256, 10:1024 +) + +// AsSymbolFlag defines what should be encoded as symbols. +type AsSymbolFlag uint8 + +const ( + // AsSymbolDefault is default. + // Currently, this means only encode struct field names as symbols. + // The default is subject to change. + AsSymbolDefault AsSymbolFlag = iota + + // AsSymbolAll means encode anything which could be a symbol as a symbol. + AsSymbolAll = 0xfe + + // AsSymbolNone means do not encode anything as a symbol. + AsSymbolNone = 1 << iota + + // AsSymbolMapStringKeys means encode keys in map[string]XXX as symbols. + AsSymbolMapStringKeysFlag + + // AsSymbolStructFieldName means encode struct field names as symbols. + AsSymbolStructFieldNameFlag +) + +// encWriter abstracts writing to a byte array or to an io.Writer. +type encWriter interface { + writeb([]byte) + writestr(string) + writen1(byte) + writen2(byte, byte) + atEndOfEncode() +} + +// encDriver abstracts the actual codec (binc vs msgpack, etc) +type encDriver interface { + IsBuiltinType(rt uintptr) bool + EncodeBuiltin(rt uintptr, v interface{}) + EncodeNil() + EncodeInt(i int64) + EncodeUint(i uint64) + EncodeBool(b bool) + EncodeFloat32(f float32) + EncodeFloat64(f float64) + // encodeExtPreamble(xtag byte, length int) + EncodeRawExt(re *RawExt, e *Encoder) + EncodeExt(v interface{}, xtag uint64, ext Ext, e *Encoder) + EncodeArrayStart(length int) + EncodeMapStart(length int) + EncodeString(c charEncoding, v string) + EncodeSymbol(v string) + EncodeStringBytes(c charEncoding, v []byte) + //TODO + //encBignum(f *big.Int) + //encStringRunes(c charEncoding, v []rune) + + reset() +} + +type encDriverAsis interface { + EncodeAsis(v []byte) +} + +type encNoSeparator struct{} + +func (_ encNoSeparator) EncodeEnd() {} + +type ioEncWriterWriter interface { + WriteByte(c byte) error + WriteString(s string) (n int, err error) + Write(p []byte) (n int, err error) +} + +type ioEncStringWriter interface { + WriteString(s string) (n int, err error) +} + +type EncodeOptions struct { + // Encode a struct as an array, and not as a map + StructToArray bool + + // Canonical representation means that encoding a value will always result in the same + // sequence of bytes. + // + // This only affects maps, as the iteration order for maps is random. + // + // The implementation MAY use the natural sort order for the map keys if possible: + // + // - If there is a natural sort order (ie for number, bool, string or []byte keys), + // then the map keys are first sorted in natural order and then written + // with corresponding map values to the strema. + // - If there is no natural sort order, then the map keys will first be + // encoded into []byte, and then sorted, + // before writing the sorted keys and the corresponding map values to the stream. + // + Canonical bool + + // CheckCircularRef controls whether we check for circular references + // and error fast during an encode. + // + // If enabled, an error is received if a pointer to a struct + // references itself either directly or through one of its fields (iteratively). + // + // This is opt-in, as there may be a performance hit to checking circular references. + CheckCircularRef bool + + // AsSymbols defines what should be encoded as symbols. + // + // Encoding as symbols can reduce the encoded size significantly. + // + // However, during decoding, each string to be encoded as a symbol must + // be checked to see if it has been seen before. Consequently, encoding time + // will increase if using symbols, because string comparisons has a clear cost. + // + // Sample values: + // AsSymbolNone + // AsSymbolAll + // AsSymbolMapStringKeys + // AsSymbolMapStringKeysFlag | AsSymbolStructFieldNameFlag + AsSymbols AsSymbolFlag +} + +// --------------------------------------------- + +type simpleIoEncWriterWriter struct { + w io.Writer + bw io.ByteWriter + sw ioEncStringWriter +} + +func (o *simpleIoEncWriterWriter) WriteByte(c byte) (err error) { + if o.bw != nil { + return o.bw.WriteByte(c) + } + _, err = o.w.Write([]byte{c}) + return +} + +func (o *simpleIoEncWriterWriter) WriteString(s string) (n int, err error) { + if o.sw != nil { + return o.sw.WriteString(s) + } + // return o.w.Write([]byte(s)) + return o.w.Write(bytesView(s)) +} + +func (o *simpleIoEncWriterWriter) Write(p []byte) (n int, err error) { + return o.w.Write(p) +} + +// ---------------------------------------- + +// ioEncWriter implements encWriter and can write to an io.Writer implementation +type ioEncWriter struct { + w ioEncWriterWriter + s simpleIoEncWriterWriter + // x [8]byte // temp byte array re-used internally for efficiency +} + +func (z *ioEncWriter) writeb(bs []byte) { + if len(bs) == 0 { + return + } + n, err := z.w.Write(bs) + if err != nil { + panic(err) + } + if n != len(bs) { + panic(fmt.Errorf("incorrect num bytes written. Expecting: %v, Wrote: %v", len(bs), n)) + } +} + +func (z *ioEncWriter) writestr(s string) { + n, err := z.w.WriteString(s) + if err != nil { + panic(err) + } + if n != len(s) { + panic(fmt.Errorf("incorrect num bytes written. Expecting: %v, Wrote: %v", len(s), n)) + } +} + +func (z *ioEncWriter) writen1(b byte) { + if err := z.w.WriteByte(b); err != nil { + panic(err) + } +} + +func (z *ioEncWriter) writen2(b1 byte, b2 byte) { + z.writen1(b1) + z.writen1(b2) +} + +func (z *ioEncWriter) atEndOfEncode() {} + +// ---------------------------------------- + +// bytesEncWriter implements encWriter and can write to an byte slice. +// It is used by Marshal function. +type bytesEncWriter struct { + b []byte + c int // cursor + out *[]byte // write out on atEndOfEncode +} + +func (z *bytesEncWriter) writeb(s []byte) { + if len(s) > 0 { + c := z.grow(len(s)) + copy(z.b[c:], s) + } +} + +func (z *bytesEncWriter) writestr(s string) { + if len(s) > 0 { + c := z.grow(len(s)) + copy(z.b[c:], s) + } +} + +func (z *bytesEncWriter) writen1(b1 byte) { + c := z.grow(1) + z.b[c] = b1 +} + +func (z *bytesEncWriter) writen2(b1 byte, b2 byte) { + c := z.grow(2) + z.b[c] = b1 + z.b[c+1] = b2 +} + +func (z *bytesEncWriter) atEndOfEncode() { + *(z.out) = z.b[:z.c] +} + +func (z *bytesEncWriter) grow(n int) (oldcursor int) { + oldcursor = z.c + z.c = oldcursor + n + if z.c > len(z.b) { + if z.c > cap(z.b) { + // appendslice logic (if cap < 1024, *2, else *1.25): more expensive. many copy calls. + // bytes.Buffer model (2*cap + n): much better + // bs := make([]byte, 2*cap(z.b)+n) + bs := make([]byte, growCap(cap(z.b), 1, n)) + copy(bs, z.b[:oldcursor]) + z.b = bs + } else { + z.b = z.b[:cap(z.b)] + } + } + return +} + +// --------------------------------------------- + +type encFnInfo struct { + e *Encoder + ti *typeInfo + xfFn Ext + xfTag uint64 + seq seqType +} + +func (f *encFnInfo) builtin(rv reflect.Value) { + f.e.e.EncodeBuiltin(f.ti.rtid, rv.Interface()) +} + +func (f *encFnInfo) rawExt(rv reflect.Value) { + // rev := rv.Interface().(RawExt) + // f.e.e.EncodeRawExt(&rev, f.e) + var re *RawExt + if rv.CanAddr() { + re = rv.Addr().Interface().(*RawExt) + } else { + rev := rv.Interface().(RawExt) + re = &rev + } + f.e.e.EncodeRawExt(re, f.e) +} + +func (f *encFnInfo) ext(rv reflect.Value) { + // if this is a struct|array and it was addressable, then pass the address directly (not the value) + if k := rv.Kind(); (k == reflect.Struct || k == reflect.Array) && rv.CanAddr() { + rv = rv.Addr() + } + f.e.e.EncodeExt(rv.Interface(), f.xfTag, f.xfFn, f.e) +} + +func (f *encFnInfo) getValueForMarshalInterface(rv reflect.Value, indir int8) (v interface{}, proceed bool) { + if indir == 0 { + v = rv.Interface() + } else if indir == -1 { + // If a non-pointer was passed to Encode(), then that value is not addressable. + // Take addr if addresable, else copy value to an addressable value. + if rv.CanAddr() { + v = rv.Addr().Interface() + } else { + rv2 := reflect.New(rv.Type()) + rv2.Elem().Set(rv) + v = rv2.Interface() + // fmt.Printf("rv.Type: %v, rv2.Type: %v, v: %v\n", rv.Type(), rv2.Type(), v) + } + } else { + for j := int8(0); j < indir; j++ { + if rv.IsNil() { + f.e.e.EncodeNil() + return + } + rv = rv.Elem() + } + v = rv.Interface() + } + return v, true +} + +func (f *encFnInfo) selferMarshal(rv reflect.Value) { + if v, proceed := f.getValueForMarshalInterface(rv, f.ti.csIndir); proceed { + v.(Selfer).CodecEncodeSelf(f.e) + } +} + +func (f *encFnInfo) binaryMarshal(rv reflect.Value) { + if v, proceed := f.getValueForMarshalInterface(rv, f.ti.bmIndir); proceed { + bs, fnerr := v.(encoding.BinaryMarshaler).MarshalBinary() + f.e.marshal(bs, fnerr, false, c_RAW) + } +} + +func (f *encFnInfo) textMarshal(rv reflect.Value) { + if v, proceed := f.getValueForMarshalInterface(rv, f.ti.tmIndir); proceed { + // debugf(">>>> encoding.TextMarshaler: %T", rv.Interface()) + bs, fnerr := v.(encoding.TextMarshaler).MarshalText() + f.e.marshal(bs, fnerr, false, c_UTF8) + } +} + +func (f *encFnInfo) jsonMarshal(rv reflect.Value) { + if v, proceed := f.getValueForMarshalInterface(rv, f.ti.jmIndir); proceed { + bs, fnerr := v.(jsonMarshaler).MarshalJSON() + f.e.marshal(bs, fnerr, true, c_UTF8) + } +} + +func (f *encFnInfo) kBool(rv reflect.Value) { + f.e.e.EncodeBool(rv.Bool()) +} + +func (f *encFnInfo) kString(rv reflect.Value) { + f.e.e.EncodeString(c_UTF8, rv.String()) +} + +func (f *encFnInfo) kFloat64(rv reflect.Value) { + f.e.e.EncodeFloat64(rv.Float()) +} + +func (f *encFnInfo) kFloat32(rv reflect.Value) { + f.e.e.EncodeFloat32(float32(rv.Float())) +} + +func (f *encFnInfo) kInt(rv reflect.Value) { + f.e.e.EncodeInt(rv.Int()) +} + +func (f *encFnInfo) kUint(rv reflect.Value) { + f.e.e.EncodeUint(rv.Uint()) +} + +func (f *encFnInfo) kInvalid(rv reflect.Value) { + f.e.e.EncodeNil() +} + +func (f *encFnInfo) kErr(rv reflect.Value) { + f.e.errorf("unsupported kind %s, for %#v", rv.Kind(), rv) +} + +func (f *encFnInfo) kSlice(rv reflect.Value) { + ti := f.ti + // array may be non-addressable, so we have to manage with care + // (don't call rv.Bytes, rv.Slice, etc). + // E.g. type struct S{B [2]byte}; + // Encode(S{}) will bomb on "panic: slice of unaddressable array". + e := f.e + if f.seq != seqTypeArray { + if rv.IsNil() { + e.e.EncodeNil() + return + } + // If in this method, then there was no extension function defined. + // So it's okay to treat as []byte. + if ti.rtid == uint8SliceTypId { + e.e.EncodeStringBytes(c_RAW, rv.Bytes()) + return + } + } + cr := e.cr + rtelem := ti.rt.Elem() + l := rv.Len() + if ti.rtid == uint8SliceTypId || rtelem.Kind() == reflect.Uint8 { + switch f.seq { + case seqTypeArray: + // if l == 0 { e.e.encodeStringBytes(c_RAW, nil) } else + if rv.CanAddr() { + e.e.EncodeStringBytes(c_RAW, rv.Slice(0, l).Bytes()) + } else { + var bs []byte + if l <= cap(e.b) { + bs = e.b[:l] + } else { + bs = make([]byte, l) + } + reflect.Copy(reflect.ValueOf(bs), rv) + // TODO: Test that reflect.Copy works instead of manual one-by-one + // for i := 0; i < l; i++ { + // bs[i] = byte(rv.Index(i).Uint()) + // } + e.e.EncodeStringBytes(c_RAW, bs) + } + case seqTypeSlice: + e.e.EncodeStringBytes(c_RAW, rv.Bytes()) + case seqTypeChan: + bs := e.b[:0] + // do not use range, so that the number of elements encoded + // does not change, and encoding does not hang waiting on someone to close chan. + // for b := range rv.Interface().(<-chan byte) { + // bs = append(bs, b) + // } + ch := rv.Interface().(<-chan byte) + for i := 0; i < l; i++ { + bs = append(bs, <-ch) + } + e.e.EncodeStringBytes(c_RAW, bs) + } + return + } + + if ti.mbs { + if l%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", l) + return + } + e.e.EncodeMapStart(l / 2) + } else { + e.e.EncodeArrayStart(l) + } + + if l > 0 { + for rtelem.Kind() == reflect.Ptr { + rtelem = rtelem.Elem() + } + // if kind is reflect.Interface, do not pre-determine the + // encoding type, because preEncodeValue may break it down to + // a concrete type and kInterface will bomb. + var fn *encFn + if rtelem.Kind() != reflect.Interface { + rtelemid := reflect.ValueOf(rtelem).Pointer() + fn = e.getEncFn(rtelemid, rtelem, true, true) + } + // TODO: Consider perf implication of encoding odd index values as symbols if type is string + for j := 0; j < l; j++ { + if cr != nil { + if ti.mbs { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } else { + cr.sendContainerState(containerArrayElem) + } + } + if f.seq == seqTypeChan { + if rv2, ok2 := rv.Recv(); ok2 { + e.encodeValue(rv2, fn) + } else { + e.encode(nil) // WE HAVE TO DO SOMETHING, so nil if nothing received. + } + } else { + e.encodeValue(rv.Index(j), fn) + } + } + } + + if cr != nil { + if ti.mbs { + cr.sendContainerState(containerMapEnd) + } else { + cr.sendContainerState(containerArrayEnd) + } + } +} + +func (f *encFnInfo) kStruct(rv reflect.Value) { + fti := f.ti + e := f.e + cr := e.cr + tisfi := fti.sfip + toMap := !(fti.toArray || e.h.StructToArray) + newlen := len(fti.sfi) + + // Use sync.Pool to reduce allocating slices unnecessarily. + // The cost of sync.Pool is less than the cost of new allocation. + pool, poolv, fkvs := encStructPoolGet(newlen) + + // if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct) + if toMap { + tisfi = fti.sfi + } + newlen = 0 + var kv stringRv + for _, si := range tisfi { + kv.r = si.field(rv, false) + if toMap { + if si.omitEmpty && isEmptyValue(kv.r) { + continue + } + kv.v = si.encName + } else { + // use the zero value. + // if a reference or struct, set to nil (so you do not output too much) + if si.omitEmpty && isEmptyValue(kv.r) { + switch kv.r.Kind() { + case reflect.Struct, reflect.Interface, reflect.Ptr, reflect.Array, + reflect.Map, reflect.Slice: + kv.r = reflect.Value{} //encode as nil + } + } + } + fkvs[newlen] = kv + newlen++ + } + + // debugf(">>>> kStruct: newlen: %v", newlen) + // sep := !e.be + ee := e.e //don't dereference everytime + + if toMap { + ee.EncodeMapStart(newlen) + // asSymbols := e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0 + asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0 + for j := 0; j < newlen; j++ { + kv = fkvs[j] + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(kv.v) + } else { + ee.EncodeString(c_UTF8, kv.v) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(kv.r, nil) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + } else { + ee.EncodeArrayStart(newlen) + for j := 0; j < newlen; j++ { + kv = fkvs[j] + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + e.encodeValue(kv.r, nil) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } + } + + // do not use defer. Instead, use explicit pool return at end of function. + // defer has a cost we are trying to avoid. + // If there is a panic and these slices are not returned, it is ok. + if pool != nil { + pool.Put(poolv) + } +} + +// func (f *encFnInfo) kPtr(rv reflect.Value) { +// debugf(">>>>>>> ??? encode kPtr called - shouldn't get called") +// if rv.IsNil() { +// f.e.e.encodeNil() +// return +// } +// f.e.encodeValue(rv.Elem()) +// } + +// func (f *encFnInfo) kInterface(rv reflect.Value) { +// println("kInterface called") +// debug.PrintStack() +// if rv.IsNil() { +// f.e.e.EncodeNil() +// return +// } +// f.e.encodeValue(rv.Elem(), nil) +// } + +func (f *encFnInfo) kMap(rv reflect.Value) { + ee := f.e.e + if rv.IsNil() { + ee.EncodeNil() + return + } + + l := rv.Len() + ee.EncodeMapStart(l) + e := f.e + cr := e.cr + if l == 0 { + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return + } + var asSymbols bool + // determine the underlying key and val encFn's for the map. + // This eliminates some work which is done for each loop iteration i.e. + // rv.Type(), ref.ValueOf(rt).Pointer(), then check map/list for fn. + // + // However, if kind is reflect.Interface, do not pre-determine the + // encoding type, because preEncodeValue may break it down to + // a concrete type and kInterface will bomb. + var keyFn, valFn *encFn + ti := f.ti + rtkey := ti.rt.Key() + rtval := ti.rt.Elem() + rtkeyid := reflect.ValueOf(rtkey).Pointer() + // keyTypeIsString := f.ti.rt.Key().Kind() == reflect.String + var keyTypeIsString = rtkeyid == stringTypId + if keyTypeIsString { + asSymbols = e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + } else { + for rtkey.Kind() == reflect.Ptr { + rtkey = rtkey.Elem() + } + if rtkey.Kind() != reflect.Interface { + rtkeyid = reflect.ValueOf(rtkey).Pointer() + keyFn = e.getEncFn(rtkeyid, rtkey, true, true) + } + } + for rtval.Kind() == reflect.Ptr { + rtval = rtval.Elem() + } + if rtval.Kind() != reflect.Interface { + rtvalid := reflect.ValueOf(rtval).Pointer() + valFn = e.getEncFn(rtvalid, rtval, true, true) + } + mks := rv.MapKeys() + // for j, lmks := 0, len(mks); j < lmks; j++ { + + if e.h.Canonical { + e.kMapCanonical(rtkeyid, rtkey, rv, mks, valFn, asSymbols) + } else { + for j := range mks { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if keyTypeIsString { + if asSymbols { + ee.EncodeSymbol(mks[j].String()) + } else { + ee.EncodeString(c_UTF8, mks[j].String()) + } + } else { + e.encodeValue(mks[j], keyFn) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mks[j]), valFn) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (e *Encoder) kMapCanonical(rtkeyid uintptr, rtkey reflect.Type, rv reflect.Value, mks []reflect.Value, valFn *encFn, asSymbols bool) { + ee := e.e + cr := e.cr + // we previously did out-of-band if an extension was registered. + // This is not necessary, as the natural kind is sufficient for ordering. + + if rtkeyid == uint8SliceTypId { + mksv := make([]bytesRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Bytes() + } + sort.Sort(bytesRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeStringBytes(c_RAW, mksv[i].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + } else { + switch rtkey.Kind() { + case reflect.Bool: + mksv := make([]boolRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Bool() + } + sort.Sort(boolRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(mksv[i].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + case reflect.String: + mksv := make([]stringRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.String() + } + sort.Sort(stringRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(mksv[i].v) + } else { + ee.EncodeString(c_UTF8, mksv[i].v) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr: + mksv := make([]uintRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Uint() + } + sort.Sort(uintRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(mksv[i].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + mksv := make([]intRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Int() + } + sort.Sort(intRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(mksv[i].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + case reflect.Float32: + mksv := make([]floatRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Float() + } + sort.Sort(floatRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(mksv[i].v)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + case reflect.Float64: + mksv := make([]floatRv, len(mks)) + for i, k := range mks { + v := &mksv[i] + v.r = k + v.v = k.Float() + } + sort.Sort(floatRvSlice(mksv)) + for i := range mksv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(mksv[i].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksv[i].r), valFn) + } + default: + // out-of-band + // first encode each key to a []byte first, then sort them, then record + var mksv []byte = make([]byte, 0, len(mks)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + mksbv := make([]bytesRv, len(mks)) + for i, k := range mks { + v := &mksbv[i] + l := len(mksv) + e2.MustEncode(k) + v.r = k + v.v = mksv[l:] + // fmt.Printf(">>>>> %s\n", mksv[l:]) + } + sort.Sort(bytesRvSlice(mksbv)) + for j := range mksbv { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(mksbv[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encodeValue(rv.MapIndex(mksbv[j].r), valFn) + } + } + } +} + +// -------------------------------------------------- + +// encFn encapsulates the captured variables and the encode function. +// This way, we only do some calculations one times, and pass to the +// code block that should be called (encapsulated in a function) +// instead of executing the checks every time. +type encFn struct { + i encFnInfo + f func(*encFnInfo, reflect.Value) +} + +// -------------------------------------------------- + +type encRtidFn struct { + rtid uintptr + fn encFn +} + +// An Encoder writes an object to an output stream in the codec format. +type Encoder struct { + // hopefully, reduce derefencing cost by laying the encWriter inside the Encoder + e encDriver + // NOTE: Encoder shouldn't call it's write methods, + // as the handler MAY need to do some coordination. + w encWriter + s []encRtidFn + ci set + be bool // is binary encoding + js bool // is json handle + + wi ioEncWriter + wb bytesEncWriter + + h *BasicHandle + hh Handle + + cr containerStateRecv + as encDriverAsis + + f map[uintptr]*encFn + b [scratchByteArrayLen]byte +} + +// NewEncoder returns an Encoder for encoding into an io.Writer. +// +// For efficiency, Users are encouraged to pass in a memory buffered writer +// (eg bufio.Writer, bytes.Buffer). +func NewEncoder(w io.Writer, h Handle) *Encoder { + e := newEncoder(h) + e.Reset(w) + return e +} + +// NewEncoderBytes returns an encoder for encoding directly and efficiently +// into a byte slice, using zero-copying to temporary slices. +// +// It will potentially replace the output byte slice pointed to. +// After encoding, the out parameter contains the encoded contents. +func NewEncoderBytes(out *[]byte, h Handle) *Encoder { + e := newEncoder(h) + e.ResetBytes(out) + return e +} + +func newEncoder(h Handle) *Encoder { + e := &Encoder{hh: h, h: h.getBasicHandle(), be: h.isBinary()} + _, e.js = h.(*JsonHandle) + e.e = h.newEncDriver(e) + e.as, _ = e.e.(encDriverAsis) + e.cr, _ = e.e.(containerStateRecv) + return e +} + +// Reset the Encoder with a new output stream. +// +// This accomodates using the state of the Encoder, +// where it has "cached" information about sub-engines. +func (e *Encoder) Reset(w io.Writer) { + ww, ok := w.(ioEncWriterWriter) + if ok { + e.wi.w = ww + } else { + sww := &e.wi.s + sww.w = w + sww.bw, _ = w.(io.ByteWriter) + sww.sw, _ = w.(ioEncStringWriter) + e.wi.w = sww + //ww = bufio.NewWriterSize(w, defEncByteBufSize) + } + e.w = &e.wi + e.e.reset() +} + +func (e *Encoder) ResetBytes(out *[]byte) { + in := *out + if in == nil { + in = make([]byte, defEncByteBufSize) + } + e.wb.b, e.wb.out, e.wb.c = in, out, 0 + e.w = &e.wb + e.e.reset() +} + +// func (e *Encoder) sendContainerState(c containerState) { +// if e.cr != nil { +// e.cr.sendContainerState(c) +// } +// } + +// Encode writes an object into a stream. +// +// Encoding can be configured via the struct tag for the fields. +// The "codec" key in struct field's tag value is the key name, +// followed by an optional comma and options. +// Note that the "json" key is used in the absence of the "codec" key. +// +// To set an option on all fields (e.g. omitempty on all fields), you +// can create a field called _struct, and set flags on it. +// +// Struct values "usually" encode as maps. Each exported struct field is encoded unless: +// - the field's tag is "-", OR +// - the field is empty (empty or the zero value) and its tag specifies the "omitempty" option. +// +// When encoding as a map, the first string in the tag (before the comma) +// is the map key string to use when encoding. +// +// However, struct values may encode as arrays. This happens when: +// - StructToArray Encode option is set, OR +// - the tag on the _struct field sets the "toarray" option +// +// Values with types that implement MapBySlice are encoded as stream maps. +// +// The empty values (for omitempty option) are false, 0, any nil pointer +// or interface value, and any array, slice, map, or string of length zero. +// +// Anonymous fields are encoded inline except: +// - the struct tag specifies a replacement name (first value) +// - the field is of an interface type +// +// Examples: +// +// // NOTE: 'json:' can be used as struct tag key, in place 'codec:' below. +// type MyStruct struct { +// _struct bool `codec:",omitempty"` //set omitempty for every field +// Field1 string `codec:"-"` //skip this field +// Field2 int `codec:"myName"` //Use key "myName" in encode stream +// Field3 int32 `codec:",omitempty"` //use key "Field3". Omit if empty. +// Field4 bool `codec:"f4,omitempty"` //use key "f4". Omit if empty. +// io.Reader //use key "Reader". +// MyStruct `codec:"my1" //use key "my1". +// MyStruct //inline it +// ... +// } +// +// type MyStruct struct { +// _struct bool `codec:",omitempty,toarray"` //set omitempty for every field +// //and encode struct as an array +// } +// +// The mode of encoding is based on the type of the value. When a value is seen: +// - If a Selfer, call its CodecEncodeSelf method +// - If an extension is registered for it, call that extension function +// - If it implements encoding.(Binary|Text|JSON)Marshaler, call its Marshal(Binary|Text|JSON) method +// - Else encode it based on its reflect.Kind +// +// Note that struct field names and keys in map[string]XXX will be treated as symbols. +// Some formats support symbols (e.g. binc) and will properly encode the string +// only once in the stream, and use a tag to refer to it thereafter. +func (e *Encoder) Encode(v interface{}) (err error) { + defer panicToErr(&err) + e.encode(v) + e.w.atEndOfEncode() + return +} + +// MustEncode is like Encode, but panics if unable to Encode. +// This provides insight to the code location that triggered the error. +func (e *Encoder) MustEncode(v interface{}) { + e.encode(v) + e.w.atEndOfEncode() +} + +// comment out these (Must)Write methods. They were only put there to support cbor. +// However, users already have access to the streams, and can write directly. +// +// // Write allows users write to the Encoder stream directly. +// func (e *Encoder) Write(bs []byte) (err error) { +// defer panicToErr(&err) +// e.w.writeb(bs) +// return +// } +// // MustWrite is like write, but panics if unable to Write. +// func (e *Encoder) MustWrite(bs []byte) { +// e.w.writeb(bs) +// } + +func (e *Encoder) encode(iv interface{}) { + // if ics, ok := iv.(Selfer); ok { + // ics.CodecEncodeSelf(e) + // return + // } + + switch v := iv.(type) { + case nil: + e.e.EncodeNil() + case Selfer: + v.CodecEncodeSelf(e) + + case reflect.Value: + e.encodeValue(v, nil) + + case string: + e.e.EncodeString(c_UTF8, v) + case bool: + e.e.EncodeBool(v) + case int: + e.e.EncodeInt(int64(v)) + case int8: + e.e.EncodeInt(int64(v)) + case int16: + e.e.EncodeInt(int64(v)) + case int32: + e.e.EncodeInt(int64(v)) + case int64: + e.e.EncodeInt(v) + case uint: + e.e.EncodeUint(uint64(v)) + case uint8: + e.e.EncodeUint(uint64(v)) + case uint16: + e.e.EncodeUint(uint64(v)) + case uint32: + e.e.EncodeUint(uint64(v)) + case uint64: + e.e.EncodeUint(v) + case float32: + e.e.EncodeFloat32(v) + case float64: + e.e.EncodeFloat64(v) + + case []uint8: + e.e.EncodeStringBytes(c_RAW, v) + + case *string: + e.e.EncodeString(c_UTF8, *v) + case *bool: + e.e.EncodeBool(*v) + case *int: + e.e.EncodeInt(int64(*v)) + case *int8: + e.e.EncodeInt(int64(*v)) + case *int16: + e.e.EncodeInt(int64(*v)) + case *int32: + e.e.EncodeInt(int64(*v)) + case *int64: + e.e.EncodeInt(*v) + case *uint: + e.e.EncodeUint(uint64(*v)) + case *uint8: + e.e.EncodeUint(uint64(*v)) + case *uint16: + e.e.EncodeUint(uint64(*v)) + case *uint32: + e.e.EncodeUint(uint64(*v)) + case *uint64: + e.e.EncodeUint(*v) + case *float32: + e.e.EncodeFloat32(*v) + case *float64: + e.e.EncodeFloat64(*v) + + case *[]uint8: + e.e.EncodeStringBytes(c_RAW, *v) + + default: + const checkCodecSelfer1 = true // in case T is passed, where *T is a Selfer, still checkCodecSelfer + if !fastpathEncodeTypeSwitch(iv, e) { + e.encodeI(iv, false, checkCodecSelfer1) + } + } +} + +func (e *Encoder) preEncodeValue(rv reflect.Value) (rv2 reflect.Value, sptr uintptr, proceed bool) { + // use a goto statement instead of a recursive function for ptr/interface. +TOP: + switch rv.Kind() { + case reflect.Ptr: + if rv.IsNil() { + e.e.EncodeNil() + return + } + rv = rv.Elem() + if e.h.CheckCircularRef && rv.Kind() == reflect.Struct { + // TODO: Movable pointers will be an issue here. Future problem. + sptr = rv.UnsafeAddr() + break TOP + } + goto TOP + case reflect.Interface: + if rv.IsNil() { + e.e.EncodeNil() + return + } + rv = rv.Elem() + goto TOP + case reflect.Slice, reflect.Map: + if rv.IsNil() { + e.e.EncodeNil() + return + } + case reflect.Invalid, reflect.Func: + e.e.EncodeNil() + return + } + + proceed = true + rv2 = rv + return +} + +func (e *Encoder) doEncodeValue(rv reflect.Value, fn *encFn, sptr uintptr, + checkFastpath, checkCodecSelfer bool) { + if sptr != 0 { + if (&e.ci).add(sptr) { + e.errorf("circular reference found: # %d", sptr) + } + } + if fn == nil { + rt := rv.Type() + rtid := reflect.ValueOf(rt).Pointer() + // fn = e.getEncFn(rtid, rt, true, true) + fn = e.getEncFn(rtid, rt, checkFastpath, checkCodecSelfer) + } + fn.f(&fn.i, rv) + if sptr != 0 { + (&e.ci).remove(sptr) + } +} + +func (e *Encoder) encodeI(iv interface{}, checkFastpath, checkCodecSelfer bool) { + if rv, sptr, proceed := e.preEncodeValue(reflect.ValueOf(iv)); proceed { + e.doEncodeValue(rv, nil, sptr, checkFastpath, checkCodecSelfer) + } +} + +func (e *Encoder) encodeValue(rv reflect.Value, fn *encFn) { + // if a valid fn is passed, it MUST BE for the dereferenced type of rv + if rv, sptr, proceed := e.preEncodeValue(rv); proceed { + e.doEncodeValue(rv, fn, sptr, true, true) + } +} + +func (e *Encoder) getEncFn(rtid uintptr, rt reflect.Type, checkFastpath, checkCodecSelfer bool) (fn *encFn) { + // rtid := reflect.ValueOf(rt).Pointer() + var ok bool + if useMapForCodecCache { + fn, ok = e.f[rtid] + } else { + for i := range e.s { + v := &(e.s[i]) + if v.rtid == rtid { + fn, ok = &(v.fn), true + break + } + } + } + if ok { + return + } + + if useMapForCodecCache { + if e.f == nil { + e.f = make(map[uintptr]*encFn, initCollectionCap) + } + fn = new(encFn) + e.f[rtid] = fn + } else { + if e.s == nil { + e.s = make([]encRtidFn, 0, initCollectionCap) + } + e.s = append(e.s, encRtidFn{rtid: rtid}) + fn = &(e.s[len(e.s)-1]).fn + } + + ti := e.h.getTypeInfo(rtid, rt) + fi := &(fn.i) + fi.e = e + fi.ti = ti + + if checkCodecSelfer && ti.cs { + fn.f = (*encFnInfo).selferMarshal + } else if rtid == rawExtTypId { + fn.f = (*encFnInfo).rawExt + } else if e.e.IsBuiltinType(rtid) { + fn.f = (*encFnInfo).builtin + } else if xfFn := e.h.getExt(rtid); xfFn != nil { + fi.xfTag, fi.xfFn = xfFn.tag, xfFn.ext + fn.f = (*encFnInfo).ext + } else if supportMarshalInterfaces && e.be && ti.bm { + fn.f = (*encFnInfo).binaryMarshal + } else if supportMarshalInterfaces && !e.be && e.js && ti.jm { + //If JSON, we should check JSONMarshal before textMarshal + fn.f = (*encFnInfo).jsonMarshal + } else if supportMarshalInterfaces && !e.be && ti.tm { + fn.f = (*encFnInfo).textMarshal + } else { + rk := rt.Kind() + if fastpathEnabled && checkFastpath && (rk == reflect.Map || rk == reflect.Slice) { + if rt.PkgPath() == "" { // un-named slice or map + if idx := fastpathAV.index(rtid); idx != -1 { + fn.f = fastpathAV[idx].encfn + } + } else { + ok = false + // use mapping for underlying type if there + var rtu reflect.Type + if rk == reflect.Map { + rtu = reflect.MapOf(rt.Key(), rt.Elem()) + } else { + rtu = reflect.SliceOf(rt.Elem()) + } + rtuid := reflect.ValueOf(rtu).Pointer() + if idx := fastpathAV.index(rtuid); idx != -1 { + xfnf := fastpathAV[idx].encfn + xrt := fastpathAV[idx].rt + fn.f = func(xf *encFnInfo, xrv reflect.Value) { + xfnf(xf, xrv.Convert(xrt)) + } + } + } + } + if fn.f == nil { + switch rk { + case reflect.Bool: + fn.f = (*encFnInfo).kBool + case reflect.String: + fn.f = (*encFnInfo).kString + case reflect.Float64: + fn.f = (*encFnInfo).kFloat64 + case reflect.Float32: + fn.f = (*encFnInfo).kFloat32 + case reflect.Int, reflect.Int8, reflect.Int64, reflect.Int32, reflect.Int16: + fn.f = (*encFnInfo).kInt + case reflect.Uint8, reflect.Uint64, reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uintptr: + fn.f = (*encFnInfo).kUint + case reflect.Invalid: + fn.f = (*encFnInfo).kInvalid + case reflect.Chan: + fi.seq = seqTypeChan + fn.f = (*encFnInfo).kSlice + case reflect.Slice: + fi.seq = seqTypeSlice + fn.f = (*encFnInfo).kSlice + case reflect.Array: + fi.seq = seqTypeArray + fn.f = (*encFnInfo).kSlice + case reflect.Struct: + fn.f = (*encFnInfo).kStruct + // reflect.Ptr and reflect.Interface are handled already by preEncodeValue + // case reflect.Ptr: + // fn.f = (*encFnInfo).kPtr + // case reflect.Interface: + // fn.f = (*encFnInfo).kInterface + case reflect.Map: + fn.f = (*encFnInfo).kMap + default: + fn.f = (*encFnInfo).kErr + } + } + } + + return +} + +func (e *Encoder) marshal(bs []byte, fnerr error, asis bool, c charEncoding) { + if fnerr != nil { + panic(fnerr) + } + if bs == nil { + e.e.EncodeNil() + } else if asis { + e.asis(bs) + } else { + e.e.EncodeStringBytes(c, bs) + } +} + +func (e *Encoder) asis(v []byte) { + if e.as == nil { + e.w.writeb(v) + } else { + e.as.EncodeAsis(v) + } +} + +func (e *Encoder) errorf(format string, params ...interface{}) { + err := fmt.Errorf(format, params...) + panic(err) +} + +// ---------------------------------------- + +const encStructPoolLen = 5 + +// encStructPool is an array of sync.Pool. +// Each element of the array pools one of encStructPool(8|16|32|64). +// It allows the re-use of slices up to 64 in length. +// A performance cost of encoding structs was collecting +// which values were empty and should be omitted. +// We needed slices of reflect.Value and string to collect them. +// This shared pool reduces the amount of unnecessary creation we do. +// The cost is that of locking sometimes, but sync.Pool is efficient +// enough to reduce thread contention. +var encStructPool [encStructPoolLen]sync.Pool + +func init() { + encStructPool[0].New = func() interface{} { return new([8]stringRv) } + encStructPool[1].New = func() interface{} { return new([16]stringRv) } + encStructPool[2].New = func() interface{} { return new([32]stringRv) } + encStructPool[3].New = func() interface{} { return new([64]stringRv) } + encStructPool[4].New = func() interface{} { return new([128]stringRv) } +} + +func encStructPoolGet(newlen int) (p *sync.Pool, v interface{}, s []stringRv) { + // if encStructPoolLen != 5 { // constant chec, so removed at build time. + // panic(errors.New("encStructPoolLen must be equal to 4")) // defensive, in case it is changed + // } + // idxpool := newlen / 8 + if newlen <= 8 { + p = &encStructPool[0] + v = p.Get() + s = v.(*[8]stringRv)[:newlen] + } else if newlen <= 16 { + p = &encStructPool[1] + v = p.Get() + s = v.(*[16]stringRv)[:newlen] + } else if newlen <= 32 { + p = &encStructPool[2] + v = p.Get() + s = v.(*[32]stringRv)[:newlen] + } else if newlen <= 64 { + p = &encStructPool[3] + v = p.Get() + s = v.(*[64]stringRv)[:newlen] + } else if newlen <= 128 { + p = &encStructPool[4] + v = p.Get() + s = v.(*[128]stringRv)[:newlen] + } else { + s = make([]stringRv, newlen) + } + return +} + +// ---------------------------------------- + +// func encErr(format string, params ...interface{}) { +// doPanic(msgTagEnc, format, params...) +// } diff --git a/vendor/github.com/ugorji/go/codec/fast-path.generated.go b/vendor/github.com/ugorji/go/codec/fast-path.generated.go new file mode 100644 index 000000000..cf6e00df2 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/fast-path.generated.go @@ -0,0 +1,39365 @@ +// +build !notfastpath + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +// ************************************************************ +// DO NOT EDIT. +// THIS FILE IS AUTO-GENERATED from fast-path.go.tmpl +// ************************************************************ + +package codec + +// Fast path functions try to create a fast path encode or decode implementation +// for common maps and slices. +// +// We define the functions and register then in this single file +// so as not to pollute the encode.go and decode.go, and create a dependency in there. +// This file can be omitted without causing a build failure. +// +// The advantage of fast paths is: +// - Many calls bypass reflection altogether +// +// Currently support +// - slice of all builtin types, +// - map of all builtin types to string or interface value +// - symetrical maps of all builtin types (e.g. str-str, uint8-uint8) +// This should provide adequate "typical" implementations. +// +// Note that fast track decode functions must handle values for which an address cannot be obtained. +// For example: +// m2 := map[string]int{} +// p2 := []interface{}{m2} +// // decoding into p2 will bomb if fast track functions do not treat like unaddressable. +// + +import ( + "reflect" + "sort" +) + +const fastpathCheckNilFalse = false // for reflect +const fastpathCheckNilTrue = true // for type switch + +type fastpathT struct{} + +var fastpathTV fastpathT + +type fastpathE struct { + rtid uintptr + rt reflect.Type + encfn func(*encFnInfo, reflect.Value) + decfn func(*decFnInfo, reflect.Value) +} + +type fastpathA [271]fastpathE + +func (x *fastpathA) index(rtid uintptr) int { + // use binary search to grab the index (adapted from sort/search.go) + h, i, j := 0, 0, 271 // len(x) + for i < j { + h = i + (j-i)/2 + if x[h].rtid < rtid { + i = h + 1 + } else { + j = h + } + } + if i < 271 && x[i].rtid == rtid { + return i + } + return -1 +} + +type fastpathAslice []fastpathE + +func (x fastpathAslice) Len() int { return len(x) } +func (x fastpathAslice) Less(i, j int) bool { return x[i].rtid < x[j].rtid } +func (x fastpathAslice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +var fastpathAV fastpathA + +// due to possible initialization loop error, make fastpath in an init() +func init() { + if !fastpathEnabled { + return + } + i := 0 + fn := func(v interface{}, fe func(*encFnInfo, reflect.Value), fd func(*decFnInfo, reflect.Value)) (f fastpathE) { + xrt := reflect.TypeOf(v) + xptr := reflect.ValueOf(xrt).Pointer() + fastpathAV[i] = fastpathE{xptr, xrt, fe, fd} + i++ + return + } + + fn([]interface{}(nil), (*encFnInfo).fastpathEncSliceIntfR, (*decFnInfo).fastpathDecSliceIntfR) + fn([]string(nil), (*encFnInfo).fastpathEncSliceStringR, (*decFnInfo).fastpathDecSliceStringR) + fn([]float32(nil), (*encFnInfo).fastpathEncSliceFloat32R, (*decFnInfo).fastpathDecSliceFloat32R) + fn([]float64(nil), (*encFnInfo).fastpathEncSliceFloat64R, (*decFnInfo).fastpathDecSliceFloat64R) + fn([]uint(nil), (*encFnInfo).fastpathEncSliceUintR, (*decFnInfo).fastpathDecSliceUintR) + fn([]uint16(nil), (*encFnInfo).fastpathEncSliceUint16R, (*decFnInfo).fastpathDecSliceUint16R) + fn([]uint32(nil), (*encFnInfo).fastpathEncSliceUint32R, (*decFnInfo).fastpathDecSliceUint32R) + fn([]uint64(nil), (*encFnInfo).fastpathEncSliceUint64R, (*decFnInfo).fastpathDecSliceUint64R) + fn([]uintptr(nil), (*encFnInfo).fastpathEncSliceUintptrR, (*decFnInfo).fastpathDecSliceUintptrR) + fn([]int(nil), (*encFnInfo).fastpathEncSliceIntR, (*decFnInfo).fastpathDecSliceIntR) + fn([]int8(nil), (*encFnInfo).fastpathEncSliceInt8R, (*decFnInfo).fastpathDecSliceInt8R) + fn([]int16(nil), (*encFnInfo).fastpathEncSliceInt16R, (*decFnInfo).fastpathDecSliceInt16R) + fn([]int32(nil), (*encFnInfo).fastpathEncSliceInt32R, (*decFnInfo).fastpathDecSliceInt32R) + fn([]int64(nil), (*encFnInfo).fastpathEncSliceInt64R, (*decFnInfo).fastpathDecSliceInt64R) + fn([]bool(nil), (*encFnInfo).fastpathEncSliceBoolR, (*decFnInfo).fastpathDecSliceBoolR) + + fn(map[interface{}]interface{}(nil), (*encFnInfo).fastpathEncMapIntfIntfR, (*decFnInfo).fastpathDecMapIntfIntfR) + fn(map[interface{}]string(nil), (*encFnInfo).fastpathEncMapIntfStringR, (*decFnInfo).fastpathDecMapIntfStringR) + fn(map[interface{}]uint(nil), (*encFnInfo).fastpathEncMapIntfUintR, (*decFnInfo).fastpathDecMapIntfUintR) + fn(map[interface{}]uint8(nil), (*encFnInfo).fastpathEncMapIntfUint8R, (*decFnInfo).fastpathDecMapIntfUint8R) + fn(map[interface{}]uint16(nil), (*encFnInfo).fastpathEncMapIntfUint16R, (*decFnInfo).fastpathDecMapIntfUint16R) + fn(map[interface{}]uint32(nil), (*encFnInfo).fastpathEncMapIntfUint32R, (*decFnInfo).fastpathDecMapIntfUint32R) + fn(map[interface{}]uint64(nil), (*encFnInfo).fastpathEncMapIntfUint64R, (*decFnInfo).fastpathDecMapIntfUint64R) + fn(map[interface{}]uintptr(nil), (*encFnInfo).fastpathEncMapIntfUintptrR, (*decFnInfo).fastpathDecMapIntfUintptrR) + fn(map[interface{}]int(nil), (*encFnInfo).fastpathEncMapIntfIntR, (*decFnInfo).fastpathDecMapIntfIntR) + fn(map[interface{}]int8(nil), (*encFnInfo).fastpathEncMapIntfInt8R, (*decFnInfo).fastpathDecMapIntfInt8R) + fn(map[interface{}]int16(nil), (*encFnInfo).fastpathEncMapIntfInt16R, (*decFnInfo).fastpathDecMapIntfInt16R) + fn(map[interface{}]int32(nil), (*encFnInfo).fastpathEncMapIntfInt32R, (*decFnInfo).fastpathDecMapIntfInt32R) + fn(map[interface{}]int64(nil), (*encFnInfo).fastpathEncMapIntfInt64R, (*decFnInfo).fastpathDecMapIntfInt64R) + fn(map[interface{}]float32(nil), (*encFnInfo).fastpathEncMapIntfFloat32R, (*decFnInfo).fastpathDecMapIntfFloat32R) + fn(map[interface{}]float64(nil), (*encFnInfo).fastpathEncMapIntfFloat64R, (*decFnInfo).fastpathDecMapIntfFloat64R) + fn(map[interface{}]bool(nil), (*encFnInfo).fastpathEncMapIntfBoolR, (*decFnInfo).fastpathDecMapIntfBoolR) + fn(map[string]interface{}(nil), (*encFnInfo).fastpathEncMapStringIntfR, (*decFnInfo).fastpathDecMapStringIntfR) + fn(map[string]string(nil), (*encFnInfo).fastpathEncMapStringStringR, (*decFnInfo).fastpathDecMapStringStringR) + fn(map[string]uint(nil), (*encFnInfo).fastpathEncMapStringUintR, (*decFnInfo).fastpathDecMapStringUintR) + fn(map[string]uint8(nil), (*encFnInfo).fastpathEncMapStringUint8R, (*decFnInfo).fastpathDecMapStringUint8R) + fn(map[string]uint16(nil), (*encFnInfo).fastpathEncMapStringUint16R, (*decFnInfo).fastpathDecMapStringUint16R) + fn(map[string]uint32(nil), (*encFnInfo).fastpathEncMapStringUint32R, (*decFnInfo).fastpathDecMapStringUint32R) + fn(map[string]uint64(nil), (*encFnInfo).fastpathEncMapStringUint64R, (*decFnInfo).fastpathDecMapStringUint64R) + fn(map[string]uintptr(nil), (*encFnInfo).fastpathEncMapStringUintptrR, (*decFnInfo).fastpathDecMapStringUintptrR) + fn(map[string]int(nil), (*encFnInfo).fastpathEncMapStringIntR, (*decFnInfo).fastpathDecMapStringIntR) + fn(map[string]int8(nil), (*encFnInfo).fastpathEncMapStringInt8R, (*decFnInfo).fastpathDecMapStringInt8R) + fn(map[string]int16(nil), (*encFnInfo).fastpathEncMapStringInt16R, (*decFnInfo).fastpathDecMapStringInt16R) + fn(map[string]int32(nil), (*encFnInfo).fastpathEncMapStringInt32R, (*decFnInfo).fastpathDecMapStringInt32R) + fn(map[string]int64(nil), (*encFnInfo).fastpathEncMapStringInt64R, (*decFnInfo).fastpathDecMapStringInt64R) + fn(map[string]float32(nil), (*encFnInfo).fastpathEncMapStringFloat32R, (*decFnInfo).fastpathDecMapStringFloat32R) + fn(map[string]float64(nil), (*encFnInfo).fastpathEncMapStringFloat64R, (*decFnInfo).fastpathDecMapStringFloat64R) + fn(map[string]bool(nil), (*encFnInfo).fastpathEncMapStringBoolR, (*decFnInfo).fastpathDecMapStringBoolR) + fn(map[float32]interface{}(nil), (*encFnInfo).fastpathEncMapFloat32IntfR, (*decFnInfo).fastpathDecMapFloat32IntfR) + fn(map[float32]string(nil), (*encFnInfo).fastpathEncMapFloat32StringR, (*decFnInfo).fastpathDecMapFloat32StringR) + fn(map[float32]uint(nil), (*encFnInfo).fastpathEncMapFloat32UintR, (*decFnInfo).fastpathDecMapFloat32UintR) + fn(map[float32]uint8(nil), (*encFnInfo).fastpathEncMapFloat32Uint8R, (*decFnInfo).fastpathDecMapFloat32Uint8R) + fn(map[float32]uint16(nil), (*encFnInfo).fastpathEncMapFloat32Uint16R, (*decFnInfo).fastpathDecMapFloat32Uint16R) + fn(map[float32]uint32(nil), (*encFnInfo).fastpathEncMapFloat32Uint32R, (*decFnInfo).fastpathDecMapFloat32Uint32R) + fn(map[float32]uint64(nil), (*encFnInfo).fastpathEncMapFloat32Uint64R, (*decFnInfo).fastpathDecMapFloat32Uint64R) + fn(map[float32]uintptr(nil), (*encFnInfo).fastpathEncMapFloat32UintptrR, (*decFnInfo).fastpathDecMapFloat32UintptrR) + fn(map[float32]int(nil), (*encFnInfo).fastpathEncMapFloat32IntR, (*decFnInfo).fastpathDecMapFloat32IntR) + fn(map[float32]int8(nil), (*encFnInfo).fastpathEncMapFloat32Int8R, (*decFnInfo).fastpathDecMapFloat32Int8R) + fn(map[float32]int16(nil), (*encFnInfo).fastpathEncMapFloat32Int16R, (*decFnInfo).fastpathDecMapFloat32Int16R) + fn(map[float32]int32(nil), (*encFnInfo).fastpathEncMapFloat32Int32R, (*decFnInfo).fastpathDecMapFloat32Int32R) + fn(map[float32]int64(nil), (*encFnInfo).fastpathEncMapFloat32Int64R, (*decFnInfo).fastpathDecMapFloat32Int64R) + fn(map[float32]float32(nil), (*encFnInfo).fastpathEncMapFloat32Float32R, (*decFnInfo).fastpathDecMapFloat32Float32R) + fn(map[float32]float64(nil), (*encFnInfo).fastpathEncMapFloat32Float64R, (*decFnInfo).fastpathDecMapFloat32Float64R) + fn(map[float32]bool(nil), (*encFnInfo).fastpathEncMapFloat32BoolR, (*decFnInfo).fastpathDecMapFloat32BoolR) + fn(map[float64]interface{}(nil), (*encFnInfo).fastpathEncMapFloat64IntfR, (*decFnInfo).fastpathDecMapFloat64IntfR) + fn(map[float64]string(nil), (*encFnInfo).fastpathEncMapFloat64StringR, (*decFnInfo).fastpathDecMapFloat64StringR) + fn(map[float64]uint(nil), (*encFnInfo).fastpathEncMapFloat64UintR, (*decFnInfo).fastpathDecMapFloat64UintR) + fn(map[float64]uint8(nil), (*encFnInfo).fastpathEncMapFloat64Uint8R, (*decFnInfo).fastpathDecMapFloat64Uint8R) + fn(map[float64]uint16(nil), (*encFnInfo).fastpathEncMapFloat64Uint16R, (*decFnInfo).fastpathDecMapFloat64Uint16R) + fn(map[float64]uint32(nil), (*encFnInfo).fastpathEncMapFloat64Uint32R, (*decFnInfo).fastpathDecMapFloat64Uint32R) + fn(map[float64]uint64(nil), (*encFnInfo).fastpathEncMapFloat64Uint64R, (*decFnInfo).fastpathDecMapFloat64Uint64R) + fn(map[float64]uintptr(nil), (*encFnInfo).fastpathEncMapFloat64UintptrR, (*decFnInfo).fastpathDecMapFloat64UintptrR) + fn(map[float64]int(nil), (*encFnInfo).fastpathEncMapFloat64IntR, (*decFnInfo).fastpathDecMapFloat64IntR) + fn(map[float64]int8(nil), (*encFnInfo).fastpathEncMapFloat64Int8R, (*decFnInfo).fastpathDecMapFloat64Int8R) + fn(map[float64]int16(nil), (*encFnInfo).fastpathEncMapFloat64Int16R, (*decFnInfo).fastpathDecMapFloat64Int16R) + fn(map[float64]int32(nil), (*encFnInfo).fastpathEncMapFloat64Int32R, (*decFnInfo).fastpathDecMapFloat64Int32R) + fn(map[float64]int64(nil), (*encFnInfo).fastpathEncMapFloat64Int64R, (*decFnInfo).fastpathDecMapFloat64Int64R) + fn(map[float64]float32(nil), (*encFnInfo).fastpathEncMapFloat64Float32R, (*decFnInfo).fastpathDecMapFloat64Float32R) + fn(map[float64]float64(nil), (*encFnInfo).fastpathEncMapFloat64Float64R, (*decFnInfo).fastpathDecMapFloat64Float64R) + fn(map[float64]bool(nil), (*encFnInfo).fastpathEncMapFloat64BoolR, (*decFnInfo).fastpathDecMapFloat64BoolR) + fn(map[uint]interface{}(nil), (*encFnInfo).fastpathEncMapUintIntfR, (*decFnInfo).fastpathDecMapUintIntfR) + fn(map[uint]string(nil), (*encFnInfo).fastpathEncMapUintStringR, (*decFnInfo).fastpathDecMapUintStringR) + fn(map[uint]uint(nil), (*encFnInfo).fastpathEncMapUintUintR, (*decFnInfo).fastpathDecMapUintUintR) + fn(map[uint]uint8(nil), (*encFnInfo).fastpathEncMapUintUint8R, (*decFnInfo).fastpathDecMapUintUint8R) + fn(map[uint]uint16(nil), (*encFnInfo).fastpathEncMapUintUint16R, (*decFnInfo).fastpathDecMapUintUint16R) + fn(map[uint]uint32(nil), (*encFnInfo).fastpathEncMapUintUint32R, (*decFnInfo).fastpathDecMapUintUint32R) + fn(map[uint]uint64(nil), (*encFnInfo).fastpathEncMapUintUint64R, (*decFnInfo).fastpathDecMapUintUint64R) + fn(map[uint]uintptr(nil), (*encFnInfo).fastpathEncMapUintUintptrR, (*decFnInfo).fastpathDecMapUintUintptrR) + fn(map[uint]int(nil), (*encFnInfo).fastpathEncMapUintIntR, (*decFnInfo).fastpathDecMapUintIntR) + fn(map[uint]int8(nil), (*encFnInfo).fastpathEncMapUintInt8R, (*decFnInfo).fastpathDecMapUintInt8R) + fn(map[uint]int16(nil), (*encFnInfo).fastpathEncMapUintInt16R, (*decFnInfo).fastpathDecMapUintInt16R) + fn(map[uint]int32(nil), (*encFnInfo).fastpathEncMapUintInt32R, (*decFnInfo).fastpathDecMapUintInt32R) + fn(map[uint]int64(nil), (*encFnInfo).fastpathEncMapUintInt64R, (*decFnInfo).fastpathDecMapUintInt64R) + fn(map[uint]float32(nil), (*encFnInfo).fastpathEncMapUintFloat32R, (*decFnInfo).fastpathDecMapUintFloat32R) + fn(map[uint]float64(nil), (*encFnInfo).fastpathEncMapUintFloat64R, (*decFnInfo).fastpathDecMapUintFloat64R) + fn(map[uint]bool(nil), (*encFnInfo).fastpathEncMapUintBoolR, (*decFnInfo).fastpathDecMapUintBoolR) + fn(map[uint8]interface{}(nil), (*encFnInfo).fastpathEncMapUint8IntfR, (*decFnInfo).fastpathDecMapUint8IntfR) + fn(map[uint8]string(nil), (*encFnInfo).fastpathEncMapUint8StringR, (*decFnInfo).fastpathDecMapUint8StringR) + fn(map[uint8]uint(nil), (*encFnInfo).fastpathEncMapUint8UintR, (*decFnInfo).fastpathDecMapUint8UintR) + fn(map[uint8]uint8(nil), (*encFnInfo).fastpathEncMapUint8Uint8R, (*decFnInfo).fastpathDecMapUint8Uint8R) + fn(map[uint8]uint16(nil), (*encFnInfo).fastpathEncMapUint8Uint16R, (*decFnInfo).fastpathDecMapUint8Uint16R) + fn(map[uint8]uint32(nil), (*encFnInfo).fastpathEncMapUint8Uint32R, (*decFnInfo).fastpathDecMapUint8Uint32R) + fn(map[uint8]uint64(nil), (*encFnInfo).fastpathEncMapUint8Uint64R, (*decFnInfo).fastpathDecMapUint8Uint64R) + fn(map[uint8]uintptr(nil), (*encFnInfo).fastpathEncMapUint8UintptrR, (*decFnInfo).fastpathDecMapUint8UintptrR) + fn(map[uint8]int(nil), (*encFnInfo).fastpathEncMapUint8IntR, (*decFnInfo).fastpathDecMapUint8IntR) + fn(map[uint8]int8(nil), (*encFnInfo).fastpathEncMapUint8Int8R, (*decFnInfo).fastpathDecMapUint8Int8R) + fn(map[uint8]int16(nil), (*encFnInfo).fastpathEncMapUint8Int16R, (*decFnInfo).fastpathDecMapUint8Int16R) + fn(map[uint8]int32(nil), (*encFnInfo).fastpathEncMapUint8Int32R, (*decFnInfo).fastpathDecMapUint8Int32R) + fn(map[uint8]int64(nil), (*encFnInfo).fastpathEncMapUint8Int64R, (*decFnInfo).fastpathDecMapUint8Int64R) + fn(map[uint8]float32(nil), (*encFnInfo).fastpathEncMapUint8Float32R, (*decFnInfo).fastpathDecMapUint8Float32R) + fn(map[uint8]float64(nil), (*encFnInfo).fastpathEncMapUint8Float64R, (*decFnInfo).fastpathDecMapUint8Float64R) + fn(map[uint8]bool(nil), (*encFnInfo).fastpathEncMapUint8BoolR, (*decFnInfo).fastpathDecMapUint8BoolR) + fn(map[uint16]interface{}(nil), (*encFnInfo).fastpathEncMapUint16IntfR, (*decFnInfo).fastpathDecMapUint16IntfR) + fn(map[uint16]string(nil), (*encFnInfo).fastpathEncMapUint16StringR, (*decFnInfo).fastpathDecMapUint16StringR) + fn(map[uint16]uint(nil), (*encFnInfo).fastpathEncMapUint16UintR, (*decFnInfo).fastpathDecMapUint16UintR) + fn(map[uint16]uint8(nil), (*encFnInfo).fastpathEncMapUint16Uint8R, (*decFnInfo).fastpathDecMapUint16Uint8R) + fn(map[uint16]uint16(nil), (*encFnInfo).fastpathEncMapUint16Uint16R, (*decFnInfo).fastpathDecMapUint16Uint16R) + fn(map[uint16]uint32(nil), (*encFnInfo).fastpathEncMapUint16Uint32R, (*decFnInfo).fastpathDecMapUint16Uint32R) + fn(map[uint16]uint64(nil), (*encFnInfo).fastpathEncMapUint16Uint64R, (*decFnInfo).fastpathDecMapUint16Uint64R) + fn(map[uint16]uintptr(nil), (*encFnInfo).fastpathEncMapUint16UintptrR, (*decFnInfo).fastpathDecMapUint16UintptrR) + fn(map[uint16]int(nil), (*encFnInfo).fastpathEncMapUint16IntR, (*decFnInfo).fastpathDecMapUint16IntR) + fn(map[uint16]int8(nil), (*encFnInfo).fastpathEncMapUint16Int8R, (*decFnInfo).fastpathDecMapUint16Int8R) + fn(map[uint16]int16(nil), (*encFnInfo).fastpathEncMapUint16Int16R, (*decFnInfo).fastpathDecMapUint16Int16R) + fn(map[uint16]int32(nil), (*encFnInfo).fastpathEncMapUint16Int32R, (*decFnInfo).fastpathDecMapUint16Int32R) + fn(map[uint16]int64(nil), (*encFnInfo).fastpathEncMapUint16Int64R, (*decFnInfo).fastpathDecMapUint16Int64R) + fn(map[uint16]float32(nil), (*encFnInfo).fastpathEncMapUint16Float32R, (*decFnInfo).fastpathDecMapUint16Float32R) + fn(map[uint16]float64(nil), (*encFnInfo).fastpathEncMapUint16Float64R, (*decFnInfo).fastpathDecMapUint16Float64R) + fn(map[uint16]bool(nil), (*encFnInfo).fastpathEncMapUint16BoolR, (*decFnInfo).fastpathDecMapUint16BoolR) + fn(map[uint32]interface{}(nil), (*encFnInfo).fastpathEncMapUint32IntfR, (*decFnInfo).fastpathDecMapUint32IntfR) + fn(map[uint32]string(nil), (*encFnInfo).fastpathEncMapUint32StringR, (*decFnInfo).fastpathDecMapUint32StringR) + fn(map[uint32]uint(nil), (*encFnInfo).fastpathEncMapUint32UintR, (*decFnInfo).fastpathDecMapUint32UintR) + fn(map[uint32]uint8(nil), (*encFnInfo).fastpathEncMapUint32Uint8R, (*decFnInfo).fastpathDecMapUint32Uint8R) + fn(map[uint32]uint16(nil), (*encFnInfo).fastpathEncMapUint32Uint16R, (*decFnInfo).fastpathDecMapUint32Uint16R) + fn(map[uint32]uint32(nil), (*encFnInfo).fastpathEncMapUint32Uint32R, (*decFnInfo).fastpathDecMapUint32Uint32R) + fn(map[uint32]uint64(nil), (*encFnInfo).fastpathEncMapUint32Uint64R, (*decFnInfo).fastpathDecMapUint32Uint64R) + fn(map[uint32]uintptr(nil), (*encFnInfo).fastpathEncMapUint32UintptrR, (*decFnInfo).fastpathDecMapUint32UintptrR) + fn(map[uint32]int(nil), (*encFnInfo).fastpathEncMapUint32IntR, (*decFnInfo).fastpathDecMapUint32IntR) + fn(map[uint32]int8(nil), (*encFnInfo).fastpathEncMapUint32Int8R, (*decFnInfo).fastpathDecMapUint32Int8R) + fn(map[uint32]int16(nil), (*encFnInfo).fastpathEncMapUint32Int16R, (*decFnInfo).fastpathDecMapUint32Int16R) + fn(map[uint32]int32(nil), (*encFnInfo).fastpathEncMapUint32Int32R, (*decFnInfo).fastpathDecMapUint32Int32R) + fn(map[uint32]int64(nil), (*encFnInfo).fastpathEncMapUint32Int64R, (*decFnInfo).fastpathDecMapUint32Int64R) + fn(map[uint32]float32(nil), (*encFnInfo).fastpathEncMapUint32Float32R, (*decFnInfo).fastpathDecMapUint32Float32R) + fn(map[uint32]float64(nil), (*encFnInfo).fastpathEncMapUint32Float64R, (*decFnInfo).fastpathDecMapUint32Float64R) + fn(map[uint32]bool(nil), (*encFnInfo).fastpathEncMapUint32BoolR, (*decFnInfo).fastpathDecMapUint32BoolR) + fn(map[uint64]interface{}(nil), (*encFnInfo).fastpathEncMapUint64IntfR, (*decFnInfo).fastpathDecMapUint64IntfR) + fn(map[uint64]string(nil), (*encFnInfo).fastpathEncMapUint64StringR, (*decFnInfo).fastpathDecMapUint64StringR) + fn(map[uint64]uint(nil), (*encFnInfo).fastpathEncMapUint64UintR, (*decFnInfo).fastpathDecMapUint64UintR) + fn(map[uint64]uint8(nil), (*encFnInfo).fastpathEncMapUint64Uint8R, (*decFnInfo).fastpathDecMapUint64Uint8R) + fn(map[uint64]uint16(nil), (*encFnInfo).fastpathEncMapUint64Uint16R, (*decFnInfo).fastpathDecMapUint64Uint16R) + fn(map[uint64]uint32(nil), (*encFnInfo).fastpathEncMapUint64Uint32R, (*decFnInfo).fastpathDecMapUint64Uint32R) + fn(map[uint64]uint64(nil), (*encFnInfo).fastpathEncMapUint64Uint64R, (*decFnInfo).fastpathDecMapUint64Uint64R) + fn(map[uint64]uintptr(nil), (*encFnInfo).fastpathEncMapUint64UintptrR, (*decFnInfo).fastpathDecMapUint64UintptrR) + fn(map[uint64]int(nil), (*encFnInfo).fastpathEncMapUint64IntR, (*decFnInfo).fastpathDecMapUint64IntR) + fn(map[uint64]int8(nil), (*encFnInfo).fastpathEncMapUint64Int8R, (*decFnInfo).fastpathDecMapUint64Int8R) + fn(map[uint64]int16(nil), (*encFnInfo).fastpathEncMapUint64Int16R, (*decFnInfo).fastpathDecMapUint64Int16R) + fn(map[uint64]int32(nil), (*encFnInfo).fastpathEncMapUint64Int32R, (*decFnInfo).fastpathDecMapUint64Int32R) + fn(map[uint64]int64(nil), (*encFnInfo).fastpathEncMapUint64Int64R, (*decFnInfo).fastpathDecMapUint64Int64R) + fn(map[uint64]float32(nil), (*encFnInfo).fastpathEncMapUint64Float32R, (*decFnInfo).fastpathDecMapUint64Float32R) + fn(map[uint64]float64(nil), (*encFnInfo).fastpathEncMapUint64Float64R, (*decFnInfo).fastpathDecMapUint64Float64R) + fn(map[uint64]bool(nil), (*encFnInfo).fastpathEncMapUint64BoolR, (*decFnInfo).fastpathDecMapUint64BoolR) + fn(map[uintptr]interface{}(nil), (*encFnInfo).fastpathEncMapUintptrIntfR, (*decFnInfo).fastpathDecMapUintptrIntfR) + fn(map[uintptr]string(nil), (*encFnInfo).fastpathEncMapUintptrStringR, (*decFnInfo).fastpathDecMapUintptrStringR) + fn(map[uintptr]uint(nil), (*encFnInfo).fastpathEncMapUintptrUintR, (*decFnInfo).fastpathDecMapUintptrUintR) + fn(map[uintptr]uint8(nil), (*encFnInfo).fastpathEncMapUintptrUint8R, (*decFnInfo).fastpathDecMapUintptrUint8R) + fn(map[uintptr]uint16(nil), (*encFnInfo).fastpathEncMapUintptrUint16R, (*decFnInfo).fastpathDecMapUintptrUint16R) + fn(map[uintptr]uint32(nil), (*encFnInfo).fastpathEncMapUintptrUint32R, (*decFnInfo).fastpathDecMapUintptrUint32R) + fn(map[uintptr]uint64(nil), (*encFnInfo).fastpathEncMapUintptrUint64R, (*decFnInfo).fastpathDecMapUintptrUint64R) + fn(map[uintptr]uintptr(nil), (*encFnInfo).fastpathEncMapUintptrUintptrR, (*decFnInfo).fastpathDecMapUintptrUintptrR) + fn(map[uintptr]int(nil), (*encFnInfo).fastpathEncMapUintptrIntR, (*decFnInfo).fastpathDecMapUintptrIntR) + fn(map[uintptr]int8(nil), (*encFnInfo).fastpathEncMapUintptrInt8R, (*decFnInfo).fastpathDecMapUintptrInt8R) + fn(map[uintptr]int16(nil), (*encFnInfo).fastpathEncMapUintptrInt16R, (*decFnInfo).fastpathDecMapUintptrInt16R) + fn(map[uintptr]int32(nil), (*encFnInfo).fastpathEncMapUintptrInt32R, (*decFnInfo).fastpathDecMapUintptrInt32R) + fn(map[uintptr]int64(nil), (*encFnInfo).fastpathEncMapUintptrInt64R, (*decFnInfo).fastpathDecMapUintptrInt64R) + fn(map[uintptr]float32(nil), (*encFnInfo).fastpathEncMapUintptrFloat32R, (*decFnInfo).fastpathDecMapUintptrFloat32R) + fn(map[uintptr]float64(nil), (*encFnInfo).fastpathEncMapUintptrFloat64R, (*decFnInfo).fastpathDecMapUintptrFloat64R) + fn(map[uintptr]bool(nil), (*encFnInfo).fastpathEncMapUintptrBoolR, (*decFnInfo).fastpathDecMapUintptrBoolR) + fn(map[int]interface{}(nil), (*encFnInfo).fastpathEncMapIntIntfR, (*decFnInfo).fastpathDecMapIntIntfR) + fn(map[int]string(nil), (*encFnInfo).fastpathEncMapIntStringR, (*decFnInfo).fastpathDecMapIntStringR) + fn(map[int]uint(nil), (*encFnInfo).fastpathEncMapIntUintR, (*decFnInfo).fastpathDecMapIntUintR) + fn(map[int]uint8(nil), (*encFnInfo).fastpathEncMapIntUint8R, (*decFnInfo).fastpathDecMapIntUint8R) + fn(map[int]uint16(nil), (*encFnInfo).fastpathEncMapIntUint16R, (*decFnInfo).fastpathDecMapIntUint16R) + fn(map[int]uint32(nil), (*encFnInfo).fastpathEncMapIntUint32R, (*decFnInfo).fastpathDecMapIntUint32R) + fn(map[int]uint64(nil), (*encFnInfo).fastpathEncMapIntUint64R, (*decFnInfo).fastpathDecMapIntUint64R) + fn(map[int]uintptr(nil), (*encFnInfo).fastpathEncMapIntUintptrR, (*decFnInfo).fastpathDecMapIntUintptrR) + fn(map[int]int(nil), (*encFnInfo).fastpathEncMapIntIntR, (*decFnInfo).fastpathDecMapIntIntR) + fn(map[int]int8(nil), (*encFnInfo).fastpathEncMapIntInt8R, (*decFnInfo).fastpathDecMapIntInt8R) + fn(map[int]int16(nil), (*encFnInfo).fastpathEncMapIntInt16R, (*decFnInfo).fastpathDecMapIntInt16R) + fn(map[int]int32(nil), (*encFnInfo).fastpathEncMapIntInt32R, (*decFnInfo).fastpathDecMapIntInt32R) + fn(map[int]int64(nil), (*encFnInfo).fastpathEncMapIntInt64R, (*decFnInfo).fastpathDecMapIntInt64R) + fn(map[int]float32(nil), (*encFnInfo).fastpathEncMapIntFloat32R, (*decFnInfo).fastpathDecMapIntFloat32R) + fn(map[int]float64(nil), (*encFnInfo).fastpathEncMapIntFloat64R, (*decFnInfo).fastpathDecMapIntFloat64R) + fn(map[int]bool(nil), (*encFnInfo).fastpathEncMapIntBoolR, (*decFnInfo).fastpathDecMapIntBoolR) + fn(map[int8]interface{}(nil), (*encFnInfo).fastpathEncMapInt8IntfR, (*decFnInfo).fastpathDecMapInt8IntfR) + fn(map[int8]string(nil), (*encFnInfo).fastpathEncMapInt8StringR, (*decFnInfo).fastpathDecMapInt8StringR) + fn(map[int8]uint(nil), (*encFnInfo).fastpathEncMapInt8UintR, (*decFnInfo).fastpathDecMapInt8UintR) + fn(map[int8]uint8(nil), (*encFnInfo).fastpathEncMapInt8Uint8R, (*decFnInfo).fastpathDecMapInt8Uint8R) + fn(map[int8]uint16(nil), (*encFnInfo).fastpathEncMapInt8Uint16R, (*decFnInfo).fastpathDecMapInt8Uint16R) + fn(map[int8]uint32(nil), (*encFnInfo).fastpathEncMapInt8Uint32R, (*decFnInfo).fastpathDecMapInt8Uint32R) + fn(map[int8]uint64(nil), (*encFnInfo).fastpathEncMapInt8Uint64R, (*decFnInfo).fastpathDecMapInt8Uint64R) + fn(map[int8]uintptr(nil), (*encFnInfo).fastpathEncMapInt8UintptrR, (*decFnInfo).fastpathDecMapInt8UintptrR) + fn(map[int8]int(nil), (*encFnInfo).fastpathEncMapInt8IntR, (*decFnInfo).fastpathDecMapInt8IntR) + fn(map[int8]int8(nil), (*encFnInfo).fastpathEncMapInt8Int8R, (*decFnInfo).fastpathDecMapInt8Int8R) + fn(map[int8]int16(nil), (*encFnInfo).fastpathEncMapInt8Int16R, (*decFnInfo).fastpathDecMapInt8Int16R) + fn(map[int8]int32(nil), (*encFnInfo).fastpathEncMapInt8Int32R, (*decFnInfo).fastpathDecMapInt8Int32R) + fn(map[int8]int64(nil), (*encFnInfo).fastpathEncMapInt8Int64R, (*decFnInfo).fastpathDecMapInt8Int64R) + fn(map[int8]float32(nil), (*encFnInfo).fastpathEncMapInt8Float32R, (*decFnInfo).fastpathDecMapInt8Float32R) + fn(map[int8]float64(nil), (*encFnInfo).fastpathEncMapInt8Float64R, (*decFnInfo).fastpathDecMapInt8Float64R) + fn(map[int8]bool(nil), (*encFnInfo).fastpathEncMapInt8BoolR, (*decFnInfo).fastpathDecMapInt8BoolR) + fn(map[int16]interface{}(nil), (*encFnInfo).fastpathEncMapInt16IntfR, (*decFnInfo).fastpathDecMapInt16IntfR) + fn(map[int16]string(nil), (*encFnInfo).fastpathEncMapInt16StringR, (*decFnInfo).fastpathDecMapInt16StringR) + fn(map[int16]uint(nil), (*encFnInfo).fastpathEncMapInt16UintR, (*decFnInfo).fastpathDecMapInt16UintR) + fn(map[int16]uint8(nil), (*encFnInfo).fastpathEncMapInt16Uint8R, (*decFnInfo).fastpathDecMapInt16Uint8R) + fn(map[int16]uint16(nil), (*encFnInfo).fastpathEncMapInt16Uint16R, (*decFnInfo).fastpathDecMapInt16Uint16R) + fn(map[int16]uint32(nil), (*encFnInfo).fastpathEncMapInt16Uint32R, (*decFnInfo).fastpathDecMapInt16Uint32R) + fn(map[int16]uint64(nil), (*encFnInfo).fastpathEncMapInt16Uint64R, (*decFnInfo).fastpathDecMapInt16Uint64R) + fn(map[int16]uintptr(nil), (*encFnInfo).fastpathEncMapInt16UintptrR, (*decFnInfo).fastpathDecMapInt16UintptrR) + fn(map[int16]int(nil), (*encFnInfo).fastpathEncMapInt16IntR, (*decFnInfo).fastpathDecMapInt16IntR) + fn(map[int16]int8(nil), (*encFnInfo).fastpathEncMapInt16Int8R, (*decFnInfo).fastpathDecMapInt16Int8R) + fn(map[int16]int16(nil), (*encFnInfo).fastpathEncMapInt16Int16R, (*decFnInfo).fastpathDecMapInt16Int16R) + fn(map[int16]int32(nil), (*encFnInfo).fastpathEncMapInt16Int32R, (*decFnInfo).fastpathDecMapInt16Int32R) + fn(map[int16]int64(nil), (*encFnInfo).fastpathEncMapInt16Int64R, (*decFnInfo).fastpathDecMapInt16Int64R) + fn(map[int16]float32(nil), (*encFnInfo).fastpathEncMapInt16Float32R, (*decFnInfo).fastpathDecMapInt16Float32R) + fn(map[int16]float64(nil), (*encFnInfo).fastpathEncMapInt16Float64R, (*decFnInfo).fastpathDecMapInt16Float64R) + fn(map[int16]bool(nil), (*encFnInfo).fastpathEncMapInt16BoolR, (*decFnInfo).fastpathDecMapInt16BoolR) + fn(map[int32]interface{}(nil), (*encFnInfo).fastpathEncMapInt32IntfR, (*decFnInfo).fastpathDecMapInt32IntfR) + fn(map[int32]string(nil), (*encFnInfo).fastpathEncMapInt32StringR, (*decFnInfo).fastpathDecMapInt32StringR) + fn(map[int32]uint(nil), (*encFnInfo).fastpathEncMapInt32UintR, (*decFnInfo).fastpathDecMapInt32UintR) + fn(map[int32]uint8(nil), (*encFnInfo).fastpathEncMapInt32Uint8R, (*decFnInfo).fastpathDecMapInt32Uint8R) + fn(map[int32]uint16(nil), (*encFnInfo).fastpathEncMapInt32Uint16R, (*decFnInfo).fastpathDecMapInt32Uint16R) + fn(map[int32]uint32(nil), (*encFnInfo).fastpathEncMapInt32Uint32R, (*decFnInfo).fastpathDecMapInt32Uint32R) + fn(map[int32]uint64(nil), (*encFnInfo).fastpathEncMapInt32Uint64R, (*decFnInfo).fastpathDecMapInt32Uint64R) + fn(map[int32]uintptr(nil), (*encFnInfo).fastpathEncMapInt32UintptrR, (*decFnInfo).fastpathDecMapInt32UintptrR) + fn(map[int32]int(nil), (*encFnInfo).fastpathEncMapInt32IntR, (*decFnInfo).fastpathDecMapInt32IntR) + fn(map[int32]int8(nil), (*encFnInfo).fastpathEncMapInt32Int8R, (*decFnInfo).fastpathDecMapInt32Int8R) + fn(map[int32]int16(nil), (*encFnInfo).fastpathEncMapInt32Int16R, (*decFnInfo).fastpathDecMapInt32Int16R) + fn(map[int32]int32(nil), (*encFnInfo).fastpathEncMapInt32Int32R, (*decFnInfo).fastpathDecMapInt32Int32R) + fn(map[int32]int64(nil), (*encFnInfo).fastpathEncMapInt32Int64R, (*decFnInfo).fastpathDecMapInt32Int64R) + fn(map[int32]float32(nil), (*encFnInfo).fastpathEncMapInt32Float32R, (*decFnInfo).fastpathDecMapInt32Float32R) + fn(map[int32]float64(nil), (*encFnInfo).fastpathEncMapInt32Float64R, (*decFnInfo).fastpathDecMapInt32Float64R) + fn(map[int32]bool(nil), (*encFnInfo).fastpathEncMapInt32BoolR, (*decFnInfo).fastpathDecMapInt32BoolR) + fn(map[int64]interface{}(nil), (*encFnInfo).fastpathEncMapInt64IntfR, (*decFnInfo).fastpathDecMapInt64IntfR) + fn(map[int64]string(nil), (*encFnInfo).fastpathEncMapInt64StringR, (*decFnInfo).fastpathDecMapInt64StringR) + fn(map[int64]uint(nil), (*encFnInfo).fastpathEncMapInt64UintR, (*decFnInfo).fastpathDecMapInt64UintR) + fn(map[int64]uint8(nil), (*encFnInfo).fastpathEncMapInt64Uint8R, (*decFnInfo).fastpathDecMapInt64Uint8R) + fn(map[int64]uint16(nil), (*encFnInfo).fastpathEncMapInt64Uint16R, (*decFnInfo).fastpathDecMapInt64Uint16R) + fn(map[int64]uint32(nil), (*encFnInfo).fastpathEncMapInt64Uint32R, (*decFnInfo).fastpathDecMapInt64Uint32R) + fn(map[int64]uint64(nil), (*encFnInfo).fastpathEncMapInt64Uint64R, (*decFnInfo).fastpathDecMapInt64Uint64R) + fn(map[int64]uintptr(nil), (*encFnInfo).fastpathEncMapInt64UintptrR, (*decFnInfo).fastpathDecMapInt64UintptrR) + fn(map[int64]int(nil), (*encFnInfo).fastpathEncMapInt64IntR, (*decFnInfo).fastpathDecMapInt64IntR) + fn(map[int64]int8(nil), (*encFnInfo).fastpathEncMapInt64Int8R, (*decFnInfo).fastpathDecMapInt64Int8R) + fn(map[int64]int16(nil), (*encFnInfo).fastpathEncMapInt64Int16R, (*decFnInfo).fastpathDecMapInt64Int16R) + fn(map[int64]int32(nil), (*encFnInfo).fastpathEncMapInt64Int32R, (*decFnInfo).fastpathDecMapInt64Int32R) + fn(map[int64]int64(nil), (*encFnInfo).fastpathEncMapInt64Int64R, (*decFnInfo).fastpathDecMapInt64Int64R) + fn(map[int64]float32(nil), (*encFnInfo).fastpathEncMapInt64Float32R, (*decFnInfo).fastpathDecMapInt64Float32R) + fn(map[int64]float64(nil), (*encFnInfo).fastpathEncMapInt64Float64R, (*decFnInfo).fastpathDecMapInt64Float64R) + fn(map[int64]bool(nil), (*encFnInfo).fastpathEncMapInt64BoolR, (*decFnInfo).fastpathDecMapInt64BoolR) + fn(map[bool]interface{}(nil), (*encFnInfo).fastpathEncMapBoolIntfR, (*decFnInfo).fastpathDecMapBoolIntfR) + fn(map[bool]string(nil), (*encFnInfo).fastpathEncMapBoolStringR, (*decFnInfo).fastpathDecMapBoolStringR) + fn(map[bool]uint(nil), (*encFnInfo).fastpathEncMapBoolUintR, (*decFnInfo).fastpathDecMapBoolUintR) + fn(map[bool]uint8(nil), (*encFnInfo).fastpathEncMapBoolUint8R, (*decFnInfo).fastpathDecMapBoolUint8R) + fn(map[bool]uint16(nil), (*encFnInfo).fastpathEncMapBoolUint16R, (*decFnInfo).fastpathDecMapBoolUint16R) + fn(map[bool]uint32(nil), (*encFnInfo).fastpathEncMapBoolUint32R, (*decFnInfo).fastpathDecMapBoolUint32R) + fn(map[bool]uint64(nil), (*encFnInfo).fastpathEncMapBoolUint64R, (*decFnInfo).fastpathDecMapBoolUint64R) + fn(map[bool]uintptr(nil), (*encFnInfo).fastpathEncMapBoolUintptrR, (*decFnInfo).fastpathDecMapBoolUintptrR) + fn(map[bool]int(nil), (*encFnInfo).fastpathEncMapBoolIntR, (*decFnInfo).fastpathDecMapBoolIntR) + fn(map[bool]int8(nil), (*encFnInfo).fastpathEncMapBoolInt8R, (*decFnInfo).fastpathDecMapBoolInt8R) + fn(map[bool]int16(nil), (*encFnInfo).fastpathEncMapBoolInt16R, (*decFnInfo).fastpathDecMapBoolInt16R) + fn(map[bool]int32(nil), (*encFnInfo).fastpathEncMapBoolInt32R, (*decFnInfo).fastpathDecMapBoolInt32R) + fn(map[bool]int64(nil), (*encFnInfo).fastpathEncMapBoolInt64R, (*decFnInfo).fastpathDecMapBoolInt64R) + fn(map[bool]float32(nil), (*encFnInfo).fastpathEncMapBoolFloat32R, (*decFnInfo).fastpathDecMapBoolFloat32R) + fn(map[bool]float64(nil), (*encFnInfo).fastpathEncMapBoolFloat64R, (*decFnInfo).fastpathDecMapBoolFloat64R) + fn(map[bool]bool(nil), (*encFnInfo).fastpathEncMapBoolBoolR, (*decFnInfo).fastpathDecMapBoolBoolR) + + sort.Sort(fastpathAslice(fastpathAV[:])) +} + +// -- encode + +// -- -- fast path type switch +func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { + + case []interface{}: + fastpathTV.EncSliceIntfV(v, fastpathCheckNilTrue, e) + case *[]interface{}: + fastpathTV.EncSliceIntfV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]interface{}: + fastpathTV.EncMapIntfIntfV(v, fastpathCheckNilTrue, e) + case *map[interface{}]interface{}: + fastpathTV.EncMapIntfIntfV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]string: + fastpathTV.EncMapIntfStringV(v, fastpathCheckNilTrue, e) + case *map[interface{}]string: + fastpathTV.EncMapIntfStringV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint: + fastpathTV.EncMapIntfUintV(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint: + fastpathTV.EncMapIntfUintV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint8: + fastpathTV.EncMapIntfUint8V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint8: + fastpathTV.EncMapIntfUint8V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint16: + fastpathTV.EncMapIntfUint16V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint16: + fastpathTV.EncMapIntfUint16V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint32: + fastpathTV.EncMapIntfUint32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint32: + fastpathTV.EncMapIntfUint32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint64: + fastpathTV.EncMapIntfUint64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint64: + fastpathTV.EncMapIntfUint64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uintptr: + fastpathTV.EncMapIntfUintptrV(v, fastpathCheckNilTrue, e) + case *map[interface{}]uintptr: + fastpathTV.EncMapIntfUintptrV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int: + fastpathTV.EncMapIntfIntV(v, fastpathCheckNilTrue, e) + case *map[interface{}]int: + fastpathTV.EncMapIntfIntV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int8: + fastpathTV.EncMapIntfInt8V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int8: + fastpathTV.EncMapIntfInt8V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int16: + fastpathTV.EncMapIntfInt16V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int16: + fastpathTV.EncMapIntfInt16V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int32: + fastpathTV.EncMapIntfInt32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int32: + fastpathTV.EncMapIntfInt32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int64: + fastpathTV.EncMapIntfInt64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int64: + fastpathTV.EncMapIntfInt64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]float32: + fastpathTV.EncMapIntfFloat32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]float32: + fastpathTV.EncMapIntfFloat32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]float64: + fastpathTV.EncMapIntfFloat64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]float64: + fastpathTV.EncMapIntfFloat64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]bool: + fastpathTV.EncMapIntfBoolV(v, fastpathCheckNilTrue, e) + case *map[interface{}]bool: + fastpathTV.EncMapIntfBoolV(*v, fastpathCheckNilTrue, e) + + case []string: + fastpathTV.EncSliceStringV(v, fastpathCheckNilTrue, e) + case *[]string: + fastpathTV.EncSliceStringV(*v, fastpathCheckNilTrue, e) + + case map[string]interface{}: + fastpathTV.EncMapStringIntfV(v, fastpathCheckNilTrue, e) + case *map[string]interface{}: + fastpathTV.EncMapStringIntfV(*v, fastpathCheckNilTrue, e) + + case map[string]string: + fastpathTV.EncMapStringStringV(v, fastpathCheckNilTrue, e) + case *map[string]string: + fastpathTV.EncMapStringStringV(*v, fastpathCheckNilTrue, e) + + case map[string]uint: + fastpathTV.EncMapStringUintV(v, fastpathCheckNilTrue, e) + case *map[string]uint: + fastpathTV.EncMapStringUintV(*v, fastpathCheckNilTrue, e) + + case map[string]uint8: + fastpathTV.EncMapStringUint8V(v, fastpathCheckNilTrue, e) + case *map[string]uint8: + fastpathTV.EncMapStringUint8V(*v, fastpathCheckNilTrue, e) + + case map[string]uint16: + fastpathTV.EncMapStringUint16V(v, fastpathCheckNilTrue, e) + case *map[string]uint16: + fastpathTV.EncMapStringUint16V(*v, fastpathCheckNilTrue, e) + + case map[string]uint32: + fastpathTV.EncMapStringUint32V(v, fastpathCheckNilTrue, e) + case *map[string]uint32: + fastpathTV.EncMapStringUint32V(*v, fastpathCheckNilTrue, e) + + case map[string]uint64: + fastpathTV.EncMapStringUint64V(v, fastpathCheckNilTrue, e) + case *map[string]uint64: + fastpathTV.EncMapStringUint64V(*v, fastpathCheckNilTrue, e) + + case map[string]uintptr: + fastpathTV.EncMapStringUintptrV(v, fastpathCheckNilTrue, e) + case *map[string]uintptr: + fastpathTV.EncMapStringUintptrV(*v, fastpathCheckNilTrue, e) + + case map[string]int: + fastpathTV.EncMapStringIntV(v, fastpathCheckNilTrue, e) + case *map[string]int: + fastpathTV.EncMapStringIntV(*v, fastpathCheckNilTrue, e) + + case map[string]int8: + fastpathTV.EncMapStringInt8V(v, fastpathCheckNilTrue, e) + case *map[string]int8: + fastpathTV.EncMapStringInt8V(*v, fastpathCheckNilTrue, e) + + case map[string]int16: + fastpathTV.EncMapStringInt16V(v, fastpathCheckNilTrue, e) + case *map[string]int16: + fastpathTV.EncMapStringInt16V(*v, fastpathCheckNilTrue, e) + + case map[string]int32: + fastpathTV.EncMapStringInt32V(v, fastpathCheckNilTrue, e) + case *map[string]int32: + fastpathTV.EncMapStringInt32V(*v, fastpathCheckNilTrue, e) + + case map[string]int64: + fastpathTV.EncMapStringInt64V(v, fastpathCheckNilTrue, e) + case *map[string]int64: + fastpathTV.EncMapStringInt64V(*v, fastpathCheckNilTrue, e) + + case map[string]float32: + fastpathTV.EncMapStringFloat32V(v, fastpathCheckNilTrue, e) + case *map[string]float32: + fastpathTV.EncMapStringFloat32V(*v, fastpathCheckNilTrue, e) + + case map[string]float64: + fastpathTV.EncMapStringFloat64V(v, fastpathCheckNilTrue, e) + case *map[string]float64: + fastpathTV.EncMapStringFloat64V(*v, fastpathCheckNilTrue, e) + + case map[string]bool: + fastpathTV.EncMapStringBoolV(v, fastpathCheckNilTrue, e) + case *map[string]bool: + fastpathTV.EncMapStringBoolV(*v, fastpathCheckNilTrue, e) + + case []float32: + fastpathTV.EncSliceFloat32V(v, fastpathCheckNilTrue, e) + case *[]float32: + fastpathTV.EncSliceFloat32V(*v, fastpathCheckNilTrue, e) + + case map[float32]interface{}: + fastpathTV.EncMapFloat32IntfV(v, fastpathCheckNilTrue, e) + case *map[float32]interface{}: + fastpathTV.EncMapFloat32IntfV(*v, fastpathCheckNilTrue, e) + + case map[float32]string: + fastpathTV.EncMapFloat32StringV(v, fastpathCheckNilTrue, e) + case *map[float32]string: + fastpathTV.EncMapFloat32StringV(*v, fastpathCheckNilTrue, e) + + case map[float32]uint: + fastpathTV.EncMapFloat32UintV(v, fastpathCheckNilTrue, e) + case *map[float32]uint: + fastpathTV.EncMapFloat32UintV(*v, fastpathCheckNilTrue, e) + + case map[float32]uint8: + fastpathTV.EncMapFloat32Uint8V(v, fastpathCheckNilTrue, e) + case *map[float32]uint8: + fastpathTV.EncMapFloat32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint16: + fastpathTV.EncMapFloat32Uint16V(v, fastpathCheckNilTrue, e) + case *map[float32]uint16: + fastpathTV.EncMapFloat32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint32: + fastpathTV.EncMapFloat32Uint32V(v, fastpathCheckNilTrue, e) + case *map[float32]uint32: + fastpathTV.EncMapFloat32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint64: + fastpathTV.EncMapFloat32Uint64V(v, fastpathCheckNilTrue, e) + case *map[float32]uint64: + fastpathTV.EncMapFloat32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[float32]uintptr: + fastpathTV.EncMapFloat32UintptrV(v, fastpathCheckNilTrue, e) + case *map[float32]uintptr: + fastpathTV.EncMapFloat32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[float32]int: + fastpathTV.EncMapFloat32IntV(v, fastpathCheckNilTrue, e) + case *map[float32]int: + fastpathTV.EncMapFloat32IntV(*v, fastpathCheckNilTrue, e) + + case map[float32]int8: + fastpathTV.EncMapFloat32Int8V(v, fastpathCheckNilTrue, e) + case *map[float32]int8: + fastpathTV.EncMapFloat32Int8V(*v, fastpathCheckNilTrue, e) + + case map[float32]int16: + fastpathTV.EncMapFloat32Int16V(v, fastpathCheckNilTrue, e) + case *map[float32]int16: + fastpathTV.EncMapFloat32Int16V(*v, fastpathCheckNilTrue, e) + + case map[float32]int32: + fastpathTV.EncMapFloat32Int32V(v, fastpathCheckNilTrue, e) + case *map[float32]int32: + fastpathTV.EncMapFloat32Int32V(*v, fastpathCheckNilTrue, e) + + case map[float32]int64: + fastpathTV.EncMapFloat32Int64V(v, fastpathCheckNilTrue, e) + case *map[float32]int64: + fastpathTV.EncMapFloat32Int64V(*v, fastpathCheckNilTrue, e) + + case map[float32]float32: + fastpathTV.EncMapFloat32Float32V(v, fastpathCheckNilTrue, e) + case *map[float32]float32: + fastpathTV.EncMapFloat32Float32V(*v, fastpathCheckNilTrue, e) + + case map[float32]float64: + fastpathTV.EncMapFloat32Float64V(v, fastpathCheckNilTrue, e) + case *map[float32]float64: + fastpathTV.EncMapFloat32Float64V(*v, fastpathCheckNilTrue, e) + + case map[float32]bool: + fastpathTV.EncMapFloat32BoolV(v, fastpathCheckNilTrue, e) + case *map[float32]bool: + fastpathTV.EncMapFloat32BoolV(*v, fastpathCheckNilTrue, e) + + case []float64: + fastpathTV.EncSliceFloat64V(v, fastpathCheckNilTrue, e) + case *[]float64: + fastpathTV.EncSliceFloat64V(*v, fastpathCheckNilTrue, e) + + case map[float64]interface{}: + fastpathTV.EncMapFloat64IntfV(v, fastpathCheckNilTrue, e) + case *map[float64]interface{}: + fastpathTV.EncMapFloat64IntfV(*v, fastpathCheckNilTrue, e) + + case map[float64]string: + fastpathTV.EncMapFloat64StringV(v, fastpathCheckNilTrue, e) + case *map[float64]string: + fastpathTV.EncMapFloat64StringV(*v, fastpathCheckNilTrue, e) + + case map[float64]uint: + fastpathTV.EncMapFloat64UintV(v, fastpathCheckNilTrue, e) + case *map[float64]uint: + fastpathTV.EncMapFloat64UintV(*v, fastpathCheckNilTrue, e) + + case map[float64]uint8: + fastpathTV.EncMapFloat64Uint8V(v, fastpathCheckNilTrue, e) + case *map[float64]uint8: + fastpathTV.EncMapFloat64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint16: + fastpathTV.EncMapFloat64Uint16V(v, fastpathCheckNilTrue, e) + case *map[float64]uint16: + fastpathTV.EncMapFloat64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint32: + fastpathTV.EncMapFloat64Uint32V(v, fastpathCheckNilTrue, e) + case *map[float64]uint32: + fastpathTV.EncMapFloat64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint64: + fastpathTV.EncMapFloat64Uint64V(v, fastpathCheckNilTrue, e) + case *map[float64]uint64: + fastpathTV.EncMapFloat64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[float64]uintptr: + fastpathTV.EncMapFloat64UintptrV(v, fastpathCheckNilTrue, e) + case *map[float64]uintptr: + fastpathTV.EncMapFloat64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[float64]int: + fastpathTV.EncMapFloat64IntV(v, fastpathCheckNilTrue, e) + case *map[float64]int: + fastpathTV.EncMapFloat64IntV(*v, fastpathCheckNilTrue, e) + + case map[float64]int8: + fastpathTV.EncMapFloat64Int8V(v, fastpathCheckNilTrue, e) + case *map[float64]int8: + fastpathTV.EncMapFloat64Int8V(*v, fastpathCheckNilTrue, e) + + case map[float64]int16: + fastpathTV.EncMapFloat64Int16V(v, fastpathCheckNilTrue, e) + case *map[float64]int16: + fastpathTV.EncMapFloat64Int16V(*v, fastpathCheckNilTrue, e) + + case map[float64]int32: + fastpathTV.EncMapFloat64Int32V(v, fastpathCheckNilTrue, e) + case *map[float64]int32: + fastpathTV.EncMapFloat64Int32V(*v, fastpathCheckNilTrue, e) + + case map[float64]int64: + fastpathTV.EncMapFloat64Int64V(v, fastpathCheckNilTrue, e) + case *map[float64]int64: + fastpathTV.EncMapFloat64Int64V(*v, fastpathCheckNilTrue, e) + + case map[float64]float32: + fastpathTV.EncMapFloat64Float32V(v, fastpathCheckNilTrue, e) + case *map[float64]float32: + fastpathTV.EncMapFloat64Float32V(*v, fastpathCheckNilTrue, e) + + case map[float64]float64: + fastpathTV.EncMapFloat64Float64V(v, fastpathCheckNilTrue, e) + case *map[float64]float64: + fastpathTV.EncMapFloat64Float64V(*v, fastpathCheckNilTrue, e) + + case map[float64]bool: + fastpathTV.EncMapFloat64BoolV(v, fastpathCheckNilTrue, e) + case *map[float64]bool: + fastpathTV.EncMapFloat64BoolV(*v, fastpathCheckNilTrue, e) + + case []uint: + fastpathTV.EncSliceUintV(v, fastpathCheckNilTrue, e) + case *[]uint: + fastpathTV.EncSliceUintV(*v, fastpathCheckNilTrue, e) + + case map[uint]interface{}: + fastpathTV.EncMapUintIntfV(v, fastpathCheckNilTrue, e) + case *map[uint]interface{}: + fastpathTV.EncMapUintIntfV(*v, fastpathCheckNilTrue, e) + + case map[uint]string: + fastpathTV.EncMapUintStringV(v, fastpathCheckNilTrue, e) + case *map[uint]string: + fastpathTV.EncMapUintStringV(*v, fastpathCheckNilTrue, e) + + case map[uint]uint: + fastpathTV.EncMapUintUintV(v, fastpathCheckNilTrue, e) + case *map[uint]uint: + fastpathTV.EncMapUintUintV(*v, fastpathCheckNilTrue, e) + + case map[uint]uint8: + fastpathTV.EncMapUintUint8V(v, fastpathCheckNilTrue, e) + case *map[uint]uint8: + fastpathTV.EncMapUintUint8V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint16: + fastpathTV.EncMapUintUint16V(v, fastpathCheckNilTrue, e) + case *map[uint]uint16: + fastpathTV.EncMapUintUint16V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint32: + fastpathTV.EncMapUintUint32V(v, fastpathCheckNilTrue, e) + case *map[uint]uint32: + fastpathTV.EncMapUintUint32V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint64: + fastpathTV.EncMapUintUint64V(v, fastpathCheckNilTrue, e) + case *map[uint]uint64: + fastpathTV.EncMapUintUint64V(*v, fastpathCheckNilTrue, e) + + case map[uint]uintptr: + fastpathTV.EncMapUintUintptrV(v, fastpathCheckNilTrue, e) + case *map[uint]uintptr: + fastpathTV.EncMapUintUintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint]int: + fastpathTV.EncMapUintIntV(v, fastpathCheckNilTrue, e) + case *map[uint]int: + fastpathTV.EncMapUintIntV(*v, fastpathCheckNilTrue, e) + + case map[uint]int8: + fastpathTV.EncMapUintInt8V(v, fastpathCheckNilTrue, e) + case *map[uint]int8: + fastpathTV.EncMapUintInt8V(*v, fastpathCheckNilTrue, e) + + case map[uint]int16: + fastpathTV.EncMapUintInt16V(v, fastpathCheckNilTrue, e) + case *map[uint]int16: + fastpathTV.EncMapUintInt16V(*v, fastpathCheckNilTrue, e) + + case map[uint]int32: + fastpathTV.EncMapUintInt32V(v, fastpathCheckNilTrue, e) + case *map[uint]int32: + fastpathTV.EncMapUintInt32V(*v, fastpathCheckNilTrue, e) + + case map[uint]int64: + fastpathTV.EncMapUintInt64V(v, fastpathCheckNilTrue, e) + case *map[uint]int64: + fastpathTV.EncMapUintInt64V(*v, fastpathCheckNilTrue, e) + + case map[uint]float32: + fastpathTV.EncMapUintFloat32V(v, fastpathCheckNilTrue, e) + case *map[uint]float32: + fastpathTV.EncMapUintFloat32V(*v, fastpathCheckNilTrue, e) + + case map[uint]float64: + fastpathTV.EncMapUintFloat64V(v, fastpathCheckNilTrue, e) + case *map[uint]float64: + fastpathTV.EncMapUintFloat64V(*v, fastpathCheckNilTrue, e) + + case map[uint]bool: + fastpathTV.EncMapUintBoolV(v, fastpathCheckNilTrue, e) + case *map[uint]bool: + fastpathTV.EncMapUintBoolV(*v, fastpathCheckNilTrue, e) + + case map[uint8]interface{}: + fastpathTV.EncMapUint8IntfV(v, fastpathCheckNilTrue, e) + case *map[uint8]interface{}: + fastpathTV.EncMapUint8IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint8]string: + fastpathTV.EncMapUint8StringV(v, fastpathCheckNilTrue, e) + case *map[uint8]string: + fastpathTV.EncMapUint8StringV(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint: + fastpathTV.EncMapUint8UintV(v, fastpathCheckNilTrue, e) + case *map[uint8]uint: + fastpathTV.EncMapUint8UintV(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint8: + fastpathTV.EncMapUint8Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint8: + fastpathTV.EncMapUint8Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint16: + fastpathTV.EncMapUint8Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint16: + fastpathTV.EncMapUint8Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint32: + fastpathTV.EncMapUint8Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint32: + fastpathTV.EncMapUint8Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint64: + fastpathTV.EncMapUint8Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint64: + fastpathTV.EncMapUint8Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uintptr: + fastpathTV.EncMapUint8UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint8]uintptr: + fastpathTV.EncMapUint8UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint8]int: + fastpathTV.EncMapUint8IntV(v, fastpathCheckNilTrue, e) + case *map[uint8]int: + fastpathTV.EncMapUint8IntV(*v, fastpathCheckNilTrue, e) + + case map[uint8]int8: + fastpathTV.EncMapUint8Int8V(v, fastpathCheckNilTrue, e) + case *map[uint8]int8: + fastpathTV.EncMapUint8Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int16: + fastpathTV.EncMapUint8Int16V(v, fastpathCheckNilTrue, e) + case *map[uint8]int16: + fastpathTV.EncMapUint8Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int32: + fastpathTV.EncMapUint8Int32V(v, fastpathCheckNilTrue, e) + case *map[uint8]int32: + fastpathTV.EncMapUint8Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int64: + fastpathTV.EncMapUint8Int64V(v, fastpathCheckNilTrue, e) + case *map[uint8]int64: + fastpathTV.EncMapUint8Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]float32: + fastpathTV.EncMapUint8Float32V(v, fastpathCheckNilTrue, e) + case *map[uint8]float32: + fastpathTV.EncMapUint8Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]float64: + fastpathTV.EncMapUint8Float64V(v, fastpathCheckNilTrue, e) + case *map[uint8]float64: + fastpathTV.EncMapUint8Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]bool: + fastpathTV.EncMapUint8BoolV(v, fastpathCheckNilTrue, e) + case *map[uint8]bool: + fastpathTV.EncMapUint8BoolV(*v, fastpathCheckNilTrue, e) + + case []uint16: + fastpathTV.EncSliceUint16V(v, fastpathCheckNilTrue, e) + case *[]uint16: + fastpathTV.EncSliceUint16V(*v, fastpathCheckNilTrue, e) + + case map[uint16]interface{}: + fastpathTV.EncMapUint16IntfV(v, fastpathCheckNilTrue, e) + case *map[uint16]interface{}: + fastpathTV.EncMapUint16IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint16]string: + fastpathTV.EncMapUint16StringV(v, fastpathCheckNilTrue, e) + case *map[uint16]string: + fastpathTV.EncMapUint16StringV(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint: + fastpathTV.EncMapUint16UintV(v, fastpathCheckNilTrue, e) + case *map[uint16]uint: + fastpathTV.EncMapUint16UintV(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint8: + fastpathTV.EncMapUint16Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint8: + fastpathTV.EncMapUint16Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint16: + fastpathTV.EncMapUint16Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint16: + fastpathTV.EncMapUint16Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint32: + fastpathTV.EncMapUint16Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint32: + fastpathTV.EncMapUint16Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint64: + fastpathTV.EncMapUint16Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint64: + fastpathTV.EncMapUint16Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uintptr: + fastpathTV.EncMapUint16UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint16]uintptr: + fastpathTV.EncMapUint16UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint16]int: + fastpathTV.EncMapUint16IntV(v, fastpathCheckNilTrue, e) + case *map[uint16]int: + fastpathTV.EncMapUint16IntV(*v, fastpathCheckNilTrue, e) + + case map[uint16]int8: + fastpathTV.EncMapUint16Int8V(v, fastpathCheckNilTrue, e) + case *map[uint16]int8: + fastpathTV.EncMapUint16Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int16: + fastpathTV.EncMapUint16Int16V(v, fastpathCheckNilTrue, e) + case *map[uint16]int16: + fastpathTV.EncMapUint16Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int32: + fastpathTV.EncMapUint16Int32V(v, fastpathCheckNilTrue, e) + case *map[uint16]int32: + fastpathTV.EncMapUint16Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int64: + fastpathTV.EncMapUint16Int64V(v, fastpathCheckNilTrue, e) + case *map[uint16]int64: + fastpathTV.EncMapUint16Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]float32: + fastpathTV.EncMapUint16Float32V(v, fastpathCheckNilTrue, e) + case *map[uint16]float32: + fastpathTV.EncMapUint16Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]float64: + fastpathTV.EncMapUint16Float64V(v, fastpathCheckNilTrue, e) + case *map[uint16]float64: + fastpathTV.EncMapUint16Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]bool: + fastpathTV.EncMapUint16BoolV(v, fastpathCheckNilTrue, e) + case *map[uint16]bool: + fastpathTV.EncMapUint16BoolV(*v, fastpathCheckNilTrue, e) + + case []uint32: + fastpathTV.EncSliceUint32V(v, fastpathCheckNilTrue, e) + case *[]uint32: + fastpathTV.EncSliceUint32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]interface{}: + fastpathTV.EncMapUint32IntfV(v, fastpathCheckNilTrue, e) + case *map[uint32]interface{}: + fastpathTV.EncMapUint32IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint32]string: + fastpathTV.EncMapUint32StringV(v, fastpathCheckNilTrue, e) + case *map[uint32]string: + fastpathTV.EncMapUint32StringV(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint: + fastpathTV.EncMapUint32UintV(v, fastpathCheckNilTrue, e) + case *map[uint32]uint: + fastpathTV.EncMapUint32UintV(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint8: + fastpathTV.EncMapUint32Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint8: + fastpathTV.EncMapUint32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint16: + fastpathTV.EncMapUint32Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint16: + fastpathTV.EncMapUint32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint32: + fastpathTV.EncMapUint32Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint32: + fastpathTV.EncMapUint32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint64: + fastpathTV.EncMapUint32Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint64: + fastpathTV.EncMapUint32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uintptr: + fastpathTV.EncMapUint32UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint32]uintptr: + fastpathTV.EncMapUint32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint32]int: + fastpathTV.EncMapUint32IntV(v, fastpathCheckNilTrue, e) + case *map[uint32]int: + fastpathTV.EncMapUint32IntV(*v, fastpathCheckNilTrue, e) + + case map[uint32]int8: + fastpathTV.EncMapUint32Int8V(v, fastpathCheckNilTrue, e) + case *map[uint32]int8: + fastpathTV.EncMapUint32Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int16: + fastpathTV.EncMapUint32Int16V(v, fastpathCheckNilTrue, e) + case *map[uint32]int16: + fastpathTV.EncMapUint32Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int32: + fastpathTV.EncMapUint32Int32V(v, fastpathCheckNilTrue, e) + case *map[uint32]int32: + fastpathTV.EncMapUint32Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int64: + fastpathTV.EncMapUint32Int64V(v, fastpathCheckNilTrue, e) + case *map[uint32]int64: + fastpathTV.EncMapUint32Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]float32: + fastpathTV.EncMapUint32Float32V(v, fastpathCheckNilTrue, e) + case *map[uint32]float32: + fastpathTV.EncMapUint32Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]float64: + fastpathTV.EncMapUint32Float64V(v, fastpathCheckNilTrue, e) + case *map[uint32]float64: + fastpathTV.EncMapUint32Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]bool: + fastpathTV.EncMapUint32BoolV(v, fastpathCheckNilTrue, e) + case *map[uint32]bool: + fastpathTV.EncMapUint32BoolV(*v, fastpathCheckNilTrue, e) + + case []uint64: + fastpathTV.EncSliceUint64V(v, fastpathCheckNilTrue, e) + case *[]uint64: + fastpathTV.EncSliceUint64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]interface{}: + fastpathTV.EncMapUint64IntfV(v, fastpathCheckNilTrue, e) + case *map[uint64]interface{}: + fastpathTV.EncMapUint64IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint64]string: + fastpathTV.EncMapUint64StringV(v, fastpathCheckNilTrue, e) + case *map[uint64]string: + fastpathTV.EncMapUint64StringV(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint: + fastpathTV.EncMapUint64UintV(v, fastpathCheckNilTrue, e) + case *map[uint64]uint: + fastpathTV.EncMapUint64UintV(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint8: + fastpathTV.EncMapUint64Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint8: + fastpathTV.EncMapUint64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint16: + fastpathTV.EncMapUint64Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint16: + fastpathTV.EncMapUint64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint32: + fastpathTV.EncMapUint64Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint32: + fastpathTV.EncMapUint64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint64: + fastpathTV.EncMapUint64Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint64: + fastpathTV.EncMapUint64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uintptr: + fastpathTV.EncMapUint64UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint64]uintptr: + fastpathTV.EncMapUint64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint64]int: + fastpathTV.EncMapUint64IntV(v, fastpathCheckNilTrue, e) + case *map[uint64]int: + fastpathTV.EncMapUint64IntV(*v, fastpathCheckNilTrue, e) + + case map[uint64]int8: + fastpathTV.EncMapUint64Int8V(v, fastpathCheckNilTrue, e) + case *map[uint64]int8: + fastpathTV.EncMapUint64Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int16: + fastpathTV.EncMapUint64Int16V(v, fastpathCheckNilTrue, e) + case *map[uint64]int16: + fastpathTV.EncMapUint64Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int32: + fastpathTV.EncMapUint64Int32V(v, fastpathCheckNilTrue, e) + case *map[uint64]int32: + fastpathTV.EncMapUint64Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int64: + fastpathTV.EncMapUint64Int64V(v, fastpathCheckNilTrue, e) + case *map[uint64]int64: + fastpathTV.EncMapUint64Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]float32: + fastpathTV.EncMapUint64Float32V(v, fastpathCheckNilTrue, e) + case *map[uint64]float32: + fastpathTV.EncMapUint64Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]float64: + fastpathTV.EncMapUint64Float64V(v, fastpathCheckNilTrue, e) + case *map[uint64]float64: + fastpathTV.EncMapUint64Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]bool: + fastpathTV.EncMapUint64BoolV(v, fastpathCheckNilTrue, e) + case *map[uint64]bool: + fastpathTV.EncMapUint64BoolV(*v, fastpathCheckNilTrue, e) + + case []uintptr: + fastpathTV.EncSliceUintptrV(v, fastpathCheckNilTrue, e) + case *[]uintptr: + fastpathTV.EncSliceUintptrV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]interface{}: + fastpathTV.EncMapUintptrIntfV(v, fastpathCheckNilTrue, e) + case *map[uintptr]interface{}: + fastpathTV.EncMapUintptrIntfV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]string: + fastpathTV.EncMapUintptrStringV(v, fastpathCheckNilTrue, e) + case *map[uintptr]string: + fastpathTV.EncMapUintptrStringV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint: + fastpathTV.EncMapUintptrUintV(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint: + fastpathTV.EncMapUintptrUintV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint8: + fastpathTV.EncMapUintptrUint8V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint8: + fastpathTV.EncMapUintptrUint8V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint16: + fastpathTV.EncMapUintptrUint16V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint16: + fastpathTV.EncMapUintptrUint16V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint32: + fastpathTV.EncMapUintptrUint32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint32: + fastpathTV.EncMapUintptrUint32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint64: + fastpathTV.EncMapUintptrUint64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint64: + fastpathTV.EncMapUintptrUint64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uintptr: + fastpathTV.EncMapUintptrUintptrV(v, fastpathCheckNilTrue, e) + case *map[uintptr]uintptr: + fastpathTV.EncMapUintptrUintptrV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int: + fastpathTV.EncMapUintptrIntV(v, fastpathCheckNilTrue, e) + case *map[uintptr]int: + fastpathTV.EncMapUintptrIntV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int8: + fastpathTV.EncMapUintptrInt8V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int8: + fastpathTV.EncMapUintptrInt8V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int16: + fastpathTV.EncMapUintptrInt16V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int16: + fastpathTV.EncMapUintptrInt16V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int32: + fastpathTV.EncMapUintptrInt32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int32: + fastpathTV.EncMapUintptrInt32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int64: + fastpathTV.EncMapUintptrInt64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int64: + fastpathTV.EncMapUintptrInt64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]float32: + fastpathTV.EncMapUintptrFloat32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]float32: + fastpathTV.EncMapUintptrFloat32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]float64: + fastpathTV.EncMapUintptrFloat64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]float64: + fastpathTV.EncMapUintptrFloat64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]bool: + fastpathTV.EncMapUintptrBoolV(v, fastpathCheckNilTrue, e) + case *map[uintptr]bool: + fastpathTV.EncMapUintptrBoolV(*v, fastpathCheckNilTrue, e) + + case []int: + fastpathTV.EncSliceIntV(v, fastpathCheckNilTrue, e) + case *[]int: + fastpathTV.EncSliceIntV(*v, fastpathCheckNilTrue, e) + + case map[int]interface{}: + fastpathTV.EncMapIntIntfV(v, fastpathCheckNilTrue, e) + case *map[int]interface{}: + fastpathTV.EncMapIntIntfV(*v, fastpathCheckNilTrue, e) + + case map[int]string: + fastpathTV.EncMapIntStringV(v, fastpathCheckNilTrue, e) + case *map[int]string: + fastpathTV.EncMapIntStringV(*v, fastpathCheckNilTrue, e) + + case map[int]uint: + fastpathTV.EncMapIntUintV(v, fastpathCheckNilTrue, e) + case *map[int]uint: + fastpathTV.EncMapIntUintV(*v, fastpathCheckNilTrue, e) + + case map[int]uint8: + fastpathTV.EncMapIntUint8V(v, fastpathCheckNilTrue, e) + case *map[int]uint8: + fastpathTV.EncMapIntUint8V(*v, fastpathCheckNilTrue, e) + + case map[int]uint16: + fastpathTV.EncMapIntUint16V(v, fastpathCheckNilTrue, e) + case *map[int]uint16: + fastpathTV.EncMapIntUint16V(*v, fastpathCheckNilTrue, e) + + case map[int]uint32: + fastpathTV.EncMapIntUint32V(v, fastpathCheckNilTrue, e) + case *map[int]uint32: + fastpathTV.EncMapIntUint32V(*v, fastpathCheckNilTrue, e) + + case map[int]uint64: + fastpathTV.EncMapIntUint64V(v, fastpathCheckNilTrue, e) + case *map[int]uint64: + fastpathTV.EncMapIntUint64V(*v, fastpathCheckNilTrue, e) + + case map[int]uintptr: + fastpathTV.EncMapIntUintptrV(v, fastpathCheckNilTrue, e) + case *map[int]uintptr: + fastpathTV.EncMapIntUintptrV(*v, fastpathCheckNilTrue, e) + + case map[int]int: + fastpathTV.EncMapIntIntV(v, fastpathCheckNilTrue, e) + case *map[int]int: + fastpathTV.EncMapIntIntV(*v, fastpathCheckNilTrue, e) + + case map[int]int8: + fastpathTV.EncMapIntInt8V(v, fastpathCheckNilTrue, e) + case *map[int]int8: + fastpathTV.EncMapIntInt8V(*v, fastpathCheckNilTrue, e) + + case map[int]int16: + fastpathTV.EncMapIntInt16V(v, fastpathCheckNilTrue, e) + case *map[int]int16: + fastpathTV.EncMapIntInt16V(*v, fastpathCheckNilTrue, e) + + case map[int]int32: + fastpathTV.EncMapIntInt32V(v, fastpathCheckNilTrue, e) + case *map[int]int32: + fastpathTV.EncMapIntInt32V(*v, fastpathCheckNilTrue, e) + + case map[int]int64: + fastpathTV.EncMapIntInt64V(v, fastpathCheckNilTrue, e) + case *map[int]int64: + fastpathTV.EncMapIntInt64V(*v, fastpathCheckNilTrue, e) + + case map[int]float32: + fastpathTV.EncMapIntFloat32V(v, fastpathCheckNilTrue, e) + case *map[int]float32: + fastpathTV.EncMapIntFloat32V(*v, fastpathCheckNilTrue, e) + + case map[int]float64: + fastpathTV.EncMapIntFloat64V(v, fastpathCheckNilTrue, e) + case *map[int]float64: + fastpathTV.EncMapIntFloat64V(*v, fastpathCheckNilTrue, e) + + case map[int]bool: + fastpathTV.EncMapIntBoolV(v, fastpathCheckNilTrue, e) + case *map[int]bool: + fastpathTV.EncMapIntBoolV(*v, fastpathCheckNilTrue, e) + + case []int8: + fastpathTV.EncSliceInt8V(v, fastpathCheckNilTrue, e) + case *[]int8: + fastpathTV.EncSliceInt8V(*v, fastpathCheckNilTrue, e) + + case map[int8]interface{}: + fastpathTV.EncMapInt8IntfV(v, fastpathCheckNilTrue, e) + case *map[int8]interface{}: + fastpathTV.EncMapInt8IntfV(*v, fastpathCheckNilTrue, e) + + case map[int8]string: + fastpathTV.EncMapInt8StringV(v, fastpathCheckNilTrue, e) + case *map[int8]string: + fastpathTV.EncMapInt8StringV(*v, fastpathCheckNilTrue, e) + + case map[int8]uint: + fastpathTV.EncMapInt8UintV(v, fastpathCheckNilTrue, e) + case *map[int8]uint: + fastpathTV.EncMapInt8UintV(*v, fastpathCheckNilTrue, e) + + case map[int8]uint8: + fastpathTV.EncMapInt8Uint8V(v, fastpathCheckNilTrue, e) + case *map[int8]uint8: + fastpathTV.EncMapInt8Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint16: + fastpathTV.EncMapInt8Uint16V(v, fastpathCheckNilTrue, e) + case *map[int8]uint16: + fastpathTV.EncMapInt8Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint32: + fastpathTV.EncMapInt8Uint32V(v, fastpathCheckNilTrue, e) + case *map[int8]uint32: + fastpathTV.EncMapInt8Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint64: + fastpathTV.EncMapInt8Uint64V(v, fastpathCheckNilTrue, e) + case *map[int8]uint64: + fastpathTV.EncMapInt8Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int8]uintptr: + fastpathTV.EncMapInt8UintptrV(v, fastpathCheckNilTrue, e) + case *map[int8]uintptr: + fastpathTV.EncMapInt8UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int8]int: + fastpathTV.EncMapInt8IntV(v, fastpathCheckNilTrue, e) + case *map[int8]int: + fastpathTV.EncMapInt8IntV(*v, fastpathCheckNilTrue, e) + + case map[int8]int8: + fastpathTV.EncMapInt8Int8V(v, fastpathCheckNilTrue, e) + case *map[int8]int8: + fastpathTV.EncMapInt8Int8V(*v, fastpathCheckNilTrue, e) + + case map[int8]int16: + fastpathTV.EncMapInt8Int16V(v, fastpathCheckNilTrue, e) + case *map[int8]int16: + fastpathTV.EncMapInt8Int16V(*v, fastpathCheckNilTrue, e) + + case map[int8]int32: + fastpathTV.EncMapInt8Int32V(v, fastpathCheckNilTrue, e) + case *map[int8]int32: + fastpathTV.EncMapInt8Int32V(*v, fastpathCheckNilTrue, e) + + case map[int8]int64: + fastpathTV.EncMapInt8Int64V(v, fastpathCheckNilTrue, e) + case *map[int8]int64: + fastpathTV.EncMapInt8Int64V(*v, fastpathCheckNilTrue, e) + + case map[int8]float32: + fastpathTV.EncMapInt8Float32V(v, fastpathCheckNilTrue, e) + case *map[int8]float32: + fastpathTV.EncMapInt8Float32V(*v, fastpathCheckNilTrue, e) + + case map[int8]float64: + fastpathTV.EncMapInt8Float64V(v, fastpathCheckNilTrue, e) + case *map[int8]float64: + fastpathTV.EncMapInt8Float64V(*v, fastpathCheckNilTrue, e) + + case map[int8]bool: + fastpathTV.EncMapInt8BoolV(v, fastpathCheckNilTrue, e) + case *map[int8]bool: + fastpathTV.EncMapInt8BoolV(*v, fastpathCheckNilTrue, e) + + case []int16: + fastpathTV.EncSliceInt16V(v, fastpathCheckNilTrue, e) + case *[]int16: + fastpathTV.EncSliceInt16V(*v, fastpathCheckNilTrue, e) + + case map[int16]interface{}: + fastpathTV.EncMapInt16IntfV(v, fastpathCheckNilTrue, e) + case *map[int16]interface{}: + fastpathTV.EncMapInt16IntfV(*v, fastpathCheckNilTrue, e) + + case map[int16]string: + fastpathTV.EncMapInt16StringV(v, fastpathCheckNilTrue, e) + case *map[int16]string: + fastpathTV.EncMapInt16StringV(*v, fastpathCheckNilTrue, e) + + case map[int16]uint: + fastpathTV.EncMapInt16UintV(v, fastpathCheckNilTrue, e) + case *map[int16]uint: + fastpathTV.EncMapInt16UintV(*v, fastpathCheckNilTrue, e) + + case map[int16]uint8: + fastpathTV.EncMapInt16Uint8V(v, fastpathCheckNilTrue, e) + case *map[int16]uint8: + fastpathTV.EncMapInt16Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint16: + fastpathTV.EncMapInt16Uint16V(v, fastpathCheckNilTrue, e) + case *map[int16]uint16: + fastpathTV.EncMapInt16Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint32: + fastpathTV.EncMapInt16Uint32V(v, fastpathCheckNilTrue, e) + case *map[int16]uint32: + fastpathTV.EncMapInt16Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint64: + fastpathTV.EncMapInt16Uint64V(v, fastpathCheckNilTrue, e) + case *map[int16]uint64: + fastpathTV.EncMapInt16Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int16]uintptr: + fastpathTV.EncMapInt16UintptrV(v, fastpathCheckNilTrue, e) + case *map[int16]uintptr: + fastpathTV.EncMapInt16UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int16]int: + fastpathTV.EncMapInt16IntV(v, fastpathCheckNilTrue, e) + case *map[int16]int: + fastpathTV.EncMapInt16IntV(*v, fastpathCheckNilTrue, e) + + case map[int16]int8: + fastpathTV.EncMapInt16Int8V(v, fastpathCheckNilTrue, e) + case *map[int16]int8: + fastpathTV.EncMapInt16Int8V(*v, fastpathCheckNilTrue, e) + + case map[int16]int16: + fastpathTV.EncMapInt16Int16V(v, fastpathCheckNilTrue, e) + case *map[int16]int16: + fastpathTV.EncMapInt16Int16V(*v, fastpathCheckNilTrue, e) + + case map[int16]int32: + fastpathTV.EncMapInt16Int32V(v, fastpathCheckNilTrue, e) + case *map[int16]int32: + fastpathTV.EncMapInt16Int32V(*v, fastpathCheckNilTrue, e) + + case map[int16]int64: + fastpathTV.EncMapInt16Int64V(v, fastpathCheckNilTrue, e) + case *map[int16]int64: + fastpathTV.EncMapInt16Int64V(*v, fastpathCheckNilTrue, e) + + case map[int16]float32: + fastpathTV.EncMapInt16Float32V(v, fastpathCheckNilTrue, e) + case *map[int16]float32: + fastpathTV.EncMapInt16Float32V(*v, fastpathCheckNilTrue, e) + + case map[int16]float64: + fastpathTV.EncMapInt16Float64V(v, fastpathCheckNilTrue, e) + case *map[int16]float64: + fastpathTV.EncMapInt16Float64V(*v, fastpathCheckNilTrue, e) + + case map[int16]bool: + fastpathTV.EncMapInt16BoolV(v, fastpathCheckNilTrue, e) + case *map[int16]bool: + fastpathTV.EncMapInt16BoolV(*v, fastpathCheckNilTrue, e) + + case []int32: + fastpathTV.EncSliceInt32V(v, fastpathCheckNilTrue, e) + case *[]int32: + fastpathTV.EncSliceInt32V(*v, fastpathCheckNilTrue, e) + + case map[int32]interface{}: + fastpathTV.EncMapInt32IntfV(v, fastpathCheckNilTrue, e) + case *map[int32]interface{}: + fastpathTV.EncMapInt32IntfV(*v, fastpathCheckNilTrue, e) + + case map[int32]string: + fastpathTV.EncMapInt32StringV(v, fastpathCheckNilTrue, e) + case *map[int32]string: + fastpathTV.EncMapInt32StringV(*v, fastpathCheckNilTrue, e) + + case map[int32]uint: + fastpathTV.EncMapInt32UintV(v, fastpathCheckNilTrue, e) + case *map[int32]uint: + fastpathTV.EncMapInt32UintV(*v, fastpathCheckNilTrue, e) + + case map[int32]uint8: + fastpathTV.EncMapInt32Uint8V(v, fastpathCheckNilTrue, e) + case *map[int32]uint8: + fastpathTV.EncMapInt32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint16: + fastpathTV.EncMapInt32Uint16V(v, fastpathCheckNilTrue, e) + case *map[int32]uint16: + fastpathTV.EncMapInt32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint32: + fastpathTV.EncMapInt32Uint32V(v, fastpathCheckNilTrue, e) + case *map[int32]uint32: + fastpathTV.EncMapInt32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint64: + fastpathTV.EncMapInt32Uint64V(v, fastpathCheckNilTrue, e) + case *map[int32]uint64: + fastpathTV.EncMapInt32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int32]uintptr: + fastpathTV.EncMapInt32UintptrV(v, fastpathCheckNilTrue, e) + case *map[int32]uintptr: + fastpathTV.EncMapInt32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int32]int: + fastpathTV.EncMapInt32IntV(v, fastpathCheckNilTrue, e) + case *map[int32]int: + fastpathTV.EncMapInt32IntV(*v, fastpathCheckNilTrue, e) + + case map[int32]int8: + fastpathTV.EncMapInt32Int8V(v, fastpathCheckNilTrue, e) + case *map[int32]int8: + fastpathTV.EncMapInt32Int8V(*v, fastpathCheckNilTrue, e) + + case map[int32]int16: + fastpathTV.EncMapInt32Int16V(v, fastpathCheckNilTrue, e) + case *map[int32]int16: + fastpathTV.EncMapInt32Int16V(*v, fastpathCheckNilTrue, e) + + case map[int32]int32: + fastpathTV.EncMapInt32Int32V(v, fastpathCheckNilTrue, e) + case *map[int32]int32: + fastpathTV.EncMapInt32Int32V(*v, fastpathCheckNilTrue, e) + + case map[int32]int64: + fastpathTV.EncMapInt32Int64V(v, fastpathCheckNilTrue, e) + case *map[int32]int64: + fastpathTV.EncMapInt32Int64V(*v, fastpathCheckNilTrue, e) + + case map[int32]float32: + fastpathTV.EncMapInt32Float32V(v, fastpathCheckNilTrue, e) + case *map[int32]float32: + fastpathTV.EncMapInt32Float32V(*v, fastpathCheckNilTrue, e) + + case map[int32]float64: + fastpathTV.EncMapInt32Float64V(v, fastpathCheckNilTrue, e) + case *map[int32]float64: + fastpathTV.EncMapInt32Float64V(*v, fastpathCheckNilTrue, e) + + case map[int32]bool: + fastpathTV.EncMapInt32BoolV(v, fastpathCheckNilTrue, e) + case *map[int32]bool: + fastpathTV.EncMapInt32BoolV(*v, fastpathCheckNilTrue, e) + + case []int64: + fastpathTV.EncSliceInt64V(v, fastpathCheckNilTrue, e) + case *[]int64: + fastpathTV.EncSliceInt64V(*v, fastpathCheckNilTrue, e) + + case map[int64]interface{}: + fastpathTV.EncMapInt64IntfV(v, fastpathCheckNilTrue, e) + case *map[int64]interface{}: + fastpathTV.EncMapInt64IntfV(*v, fastpathCheckNilTrue, e) + + case map[int64]string: + fastpathTV.EncMapInt64StringV(v, fastpathCheckNilTrue, e) + case *map[int64]string: + fastpathTV.EncMapInt64StringV(*v, fastpathCheckNilTrue, e) + + case map[int64]uint: + fastpathTV.EncMapInt64UintV(v, fastpathCheckNilTrue, e) + case *map[int64]uint: + fastpathTV.EncMapInt64UintV(*v, fastpathCheckNilTrue, e) + + case map[int64]uint8: + fastpathTV.EncMapInt64Uint8V(v, fastpathCheckNilTrue, e) + case *map[int64]uint8: + fastpathTV.EncMapInt64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint16: + fastpathTV.EncMapInt64Uint16V(v, fastpathCheckNilTrue, e) + case *map[int64]uint16: + fastpathTV.EncMapInt64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint32: + fastpathTV.EncMapInt64Uint32V(v, fastpathCheckNilTrue, e) + case *map[int64]uint32: + fastpathTV.EncMapInt64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint64: + fastpathTV.EncMapInt64Uint64V(v, fastpathCheckNilTrue, e) + case *map[int64]uint64: + fastpathTV.EncMapInt64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int64]uintptr: + fastpathTV.EncMapInt64UintptrV(v, fastpathCheckNilTrue, e) + case *map[int64]uintptr: + fastpathTV.EncMapInt64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int64]int: + fastpathTV.EncMapInt64IntV(v, fastpathCheckNilTrue, e) + case *map[int64]int: + fastpathTV.EncMapInt64IntV(*v, fastpathCheckNilTrue, e) + + case map[int64]int8: + fastpathTV.EncMapInt64Int8V(v, fastpathCheckNilTrue, e) + case *map[int64]int8: + fastpathTV.EncMapInt64Int8V(*v, fastpathCheckNilTrue, e) + + case map[int64]int16: + fastpathTV.EncMapInt64Int16V(v, fastpathCheckNilTrue, e) + case *map[int64]int16: + fastpathTV.EncMapInt64Int16V(*v, fastpathCheckNilTrue, e) + + case map[int64]int32: + fastpathTV.EncMapInt64Int32V(v, fastpathCheckNilTrue, e) + case *map[int64]int32: + fastpathTV.EncMapInt64Int32V(*v, fastpathCheckNilTrue, e) + + case map[int64]int64: + fastpathTV.EncMapInt64Int64V(v, fastpathCheckNilTrue, e) + case *map[int64]int64: + fastpathTV.EncMapInt64Int64V(*v, fastpathCheckNilTrue, e) + + case map[int64]float32: + fastpathTV.EncMapInt64Float32V(v, fastpathCheckNilTrue, e) + case *map[int64]float32: + fastpathTV.EncMapInt64Float32V(*v, fastpathCheckNilTrue, e) + + case map[int64]float64: + fastpathTV.EncMapInt64Float64V(v, fastpathCheckNilTrue, e) + case *map[int64]float64: + fastpathTV.EncMapInt64Float64V(*v, fastpathCheckNilTrue, e) + + case map[int64]bool: + fastpathTV.EncMapInt64BoolV(v, fastpathCheckNilTrue, e) + case *map[int64]bool: + fastpathTV.EncMapInt64BoolV(*v, fastpathCheckNilTrue, e) + + case []bool: + fastpathTV.EncSliceBoolV(v, fastpathCheckNilTrue, e) + case *[]bool: + fastpathTV.EncSliceBoolV(*v, fastpathCheckNilTrue, e) + + case map[bool]interface{}: + fastpathTV.EncMapBoolIntfV(v, fastpathCheckNilTrue, e) + case *map[bool]interface{}: + fastpathTV.EncMapBoolIntfV(*v, fastpathCheckNilTrue, e) + + case map[bool]string: + fastpathTV.EncMapBoolStringV(v, fastpathCheckNilTrue, e) + case *map[bool]string: + fastpathTV.EncMapBoolStringV(*v, fastpathCheckNilTrue, e) + + case map[bool]uint: + fastpathTV.EncMapBoolUintV(v, fastpathCheckNilTrue, e) + case *map[bool]uint: + fastpathTV.EncMapBoolUintV(*v, fastpathCheckNilTrue, e) + + case map[bool]uint8: + fastpathTV.EncMapBoolUint8V(v, fastpathCheckNilTrue, e) + case *map[bool]uint8: + fastpathTV.EncMapBoolUint8V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint16: + fastpathTV.EncMapBoolUint16V(v, fastpathCheckNilTrue, e) + case *map[bool]uint16: + fastpathTV.EncMapBoolUint16V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint32: + fastpathTV.EncMapBoolUint32V(v, fastpathCheckNilTrue, e) + case *map[bool]uint32: + fastpathTV.EncMapBoolUint32V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint64: + fastpathTV.EncMapBoolUint64V(v, fastpathCheckNilTrue, e) + case *map[bool]uint64: + fastpathTV.EncMapBoolUint64V(*v, fastpathCheckNilTrue, e) + + case map[bool]uintptr: + fastpathTV.EncMapBoolUintptrV(v, fastpathCheckNilTrue, e) + case *map[bool]uintptr: + fastpathTV.EncMapBoolUintptrV(*v, fastpathCheckNilTrue, e) + + case map[bool]int: + fastpathTV.EncMapBoolIntV(v, fastpathCheckNilTrue, e) + case *map[bool]int: + fastpathTV.EncMapBoolIntV(*v, fastpathCheckNilTrue, e) + + case map[bool]int8: + fastpathTV.EncMapBoolInt8V(v, fastpathCheckNilTrue, e) + case *map[bool]int8: + fastpathTV.EncMapBoolInt8V(*v, fastpathCheckNilTrue, e) + + case map[bool]int16: + fastpathTV.EncMapBoolInt16V(v, fastpathCheckNilTrue, e) + case *map[bool]int16: + fastpathTV.EncMapBoolInt16V(*v, fastpathCheckNilTrue, e) + + case map[bool]int32: + fastpathTV.EncMapBoolInt32V(v, fastpathCheckNilTrue, e) + case *map[bool]int32: + fastpathTV.EncMapBoolInt32V(*v, fastpathCheckNilTrue, e) + + case map[bool]int64: + fastpathTV.EncMapBoolInt64V(v, fastpathCheckNilTrue, e) + case *map[bool]int64: + fastpathTV.EncMapBoolInt64V(*v, fastpathCheckNilTrue, e) + + case map[bool]float32: + fastpathTV.EncMapBoolFloat32V(v, fastpathCheckNilTrue, e) + case *map[bool]float32: + fastpathTV.EncMapBoolFloat32V(*v, fastpathCheckNilTrue, e) + + case map[bool]float64: + fastpathTV.EncMapBoolFloat64V(v, fastpathCheckNilTrue, e) + case *map[bool]float64: + fastpathTV.EncMapBoolFloat64V(*v, fastpathCheckNilTrue, e) + + case map[bool]bool: + fastpathTV.EncMapBoolBoolV(v, fastpathCheckNilTrue, e) + case *map[bool]bool: + fastpathTV.EncMapBoolBoolV(*v, fastpathCheckNilTrue, e) + + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { + + case []interface{}: + fastpathTV.EncSliceIntfV(v, fastpathCheckNilTrue, e) + case *[]interface{}: + fastpathTV.EncSliceIntfV(*v, fastpathCheckNilTrue, e) + + case []string: + fastpathTV.EncSliceStringV(v, fastpathCheckNilTrue, e) + case *[]string: + fastpathTV.EncSliceStringV(*v, fastpathCheckNilTrue, e) + + case []float32: + fastpathTV.EncSliceFloat32V(v, fastpathCheckNilTrue, e) + case *[]float32: + fastpathTV.EncSliceFloat32V(*v, fastpathCheckNilTrue, e) + + case []float64: + fastpathTV.EncSliceFloat64V(v, fastpathCheckNilTrue, e) + case *[]float64: + fastpathTV.EncSliceFloat64V(*v, fastpathCheckNilTrue, e) + + case []uint: + fastpathTV.EncSliceUintV(v, fastpathCheckNilTrue, e) + case *[]uint: + fastpathTV.EncSliceUintV(*v, fastpathCheckNilTrue, e) + + case []uint16: + fastpathTV.EncSliceUint16V(v, fastpathCheckNilTrue, e) + case *[]uint16: + fastpathTV.EncSliceUint16V(*v, fastpathCheckNilTrue, e) + + case []uint32: + fastpathTV.EncSliceUint32V(v, fastpathCheckNilTrue, e) + case *[]uint32: + fastpathTV.EncSliceUint32V(*v, fastpathCheckNilTrue, e) + + case []uint64: + fastpathTV.EncSliceUint64V(v, fastpathCheckNilTrue, e) + case *[]uint64: + fastpathTV.EncSliceUint64V(*v, fastpathCheckNilTrue, e) + + case []uintptr: + fastpathTV.EncSliceUintptrV(v, fastpathCheckNilTrue, e) + case *[]uintptr: + fastpathTV.EncSliceUintptrV(*v, fastpathCheckNilTrue, e) + + case []int: + fastpathTV.EncSliceIntV(v, fastpathCheckNilTrue, e) + case *[]int: + fastpathTV.EncSliceIntV(*v, fastpathCheckNilTrue, e) + + case []int8: + fastpathTV.EncSliceInt8V(v, fastpathCheckNilTrue, e) + case *[]int8: + fastpathTV.EncSliceInt8V(*v, fastpathCheckNilTrue, e) + + case []int16: + fastpathTV.EncSliceInt16V(v, fastpathCheckNilTrue, e) + case *[]int16: + fastpathTV.EncSliceInt16V(*v, fastpathCheckNilTrue, e) + + case []int32: + fastpathTV.EncSliceInt32V(v, fastpathCheckNilTrue, e) + case *[]int32: + fastpathTV.EncSliceInt32V(*v, fastpathCheckNilTrue, e) + + case []int64: + fastpathTV.EncSliceInt64V(v, fastpathCheckNilTrue, e) + case *[]int64: + fastpathTV.EncSliceInt64V(*v, fastpathCheckNilTrue, e) + + case []bool: + fastpathTV.EncSliceBoolV(v, fastpathCheckNilTrue, e) + case *[]bool: + fastpathTV.EncSliceBoolV(*v, fastpathCheckNilTrue, e) + + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { + + case map[interface{}]interface{}: + fastpathTV.EncMapIntfIntfV(v, fastpathCheckNilTrue, e) + case *map[interface{}]interface{}: + fastpathTV.EncMapIntfIntfV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]string: + fastpathTV.EncMapIntfStringV(v, fastpathCheckNilTrue, e) + case *map[interface{}]string: + fastpathTV.EncMapIntfStringV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint: + fastpathTV.EncMapIntfUintV(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint: + fastpathTV.EncMapIntfUintV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint8: + fastpathTV.EncMapIntfUint8V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint8: + fastpathTV.EncMapIntfUint8V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint16: + fastpathTV.EncMapIntfUint16V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint16: + fastpathTV.EncMapIntfUint16V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint32: + fastpathTV.EncMapIntfUint32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint32: + fastpathTV.EncMapIntfUint32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uint64: + fastpathTV.EncMapIntfUint64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]uint64: + fastpathTV.EncMapIntfUint64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]uintptr: + fastpathTV.EncMapIntfUintptrV(v, fastpathCheckNilTrue, e) + case *map[interface{}]uintptr: + fastpathTV.EncMapIntfUintptrV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int: + fastpathTV.EncMapIntfIntV(v, fastpathCheckNilTrue, e) + case *map[interface{}]int: + fastpathTV.EncMapIntfIntV(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int8: + fastpathTV.EncMapIntfInt8V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int8: + fastpathTV.EncMapIntfInt8V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int16: + fastpathTV.EncMapIntfInt16V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int16: + fastpathTV.EncMapIntfInt16V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int32: + fastpathTV.EncMapIntfInt32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int32: + fastpathTV.EncMapIntfInt32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]int64: + fastpathTV.EncMapIntfInt64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]int64: + fastpathTV.EncMapIntfInt64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]float32: + fastpathTV.EncMapIntfFloat32V(v, fastpathCheckNilTrue, e) + case *map[interface{}]float32: + fastpathTV.EncMapIntfFloat32V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]float64: + fastpathTV.EncMapIntfFloat64V(v, fastpathCheckNilTrue, e) + case *map[interface{}]float64: + fastpathTV.EncMapIntfFloat64V(*v, fastpathCheckNilTrue, e) + + case map[interface{}]bool: + fastpathTV.EncMapIntfBoolV(v, fastpathCheckNilTrue, e) + case *map[interface{}]bool: + fastpathTV.EncMapIntfBoolV(*v, fastpathCheckNilTrue, e) + + case map[string]interface{}: + fastpathTV.EncMapStringIntfV(v, fastpathCheckNilTrue, e) + case *map[string]interface{}: + fastpathTV.EncMapStringIntfV(*v, fastpathCheckNilTrue, e) + + case map[string]string: + fastpathTV.EncMapStringStringV(v, fastpathCheckNilTrue, e) + case *map[string]string: + fastpathTV.EncMapStringStringV(*v, fastpathCheckNilTrue, e) + + case map[string]uint: + fastpathTV.EncMapStringUintV(v, fastpathCheckNilTrue, e) + case *map[string]uint: + fastpathTV.EncMapStringUintV(*v, fastpathCheckNilTrue, e) + + case map[string]uint8: + fastpathTV.EncMapStringUint8V(v, fastpathCheckNilTrue, e) + case *map[string]uint8: + fastpathTV.EncMapStringUint8V(*v, fastpathCheckNilTrue, e) + + case map[string]uint16: + fastpathTV.EncMapStringUint16V(v, fastpathCheckNilTrue, e) + case *map[string]uint16: + fastpathTV.EncMapStringUint16V(*v, fastpathCheckNilTrue, e) + + case map[string]uint32: + fastpathTV.EncMapStringUint32V(v, fastpathCheckNilTrue, e) + case *map[string]uint32: + fastpathTV.EncMapStringUint32V(*v, fastpathCheckNilTrue, e) + + case map[string]uint64: + fastpathTV.EncMapStringUint64V(v, fastpathCheckNilTrue, e) + case *map[string]uint64: + fastpathTV.EncMapStringUint64V(*v, fastpathCheckNilTrue, e) + + case map[string]uintptr: + fastpathTV.EncMapStringUintptrV(v, fastpathCheckNilTrue, e) + case *map[string]uintptr: + fastpathTV.EncMapStringUintptrV(*v, fastpathCheckNilTrue, e) + + case map[string]int: + fastpathTV.EncMapStringIntV(v, fastpathCheckNilTrue, e) + case *map[string]int: + fastpathTV.EncMapStringIntV(*v, fastpathCheckNilTrue, e) + + case map[string]int8: + fastpathTV.EncMapStringInt8V(v, fastpathCheckNilTrue, e) + case *map[string]int8: + fastpathTV.EncMapStringInt8V(*v, fastpathCheckNilTrue, e) + + case map[string]int16: + fastpathTV.EncMapStringInt16V(v, fastpathCheckNilTrue, e) + case *map[string]int16: + fastpathTV.EncMapStringInt16V(*v, fastpathCheckNilTrue, e) + + case map[string]int32: + fastpathTV.EncMapStringInt32V(v, fastpathCheckNilTrue, e) + case *map[string]int32: + fastpathTV.EncMapStringInt32V(*v, fastpathCheckNilTrue, e) + + case map[string]int64: + fastpathTV.EncMapStringInt64V(v, fastpathCheckNilTrue, e) + case *map[string]int64: + fastpathTV.EncMapStringInt64V(*v, fastpathCheckNilTrue, e) + + case map[string]float32: + fastpathTV.EncMapStringFloat32V(v, fastpathCheckNilTrue, e) + case *map[string]float32: + fastpathTV.EncMapStringFloat32V(*v, fastpathCheckNilTrue, e) + + case map[string]float64: + fastpathTV.EncMapStringFloat64V(v, fastpathCheckNilTrue, e) + case *map[string]float64: + fastpathTV.EncMapStringFloat64V(*v, fastpathCheckNilTrue, e) + + case map[string]bool: + fastpathTV.EncMapStringBoolV(v, fastpathCheckNilTrue, e) + case *map[string]bool: + fastpathTV.EncMapStringBoolV(*v, fastpathCheckNilTrue, e) + + case map[float32]interface{}: + fastpathTV.EncMapFloat32IntfV(v, fastpathCheckNilTrue, e) + case *map[float32]interface{}: + fastpathTV.EncMapFloat32IntfV(*v, fastpathCheckNilTrue, e) + + case map[float32]string: + fastpathTV.EncMapFloat32StringV(v, fastpathCheckNilTrue, e) + case *map[float32]string: + fastpathTV.EncMapFloat32StringV(*v, fastpathCheckNilTrue, e) + + case map[float32]uint: + fastpathTV.EncMapFloat32UintV(v, fastpathCheckNilTrue, e) + case *map[float32]uint: + fastpathTV.EncMapFloat32UintV(*v, fastpathCheckNilTrue, e) + + case map[float32]uint8: + fastpathTV.EncMapFloat32Uint8V(v, fastpathCheckNilTrue, e) + case *map[float32]uint8: + fastpathTV.EncMapFloat32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint16: + fastpathTV.EncMapFloat32Uint16V(v, fastpathCheckNilTrue, e) + case *map[float32]uint16: + fastpathTV.EncMapFloat32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint32: + fastpathTV.EncMapFloat32Uint32V(v, fastpathCheckNilTrue, e) + case *map[float32]uint32: + fastpathTV.EncMapFloat32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[float32]uint64: + fastpathTV.EncMapFloat32Uint64V(v, fastpathCheckNilTrue, e) + case *map[float32]uint64: + fastpathTV.EncMapFloat32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[float32]uintptr: + fastpathTV.EncMapFloat32UintptrV(v, fastpathCheckNilTrue, e) + case *map[float32]uintptr: + fastpathTV.EncMapFloat32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[float32]int: + fastpathTV.EncMapFloat32IntV(v, fastpathCheckNilTrue, e) + case *map[float32]int: + fastpathTV.EncMapFloat32IntV(*v, fastpathCheckNilTrue, e) + + case map[float32]int8: + fastpathTV.EncMapFloat32Int8V(v, fastpathCheckNilTrue, e) + case *map[float32]int8: + fastpathTV.EncMapFloat32Int8V(*v, fastpathCheckNilTrue, e) + + case map[float32]int16: + fastpathTV.EncMapFloat32Int16V(v, fastpathCheckNilTrue, e) + case *map[float32]int16: + fastpathTV.EncMapFloat32Int16V(*v, fastpathCheckNilTrue, e) + + case map[float32]int32: + fastpathTV.EncMapFloat32Int32V(v, fastpathCheckNilTrue, e) + case *map[float32]int32: + fastpathTV.EncMapFloat32Int32V(*v, fastpathCheckNilTrue, e) + + case map[float32]int64: + fastpathTV.EncMapFloat32Int64V(v, fastpathCheckNilTrue, e) + case *map[float32]int64: + fastpathTV.EncMapFloat32Int64V(*v, fastpathCheckNilTrue, e) + + case map[float32]float32: + fastpathTV.EncMapFloat32Float32V(v, fastpathCheckNilTrue, e) + case *map[float32]float32: + fastpathTV.EncMapFloat32Float32V(*v, fastpathCheckNilTrue, e) + + case map[float32]float64: + fastpathTV.EncMapFloat32Float64V(v, fastpathCheckNilTrue, e) + case *map[float32]float64: + fastpathTV.EncMapFloat32Float64V(*v, fastpathCheckNilTrue, e) + + case map[float32]bool: + fastpathTV.EncMapFloat32BoolV(v, fastpathCheckNilTrue, e) + case *map[float32]bool: + fastpathTV.EncMapFloat32BoolV(*v, fastpathCheckNilTrue, e) + + case map[float64]interface{}: + fastpathTV.EncMapFloat64IntfV(v, fastpathCheckNilTrue, e) + case *map[float64]interface{}: + fastpathTV.EncMapFloat64IntfV(*v, fastpathCheckNilTrue, e) + + case map[float64]string: + fastpathTV.EncMapFloat64StringV(v, fastpathCheckNilTrue, e) + case *map[float64]string: + fastpathTV.EncMapFloat64StringV(*v, fastpathCheckNilTrue, e) + + case map[float64]uint: + fastpathTV.EncMapFloat64UintV(v, fastpathCheckNilTrue, e) + case *map[float64]uint: + fastpathTV.EncMapFloat64UintV(*v, fastpathCheckNilTrue, e) + + case map[float64]uint8: + fastpathTV.EncMapFloat64Uint8V(v, fastpathCheckNilTrue, e) + case *map[float64]uint8: + fastpathTV.EncMapFloat64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint16: + fastpathTV.EncMapFloat64Uint16V(v, fastpathCheckNilTrue, e) + case *map[float64]uint16: + fastpathTV.EncMapFloat64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint32: + fastpathTV.EncMapFloat64Uint32V(v, fastpathCheckNilTrue, e) + case *map[float64]uint32: + fastpathTV.EncMapFloat64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[float64]uint64: + fastpathTV.EncMapFloat64Uint64V(v, fastpathCheckNilTrue, e) + case *map[float64]uint64: + fastpathTV.EncMapFloat64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[float64]uintptr: + fastpathTV.EncMapFloat64UintptrV(v, fastpathCheckNilTrue, e) + case *map[float64]uintptr: + fastpathTV.EncMapFloat64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[float64]int: + fastpathTV.EncMapFloat64IntV(v, fastpathCheckNilTrue, e) + case *map[float64]int: + fastpathTV.EncMapFloat64IntV(*v, fastpathCheckNilTrue, e) + + case map[float64]int8: + fastpathTV.EncMapFloat64Int8V(v, fastpathCheckNilTrue, e) + case *map[float64]int8: + fastpathTV.EncMapFloat64Int8V(*v, fastpathCheckNilTrue, e) + + case map[float64]int16: + fastpathTV.EncMapFloat64Int16V(v, fastpathCheckNilTrue, e) + case *map[float64]int16: + fastpathTV.EncMapFloat64Int16V(*v, fastpathCheckNilTrue, e) + + case map[float64]int32: + fastpathTV.EncMapFloat64Int32V(v, fastpathCheckNilTrue, e) + case *map[float64]int32: + fastpathTV.EncMapFloat64Int32V(*v, fastpathCheckNilTrue, e) + + case map[float64]int64: + fastpathTV.EncMapFloat64Int64V(v, fastpathCheckNilTrue, e) + case *map[float64]int64: + fastpathTV.EncMapFloat64Int64V(*v, fastpathCheckNilTrue, e) + + case map[float64]float32: + fastpathTV.EncMapFloat64Float32V(v, fastpathCheckNilTrue, e) + case *map[float64]float32: + fastpathTV.EncMapFloat64Float32V(*v, fastpathCheckNilTrue, e) + + case map[float64]float64: + fastpathTV.EncMapFloat64Float64V(v, fastpathCheckNilTrue, e) + case *map[float64]float64: + fastpathTV.EncMapFloat64Float64V(*v, fastpathCheckNilTrue, e) + + case map[float64]bool: + fastpathTV.EncMapFloat64BoolV(v, fastpathCheckNilTrue, e) + case *map[float64]bool: + fastpathTV.EncMapFloat64BoolV(*v, fastpathCheckNilTrue, e) + + case map[uint]interface{}: + fastpathTV.EncMapUintIntfV(v, fastpathCheckNilTrue, e) + case *map[uint]interface{}: + fastpathTV.EncMapUintIntfV(*v, fastpathCheckNilTrue, e) + + case map[uint]string: + fastpathTV.EncMapUintStringV(v, fastpathCheckNilTrue, e) + case *map[uint]string: + fastpathTV.EncMapUintStringV(*v, fastpathCheckNilTrue, e) + + case map[uint]uint: + fastpathTV.EncMapUintUintV(v, fastpathCheckNilTrue, e) + case *map[uint]uint: + fastpathTV.EncMapUintUintV(*v, fastpathCheckNilTrue, e) + + case map[uint]uint8: + fastpathTV.EncMapUintUint8V(v, fastpathCheckNilTrue, e) + case *map[uint]uint8: + fastpathTV.EncMapUintUint8V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint16: + fastpathTV.EncMapUintUint16V(v, fastpathCheckNilTrue, e) + case *map[uint]uint16: + fastpathTV.EncMapUintUint16V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint32: + fastpathTV.EncMapUintUint32V(v, fastpathCheckNilTrue, e) + case *map[uint]uint32: + fastpathTV.EncMapUintUint32V(*v, fastpathCheckNilTrue, e) + + case map[uint]uint64: + fastpathTV.EncMapUintUint64V(v, fastpathCheckNilTrue, e) + case *map[uint]uint64: + fastpathTV.EncMapUintUint64V(*v, fastpathCheckNilTrue, e) + + case map[uint]uintptr: + fastpathTV.EncMapUintUintptrV(v, fastpathCheckNilTrue, e) + case *map[uint]uintptr: + fastpathTV.EncMapUintUintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint]int: + fastpathTV.EncMapUintIntV(v, fastpathCheckNilTrue, e) + case *map[uint]int: + fastpathTV.EncMapUintIntV(*v, fastpathCheckNilTrue, e) + + case map[uint]int8: + fastpathTV.EncMapUintInt8V(v, fastpathCheckNilTrue, e) + case *map[uint]int8: + fastpathTV.EncMapUintInt8V(*v, fastpathCheckNilTrue, e) + + case map[uint]int16: + fastpathTV.EncMapUintInt16V(v, fastpathCheckNilTrue, e) + case *map[uint]int16: + fastpathTV.EncMapUintInt16V(*v, fastpathCheckNilTrue, e) + + case map[uint]int32: + fastpathTV.EncMapUintInt32V(v, fastpathCheckNilTrue, e) + case *map[uint]int32: + fastpathTV.EncMapUintInt32V(*v, fastpathCheckNilTrue, e) + + case map[uint]int64: + fastpathTV.EncMapUintInt64V(v, fastpathCheckNilTrue, e) + case *map[uint]int64: + fastpathTV.EncMapUintInt64V(*v, fastpathCheckNilTrue, e) + + case map[uint]float32: + fastpathTV.EncMapUintFloat32V(v, fastpathCheckNilTrue, e) + case *map[uint]float32: + fastpathTV.EncMapUintFloat32V(*v, fastpathCheckNilTrue, e) + + case map[uint]float64: + fastpathTV.EncMapUintFloat64V(v, fastpathCheckNilTrue, e) + case *map[uint]float64: + fastpathTV.EncMapUintFloat64V(*v, fastpathCheckNilTrue, e) + + case map[uint]bool: + fastpathTV.EncMapUintBoolV(v, fastpathCheckNilTrue, e) + case *map[uint]bool: + fastpathTV.EncMapUintBoolV(*v, fastpathCheckNilTrue, e) + + case map[uint8]interface{}: + fastpathTV.EncMapUint8IntfV(v, fastpathCheckNilTrue, e) + case *map[uint8]interface{}: + fastpathTV.EncMapUint8IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint8]string: + fastpathTV.EncMapUint8StringV(v, fastpathCheckNilTrue, e) + case *map[uint8]string: + fastpathTV.EncMapUint8StringV(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint: + fastpathTV.EncMapUint8UintV(v, fastpathCheckNilTrue, e) + case *map[uint8]uint: + fastpathTV.EncMapUint8UintV(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint8: + fastpathTV.EncMapUint8Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint8: + fastpathTV.EncMapUint8Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint16: + fastpathTV.EncMapUint8Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint16: + fastpathTV.EncMapUint8Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint32: + fastpathTV.EncMapUint8Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint32: + fastpathTV.EncMapUint8Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uint64: + fastpathTV.EncMapUint8Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint8]uint64: + fastpathTV.EncMapUint8Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]uintptr: + fastpathTV.EncMapUint8UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint8]uintptr: + fastpathTV.EncMapUint8UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint8]int: + fastpathTV.EncMapUint8IntV(v, fastpathCheckNilTrue, e) + case *map[uint8]int: + fastpathTV.EncMapUint8IntV(*v, fastpathCheckNilTrue, e) + + case map[uint8]int8: + fastpathTV.EncMapUint8Int8V(v, fastpathCheckNilTrue, e) + case *map[uint8]int8: + fastpathTV.EncMapUint8Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int16: + fastpathTV.EncMapUint8Int16V(v, fastpathCheckNilTrue, e) + case *map[uint8]int16: + fastpathTV.EncMapUint8Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int32: + fastpathTV.EncMapUint8Int32V(v, fastpathCheckNilTrue, e) + case *map[uint8]int32: + fastpathTV.EncMapUint8Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]int64: + fastpathTV.EncMapUint8Int64V(v, fastpathCheckNilTrue, e) + case *map[uint8]int64: + fastpathTV.EncMapUint8Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]float32: + fastpathTV.EncMapUint8Float32V(v, fastpathCheckNilTrue, e) + case *map[uint8]float32: + fastpathTV.EncMapUint8Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint8]float64: + fastpathTV.EncMapUint8Float64V(v, fastpathCheckNilTrue, e) + case *map[uint8]float64: + fastpathTV.EncMapUint8Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint8]bool: + fastpathTV.EncMapUint8BoolV(v, fastpathCheckNilTrue, e) + case *map[uint8]bool: + fastpathTV.EncMapUint8BoolV(*v, fastpathCheckNilTrue, e) + + case map[uint16]interface{}: + fastpathTV.EncMapUint16IntfV(v, fastpathCheckNilTrue, e) + case *map[uint16]interface{}: + fastpathTV.EncMapUint16IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint16]string: + fastpathTV.EncMapUint16StringV(v, fastpathCheckNilTrue, e) + case *map[uint16]string: + fastpathTV.EncMapUint16StringV(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint: + fastpathTV.EncMapUint16UintV(v, fastpathCheckNilTrue, e) + case *map[uint16]uint: + fastpathTV.EncMapUint16UintV(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint8: + fastpathTV.EncMapUint16Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint8: + fastpathTV.EncMapUint16Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint16: + fastpathTV.EncMapUint16Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint16: + fastpathTV.EncMapUint16Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint32: + fastpathTV.EncMapUint16Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint32: + fastpathTV.EncMapUint16Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uint64: + fastpathTV.EncMapUint16Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint16]uint64: + fastpathTV.EncMapUint16Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]uintptr: + fastpathTV.EncMapUint16UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint16]uintptr: + fastpathTV.EncMapUint16UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint16]int: + fastpathTV.EncMapUint16IntV(v, fastpathCheckNilTrue, e) + case *map[uint16]int: + fastpathTV.EncMapUint16IntV(*v, fastpathCheckNilTrue, e) + + case map[uint16]int8: + fastpathTV.EncMapUint16Int8V(v, fastpathCheckNilTrue, e) + case *map[uint16]int8: + fastpathTV.EncMapUint16Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int16: + fastpathTV.EncMapUint16Int16V(v, fastpathCheckNilTrue, e) + case *map[uint16]int16: + fastpathTV.EncMapUint16Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int32: + fastpathTV.EncMapUint16Int32V(v, fastpathCheckNilTrue, e) + case *map[uint16]int32: + fastpathTV.EncMapUint16Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]int64: + fastpathTV.EncMapUint16Int64V(v, fastpathCheckNilTrue, e) + case *map[uint16]int64: + fastpathTV.EncMapUint16Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]float32: + fastpathTV.EncMapUint16Float32V(v, fastpathCheckNilTrue, e) + case *map[uint16]float32: + fastpathTV.EncMapUint16Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint16]float64: + fastpathTV.EncMapUint16Float64V(v, fastpathCheckNilTrue, e) + case *map[uint16]float64: + fastpathTV.EncMapUint16Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint16]bool: + fastpathTV.EncMapUint16BoolV(v, fastpathCheckNilTrue, e) + case *map[uint16]bool: + fastpathTV.EncMapUint16BoolV(*v, fastpathCheckNilTrue, e) + + case map[uint32]interface{}: + fastpathTV.EncMapUint32IntfV(v, fastpathCheckNilTrue, e) + case *map[uint32]interface{}: + fastpathTV.EncMapUint32IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint32]string: + fastpathTV.EncMapUint32StringV(v, fastpathCheckNilTrue, e) + case *map[uint32]string: + fastpathTV.EncMapUint32StringV(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint: + fastpathTV.EncMapUint32UintV(v, fastpathCheckNilTrue, e) + case *map[uint32]uint: + fastpathTV.EncMapUint32UintV(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint8: + fastpathTV.EncMapUint32Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint8: + fastpathTV.EncMapUint32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint16: + fastpathTV.EncMapUint32Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint16: + fastpathTV.EncMapUint32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint32: + fastpathTV.EncMapUint32Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint32: + fastpathTV.EncMapUint32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uint64: + fastpathTV.EncMapUint32Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint32]uint64: + fastpathTV.EncMapUint32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]uintptr: + fastpathTV.EncMapUint32UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint32]uintptr: + fastpathTV.EncMapUint32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint32]int: + fastpathTV.EncMapUint32IntV(v, fastpathCheckNilTrue, e) + case *map[uint32]int: + fastpathTV.EncMapUint32IntV(*v, fastpathCheckNilTrue, e) + + case map[uint32]int8: + fastpathTV.EncMapUint32Int8V(v, fastpathCheckNilTrue, e) + case *map[uint32]int8: + fastpathTV.EncMapUint32Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int16: + fastpathTV.EncMapUint32Int16V(v, fastpathCheckNilTrue, e) + case *map[uint32]int16: + fastpathTV.EncMapUint32Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int32: + fastpathTV.EncMapUint32Int32V(v, fastpathCheckNilTrue, e) + case *map[uint32]int32: + fastpathTV.EncMapUint32Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]int64: + fastpathTV.EncMapUint32Int64V(v, fastpathCheckNilTrue, e) + case *map[uint32]int64: + fastpathTV.EncMapUint32Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]float32: + fastpathTV.EncMapUint32Float32V(v, fastpathCheckNilTrue, e) + case *map[uint32]float32: + fastpathTV.EncMapUint32Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint32]float64: + fastpathTV.EncMapUint32Float64V(v, fastpathCheckNilTrue, e) + case *map[uint32]float64: + fastpathTV.EncMapUint32Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint32]bool: + fastpathTV.EncMapUint32BoolV(v, fastpathCheckNilTrue, e) + case *map[uint32]bool: + fastpathTV.EncMapUint32BoolV(*v, fastpathCheckNilTrue, e) + + case map[uint64]interface{}: + fastpathTV.EncMapUint64IntfV(v, fastpathCheckNilTrue, e) + case *map[uint64]interface{}: + fastpathTV.EncMapUint64IntfV(*v, fastpathCheckNilTrue, e) + + case map[uint64]string: + fastpathTV.EncMapUint64StringV(v, fastpathCheckNilTrue, e) + case *map[uint64]string: + fastpathTV.EncMapUint64StringV(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint: + fastpathTV.EncMapUint64UintV(v, fastpathCheckNilTrue, e) + case *map[uint64]uint: + fastpathTV.EncMapUint64UintV(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint8: + fastpathTV.EncMapUint64Uint8V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint8: + fastpathTV.EncMapUint64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint16: + fastpathTV.EncMapUint64Uint16V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint16: + fastpathTV.EncMapUint64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint32: + fastpathTV.EncMapUint64Uint32V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint32: + fastpathTV.EncMapUint64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uint64: + fastpathTV.EncMapUint64Uint64V(v, fastpathCheckNilTrue, e) + case *map[uint64]uint64: + fastpathTV.EncMapUint64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]uintptr: + fastpathTV.EncMapUint64UintptrV(v, fastpathCheckNilTrue, e) + case *map[uint64]uintptr: + fastpathTV.EncMapUint64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[uint64]int: + fastpathTV.EncMapUint64IntV(v, fastpathCheckNilTrue, e) + case *map[uint64]int: + fastpathTV.EncMapUint64IntV(*v, fastpathCheckNilTrue, e) + + case map[uint64]int8: + fastpathTV.EncMapUint64Int8V(v, fastpathCheckNilTrue, e) + case *map[uint64]int8: + fastpathTV.EncMapUint64Int8V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int16: + fastpathTV.EncMapUint64Int16V(v, fastpathCheckNilTrue, e) + case *map[uint64]int16: + fastpathTV.EncMapUint64Int16V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int32: + fastpathTV.EncMapUint64Int32V(v, fastpathCheckNilTrue, e) + case *map[uint64]int32: + fastpathTV.EncMapUint64Int32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]int64: + fastpathTV.EncMapUint64Int64V(v, fastpathCheckNilTrue, e) + case *map[uint64]int64: + fastpathTV.EncMapUint64Int64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]float32: + fastpathTV.EncMapUint64Float32V(v, fastpathCheckNilTrue, e) + case *map[uint64]float32: + fastpathTV.EncMapUint64Float32V(*v, fastpathCheckNilTrue, e) + + case map[uint64]float64: + fastpathTV.EncMapUint64Float64V(v, fastpathCheckNilTrue, e) + case *map[uint64]float64: + fastpathTV.EncMapUint64Float64V(*v, fastpathCheckNilTrue, e) + + case map[uint64]bool: + fastpathTV.EncMapUint64BoolV(v, fastpathCheckNilTrue, e) + case *map[uint64]bool: + fastpathTV.EncMapUint64BoolV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]interface{}: + fastpathTV.EncMapUintptrIntfV(v, fastpathCheckNilTrue, e) + case *map[uintptr]interface{}: + fastpathTV.EncMapUintptrIntfV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]string: + fastpathTV.EncMapUintptrStringV(v, fastpathCheckNilTrue, e) + case *map[uintptr]string: + fastpathTV.EncMapUintptrStringV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint: + fastpathTV.EncMapUintptrUintV(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint: + fastpathTV.EncMapUintptrUintV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint8: + fastpathTV.EncMapUintptrUint8V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint8: + fastpathTV.EncMapUintptrUint8V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint16: + fastpathTV.EncMapUintptrUint16V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint16: + fastpathTV.EncMapUintptrUint16V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint32: + fastpathTV.EncMapUintptrUint32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint32: + fastpathTV.EncMapUintptrUint32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uint64: + fastpathTV.EncMapUintptrUint64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]uint64: + fastpathTV.EncMapUintptrUint64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]uintptr: + fastpathTV.EncMapUintptrUintptrV(v, fastpathCheckNilTrue, e) + case *map[uintptr]uintptr: + fastpathTV.EncMapUintptrUintptrV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int: + fastpathTV.EncMapUintptrIntV(v, fastpathCheckNilTrue, e) + case *map[uintptr]int: + fastpathTV.EncMapUintptrIntV(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int8: + fastpathTV.EncMapUintptrInt8V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int8: + fastpathTV.EncMapUintptrInt8V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int16: + fastpathTV.EncMapUintptrInt16V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int16: + fastpathTV.EncMapUintptrInt16V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int32: + fastpathTV.EncMapUintptrInt32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int32: + fastpathTV.EncMapUintptrInt32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]int64: + fastpathTV.EncMapUintptrInt64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]int64: + fastpathTV.EncMapUintptrInt64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]float32: + fastpathTV.EncMapUintptrFloat32V(v, fastpathCheckNilTrue, e) + case *map[uintptr]float32: + fastpathTV.EncMapUintptrFloat32V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]float64: + fastpathTV.EncMapUintptrFloat64V(v, fastpathCheckNilTrue, e) + case *map[uintptr]float64: + fastpathTV.EncMapUintptrFloat64V(*v, fastpathCheckNilTrue, e) + + case map[uintptr]bool: + fastpathTV.EncMapUintptrBoolV(v, fastpathCheckNilTrue, e) + case *map[uintptr]bool: + fastpathTV.EncMapUintptrBoolV(*v, fastpathCheckNilTrue, e) + + case map[int]interface{}: + fastpathTV.EncMapIntIntfV(v, fastpathCheckNilTrue, e) + case *map[int]interface{}: + fastpathTV.EncMapIntIntfV(*v, fastpathCheckNilTrue, e) + + case map[int]string: + fastpathTV.EncMapIntStringV(v, fastpathCheckNilTrue, e) + case *map[int]string: + fastpathTV.EncMapIntStringV(*v, fastpathCheckNilTrue, e) + + case map[int]uint: + fastpathTV.EncMapIntUintV(v, fastpathCheckNilTrue, e) + case *map[int]uint: + fastpathTV.EncMapIntUintV(*v, fastpathCheckNilTrue, e) + + case map[int]uint8: + fastpathTV.EncMapIntUint8V(v, fastpathCheckNilTrue, e) + case *map[int]uint8: + fastpathTV.EncMapIntUint8V(*v, fastpathCheckNilTrue, e) + + case map[int]uint16: + fastpathTV.EncMapIntUint16V(v, fastpathCheckNilTrue, e) + case *map[int]uint16: + fastpathTV.EncMapIntUint16V(*v, fastpathCheckNilTrue, e) + + case map[int]uint32: + fastpathTV.EncMapIntUint32V(v, fastpathCheckNilTrue, e) + case *map[int]uint32: + fastpathTV.EncMapIntUint32V(*v, fastpathCheckNilTrue, e) + + case map[int]uint64: + fastpathTV.EncMapIntUint64V(v, fastpathCheckNilTrue, e) + case *map[int]uint64: + fastpathTV.EncMapIntUint64V(*v, fastpathCheckNilTrue, e) + + case map[int]uintptr: + fastpathTV.EncMapIntUintptrV(v, fastpathCheckNilTrue, e) + case *map[int]uintptr: + fastpathTV.EncMapIntUintptrV(*v, fastpathCheckNilTrue, e) + + case map[int]int: + fastpathTV.EncMapIntIntV(v, fastpathCheckNilTrue, e) + case *map[int]int: + fastpathTV.EncMapIntIntV(*v, fastpathCheckNilTrue, e) + + case map[int]int8: + fastpathTV.EncMapIntInt8V(v, fastpathCheckNilTrue, e) + case *map[int]int8: + fastpathTV.EncMapIntInt8V(*v, fastpathCheckNilTrue, e) + + case map[int]int16: + fastpathTV.EncMapIntInt16V(v, fastpathCheckNilTrue, e) + case *map[int]int16: + fastpathTV.EncMapIntInt16V(*v, fastpathCheckNilTrue, e) + + case map[int]int32: + fastpathTV.EncMapIntInt32V(v, fastpathCheckNilTrue, e) + case *map[int]int32: + fastpathTV.EncMapIntInt32V(*v, fastpathCheckNilTrue, e) + + case map[int]int64: + fastpathTV.EncMapIntInt64V(v, fastpathCheckNilTrue, e) + case *map[int]int64: + fastpathTV.EncMapIntInt64V(*v, fastpathCheckNilTrue, e) + + case map[int]float32: + fastpathTV.EncMapIntFloat32V(v, fastpathCheckNilTrue, e) + case *map[int]float32: + fastpathTV.EncMapIntFloat32V(*v, fastpathCheckNilTrue, e) + + case map[int]float64: + fastpathTV.EncMapIntFloat64V(v, fastpathCheckNilTrue, e) + case *map[int]float64: + fastpathTV.EncMapIntFloat64V(*v, fastpathCheckNilTrue, e) + + case map[int]bool: + fastpathTV.EncMapIntBoolV(v, fastpathCheckNilTrue, e) + case *map[int]bool: + fastpathTV.EncMapIntBoolV(*v, fastpathCheckNilTrue, e) + + case map[int8]interface{}: + fastpathTV.EncMapInt8IntfV(v, fastpathCheckNilTrue, e) + case *map[int8]interface{}: + fastpathTV.EncMapInt8IntfV(*v, fastpathCheckNilTrue, e) + + case map[int8]string: + fastpathTV.EncMapInt8StringV(v, fastpathCheckNilTrue, e) + case *map[int8]string: + fastpathTV.EncMapInt8StringV(*v, fastpathCheckNilTrue, e) + + case map[int8]uint: + fastpathTV.EncMapInt8UintV(v, fastpathCheckNilTrue, e) + case *map[int8]uint: + fastpathTV.EncMapInt8UintV(*v, fastpathCheckNilTrue, e) + + case map[int8]uint8: + fastpathTV.EncMapInt8Uint8V(v, fastpathCheckNilTrue, e) + case *map[int8]uint8: + fastpathTV.EncMapInt8Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint16: + fastpathTV.EncMapInt8Uint16V(v, fastpathCheckNilTrue, e) + case *map[int8]uint16: + fastpathTV.EncMapInt8Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint32: + fastpathTV.EncMapInt8Uint32V(v, fastpathCheckNilTrue, e) + case *map[int8]uint32: + fastpathTV.EncMapInt8Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int8]uint64: + fastpathTV.EncMapInt8Uint64V(v, fastpathCheckNilTrue, e) + case *map[int8]uint64: + fastpathTV.EncMapInt8Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int8]uintptr: + fastpathTV.EncMapInt8UintptrV(v, fastpathCheckNilTrue, e) + case *map[int8]uintptr: + fastpathTV.EncMapInt8UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int8]int: + fastpathTV.EncMapInt8IntV(v, fastpathCheckNilTrue, e) + case *map[int8]int: + fastpathTV.EncMapInt8IntV(*v, fastpathCheckNilTrue, e) + + case map[int8]int8: + fastpathTV.EncMapInt8Int8V(v, fastpathCheckNilTrue, e) + case *map[int8]int8: + fastpathTV.EncMapInt8Int8V(*v, fastpathCheckNilTrue, e) + + case map[int8]int16: + fastpathTV.EncMapInt8Int16V(v, fastpathCheckNilTrue, e) + case *map[int8]int16: + fastpathTV.EncMapInt8Int16V(*v, fastpathCheckNilTrue, e) + + case map[int8]int32: + fastpathTV.EncMapInt8Int32V(v, fastpathCheckNilTrue, e) + case *map[int8]int32: + fastpathTV.EncMapInt8Int32V(*v, fastpathCheckNilTrue, e) + + case map[int8]int64: + fastpathTV.EncMapInt8Int64V(v, fastpathCheckNilTrue, e) + case *map[int8]int64: + fastpathTV.EncMapInt8Int64V(*v, fastpathCheckNilTrue, e) + + case map[int8]float32: + fastpathTV.EncMapInt8Float32V(v, fastpathCheckNilTrue, e) + case *map[int8]float32: + fastpathTV.EncMapInt8Float32V(*v, fastpathCheckNilTrue, e) + + case map[int8]float64: + fastpathTV.EncMapInt8Float64V(v, fastpathCheckNilTrue, e) + case *map[int8]float64: + fastpathTV.EncMapInt8Float64V(*v, fastpathCheckNilTrue, e) + + case map[int8]bool: + fastpathTV.EncMapInt8BoolV(v, fastpathCheckNilTrue, e) + case *map[int8]bool: + fastpathTV.EncMapInt8BoolV(*v, fastpathCheckNilTrue, e) + + case map[int16]interface{}: + fastpathTV.EncMapInt16IntfV(v, fastpathCheckNilTrue, e) + case *map[int16]interface{}: + fastpathTV.EncMapInt16IntfV(*v, fastpathCheckNilTrue, e) + + case map[int16]string: + fastpathTV.EncMapInt16StringV(v, fastpathCheckNilTrue, e) + case *map[int16]string: + fastpathTV.EncMapInt16StringV(*v, fastpathCheckNilTrue, e) + + case map[int16]uint: + fastpathTV.EncMapInt16UintV(v, fastpathCheckNilTrue, e) + case *map[int16]uint: + fastpathTV.EncMapInt16UintV(*v, fastpathCheckNilTrue, e) + + case map[int16]uint8: + fastpathTV.EncMapInt16Uint8V(v, fastpathCheckNilTrue, e) + case *map[int16]uint8: + fastpathTV.EncMapInt16Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint16: + fastpathTV.EncMapInt16Uint16V(v, fastpathCheckNilTrue, e) + case *map[int16]uint16: + fastpathTV.EncMapInt16Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint32: + fastpathTV.EncMapInt16Uint32V(v, fastpathCheckNilTrue, e) + case *map[int16]uint32: + fastpathTV.EncMapInt16Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int16]uint64: + fastpathTV.EncMapInt16Uint64V(v, fastpathCheckNilTrue, e) + case *map[int16]uint64: + fastpathTV.EncMapInt16Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int16]uintptr: + fastpathTV.EncMapInt16UintptrV(v, fastpathCheckNilTrue, e) + case *map[int16]uintptr: + fastpathTV.EncMapInt16UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int16]int: + fastpathTV.EncMapInt16IntV(v, fastpathCheckNilTrue, e) + case *map[int16]int: + fastpathTV.EncMapInt16IntV(*v, fastpathCheckNilTrue, e) + + case map[int16]int8: + fastpathTV.EncMapInt16Int8V(v, fastpathCheckNilTrue, e) + case *map[int16]int8: + fastpathTV.EncMapInt16Int8V(*v, fastpathCheckNilTrue, e) + + case map[int16]int16: + fastpathTV.EncMapInt16Int16V(v, fastpathCheckNilTrue, e) + case *map[int16]int16: + fastpathTV.EncMapInt16Int16V(*v, fastpathCheckNilTrue, e) + + case map[int16]int32: + fastpathTV.EncMapInt16Int32V(v, fastpathCheckNilTrue, e) + case *map[int16]int32: + fastpathTV.EncMapInt16Int32V(*v, fastpathCheckNilTrue, e) + + case map[int16]int64: + fastpathTV.EncMapInt16Int64V(v, fastpathCheckNilTrue, e) + case *map[int16]int64: + fastpathTV.EncMapInt16Int64V(*v, fastpathCheckNilTrue, e) + + case map[int16]float32: + fastpathTV.EncMapInt16Float32V(v, fastpathCheckNilTrue, e) + case *map[int16]float32: + fastpathTV.EncMapInt16Float32V(*v, fastpathCheckNilTrue, e) + + case map[int16]float64: + fastpathTV.EncMapInt16Float64V(v, fastpathCheckNilTrue, e) + case *map[int16]float64: + fastpathTV.EncMapInt16Float64V(*v, fastpathCheckNilTrue, e) + + case map[int16]bool: + fastpathTV.EncMapInt16BoolV(v, fastpathCheckNilTrue, e) + case *map[int16]bool: + fastpathTV.EncMapInt16BoolV(*v, fastpathCheckNilTrue, e) + + case map[int32]interface{}: + fastpathTV.EncMapInt32IntfV(v, fastpathCheckNilTrue, e) + case *map[int32]interface{}: + fastpathTV.EncMapInt32IntfV(*v, fastpathCheckNilTrue, e) + + case map[int32]string: + fastpathTV.EncMapInt32StringV(v, fastpathCheckNilTrue, e) + case *map[int32]string: + fastpathTV.EncMapInt32StringV(*v, fastpathCheckNilTrue, e) + + case map[int32]uint: + fastpathTV.EncMapInt32UintV(v, fastpathCheckNilTrue, e) + case *map[int32]uint: + fastpathTV.EncMapInt32UintV(*v, fastpathCheckNilTrue, e) + + case map[int32]uint8: + fastpathTV.EncMapInt32Uint8V(v, fastpathCheckNilTrue, e) + case *map[int32]uint8: + fastpathTV.EncMapInt32Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint16: + fastpathTV.EncMapInt32Uint16V(v, fastpathCheckNilTrue, e) + case *map[int32]uint16: + fastpathTV.EncMapInt32Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint32: + fastpathTV.EncMapInt32Uint32V(v, fastpathCheckNilTrue, e) + case *map[int32]uint32: + fastpathTV.EncMapInt32Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int32]uint64: + fastpathTV.EncMapInt32Uint64V(v, fastpathCheckNilTrue, e) + case *map[int32]uint64: + fastpathTV.EncMapInt32Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int32]uintptr: + fastpathTV.EncMapInt32UintptrV(v, fastpathCheckNilTrue, e) + case *map[int32]uintptr: + fastpathTV.EncMapInt32UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int32]int: + fastpathTV.EncMapInt32IntV(v, fastpathCheckNilTrue, e) + case *map[int32]int: + fastpathTV.EncMapInt32IntV(*v, fastpathCheckNilTrue, e) + + case map[int32]int8: + fastpathTV.EncMapInt32Int8V(v, fastpathCheckNilTrue, e) + case *map[int32]int8: + fastpathTV.EncMapInt32Int8V(*v, fastpathCheckNilTrue, e) + + case map[int32]int16: + fastpathTV.EncMapInt32Int16V(v, fastpathCheckNilTrue, e) + case *map[int32]int16: + fastpathTV.EncMapInt32Int16V(*v, fastpathCheckNilTrue, e) + + case map[int32]int32: + fastpathTV.EncMapInt32Int32V(v, fastpathCheckNilTrue, e) + case *map[int32]int32: + fastpathTV.EncMapInt32Int32V(*v, fastpathCheckNilTrue, e) + + case map[int32]int64: + fastpathTV.EncMapInt32Int64V(v, fastpathCheckNilTrue, e) + case *map[int32]int64: + fastpathTV.EncMapInt32Int64V(*v, fastpathCheckNilTrue, e) + + case map[int32]float32: + fastpathTV.EncMapInt32Float32V(v, fastpathCheckNilTrue, e) + case *map[int32]float32: + fastpathTV.EncMapInt32Float32V(*v, fastpathCheckNilTrue, e) + + case map[int32]float64: + fastpathTV.EncMapInt32Float64V(v, fastpathCheckNilTrue, e) + case *map[int32]float64: + fastpathTV.EncMapInt32Float64V(*v, fastpathCheckNilTrue, e) + + case map[int32]bool: + fastpathTV.EncMapInt32BoolV(v, fastpathCheckNilTrue, e) + case *map[int32]bool: + fastpathTV.EncMapInt32BoolV(*v, fastpathCheckNilTrue, e) + + case map[int64]interface{}: + fastpathTV.EncMapInt64IntfV(v, fastpathCheckNilTrue, e) + case *map[int64]interface{}: + fastpathTV.EncMapInt64IntfV(*v, fastpathCheckNilTrue, e) + + case map[int64]string: + fastpathTV.EncMapInt64StringV(v, fastpathCheckNilTrue, e) + case *map[int64]string: + fastpathTV.EncMapInt64StringV(*v, fastpathCheckNilTrue, e) + + case map[int64]uint: + fastpathTV.EncMapInt64UintV(v, fastpathCheckNilTrue, e) + case *map[int64]uint: + fastpathTV.EncMapInt64UintV(*v, fastpathCheckNilTrue, e) + + case map[int64]uint8: + fastpathTV.EncMapInt64Uint8V(v, fastpathCheckNilTrue, e) + case *map[int64]uint8: + fastpathTV.EncMapInt64Uint8V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint16: + fastpathTV.EncMapInt64Uint16V(v, fastpathCheckNilTrue, e) + case *map[int64]uint16: + fastpathTV.EncMapInt64Uint16V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint32: + fastpathTV.EncMapInt64Uint32V(v, fastpathCheckNilTrue, e) + case *map[int64]uint32: + fastpathTV.EncMapInt64Uint32V(*v, fastpathCheckNilTrue, e) + + case map[int64]uint64: + fastpathTV.EncMapInt64Uint64V(v, fastpathCheckNilTrue, e) + case *map[int64]uint64: + fastpathTV.EncMapInt64Uint64V(*v, fastpathCheckNilTrue, e) + + case map[int64]uintptr: + fastpathTV.EncMapInt64UintptrV(v, fastpathCheckNilTrue, e) + case *map[int64]uintptr: + fastpathTV.EncMapInt64UintptrV(*v, fastpathCheckNilTrue, e) + + case map[int64]int: + fastpathTV.EncMapInt64IntV(v, fastpathCheckNilTrue, e) + case *map[int64]int: + fastpathTV.EncMapInt64IntV(*v, fastpathCheckNilTrue, e) + + case map[int64]int8: + fastpathTV.EncMapInt64Int8V(v, fastpathCheckNilTrue, e) + case *map[int64]int8: + fastpathTV.EncMapInt64Int8V(*v, fastpathCheckNilTrue, e) + + case map[int64]int16: + fastpathTV.EncMapInt64Int16V(v, fastpathCheckNilTrue, e) + case *map[int64]int16: + fastpathTV.EncMapInt64Int16V(*v, fastpathCheckNilTrue, e) + + case map[int64]int32: + fastpathTV.EncMapInt64Int32V(v, fastpathCheckNilTrue, e) + case *map[int64]int32: + fastpathTV.EncMapInt64Int32V(*v, fastpathCheckNilTrue, e) + + case map[int64]int64: + fastpathTV.EncMapInt64Int64V(v, fastpathCheckNilTrue, e) + case *map[int64]int64: + fastpathTV.EncMapInt64Int64V(*v, fastpathCheckNilTrue, e) + + case map[int64]float32: + fastpathTV.EncMapInt64Float32V(v, fastpathCheckNilTrue, e) + case *map[int64]float32: + fastpathTV.EncMapInt64Float32V(*v, fastpathCheckNilTrue, e) + + case map[int64]float64: + fastpathTV.EncMapInt64Float64V(v, fastpathCheckNilTrue, e) + case *map[int64]float64: + fastpathTV.EncMapInt64Float64V(*v, fastpathCheckNilTrue, e) + + case map[int64]bool: + fastpathTV.EncMapInt64BoolV(v, fastpathCheckNilTrue, e) + case *map[int64]bool: + fastpathTV.EncMapInt64BoolV(*v, fastpathCheckNilTrue, e) + + case map[bool]interface{}: + fastpathTV.EncMapBoolIntfV(v, fastpathCheckNilTrue, e) + case *map[bool]interface{}: + fastpathTV.EncMapBoolIntfV(*v, fastpathCheckNilTrue, e) + + case map[bool]string: + fastpathTV.EncMapBoolStringV(v, fastpathCheckNilTrue, e) + case *map[bool]string: + fastpathTV.EncMapBoolStringV(*v, fastpathCheckNilTrue, e) + + case map[bool]uint: + fastpathTV.EncMapBoolUintV(v, fastpathCheckNilTrue, e) + case *map[bool]uint: + fastpathTV.EncMapBoolUintV(*v, fastpathCheckNilTrue, e) + + case map[bool]uint8: + fastpathTV.EncMapBoolUint8V(v, fastpathCheckNilTrue, e) + case *map[bool]uint8: + fastpathTV.EncMapBoolUint8V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint16: + fastpathTV.EncMapBoolUint16V(v, fastpathCheckNilTrue, e) + case *map[bool]uint16: + fastpathTV.EncMapBoolUint16V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint32: + fastpathTV.EncMapBoolUint32V(v, fastpathCheckNilTrue, e) + case *map[bool]uint32: + fastpathTV.EncMapBoolUint32V(*v, fastpathCheckNilTrue, e) + + case map[bool]uint64: + fastpathTV.EncMapBoolUint64V(v, fastpathCheckNilTrue, e) + case *map[bool]uint64: + fastpathTV.EncMapBoolUint64V(*v, fastpathCheckNilTrue, e) + + case map[bool]uintptr: + fastpathTV.EncMapBoolUintptrV(v, fastpathCheckNilTrue, e) + case *map[bool]uintptr: + fastpathTV.EncMapBoolUintptrV(*v, fastpathCheckNilTrue, e) + + case map[bool]int: + fastpathTV.EncMapBoolIntV(v, fastpathCheckNilTrue, e) + case *map[bool]int: + fastpathTV.EncMapBoolIntV(*v, fastpathCheckNilTrue, e) + + case map[bool]int8: + fastpathTV.EncMapBoolInt8V(v, fastpathCheckNilTrue, e) + case *map[bool]int8: + fastpathTV.EncMapBoolInt8V(*v, fastpathCheckNilTrue, e) + + case map[bool]int16: + fastpathTV.EncMapBoolInt16V(v, fastpathCheckNilTrue, e) + case *map[bool]int16: + fastpathTV.EncMapBoolInt16V(*v, fastpathCheckNilTrue, e) + + case map[bool]int32: + fastpathTV.EncMapBoolInt32V(v, fastpathCheckNilTrue, e) + case *map[bool]int32: + fastpathTV.EncMapBoolInt32V(*v, fastpathCheckNilTrue, e) + + case map[bool]int64: + fastpathTV.EncMapBoolInt64V(v, fastpathCheckNilTrue, e) + case *map[bool]int64: + fastpathTV.EncMapBoolInt64V(*v, fastpathCheckNilTrue, e) + + case map[bool]float32: + fastpathTV.EncMapBoolFloat32V(v, fastpathCheckNilTrue, e) + case *map[bool]float32: + fastpathTV.EncMapBoolFloat32V(*v, fastpathCheckNilTrue, e) + + case map[bool]float64: + fastpathTV.EncMapBoolFloat64V(v, fastpathCheckNilTrue, e) + case *map[bool]float64: + fastpathTV.EncMapBoolFloat64V(*v, fastpathCheckNilTrue, e) + + case map[bool]bool: + fastpathTV.EncMapBoolBoolV(v, fastpathCheckNilTrue, e) + case *map[bool]bool: + fastpathTV.EncMapBoolBoolV(*v, fastpathCheckNilTrue, e) + + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +// -- -- fast path functions + +func (f *encFnInfo) fastpathEncSliceIntfR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceIntfV(rv.Interface().([]interface{}), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceIntfV(rv.Interface().([]interface{}), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceIntfV(v []interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + e.encode(v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceIntfV(v []interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + e.encode(v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceStringR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceStringV(rv.Interface().([]string), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceStringV(rv.Interface().([]string), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceStringV(v []string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeString(c_UTF8, v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceStringV(v []string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeString(c_UTF8, v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceFloat32R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceFloat32V(rv.Interface().([]float32), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceFloat32V(rv.Interface().([]float32), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceFloat32V(v []float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeFloat32(v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceFloat32V(v []float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeFloat32(v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceFloat64R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceFloat64V(rv.Interface().([]float64), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceFloat64V(rv.Interface().([]float64), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceFloat64V(v []float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeFloat64(v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceFloat64V(v []float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeFloat64(v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceUintR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceUintV(rv.Interface().([]uint), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceUintV(rv.Interface().([]uint), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceUintV(v []uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceUintV(v []uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceUint16R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceUint16V(rv.Interface().([]uint16), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceUint16V(rv.Interface().([]uint16), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceUint16V(v []uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceUint16V(v []uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceUint32R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceUint32V(rv.Interface().([]uint32), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceUint32V(rv.Interface().([]uint32), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceUint32V(v []uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceUint32V(v []uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceUint64R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceUint64V(rv.Interface().([]uint64), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceUint64V(rv.Interface().([]uint64), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceUint64V(v []uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceUint64V(v []uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeUint(uint64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceUintptrR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceUintptrV(rv.Interface().([]uintptr), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceUintptrV(rv.Interface().([]uintptr), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceUintptrV(v []uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + e.encode(v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceUintptrV(v []uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + e.encode(v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceIntR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceIntV(rv.Interface().([]int), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceIntV(rv.Interface().([]int), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceIntV(v []int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceIntV(v []int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceInt8R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceInt8V(rv.Interface().([]int8), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceInt8V(rv.Interface().([]int8), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceInt8V(v []int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceInt8V(v []int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceInt16R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceInt16V(rv.Interface().([]int16), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceInt16V(rv.Interface().([]int16), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceInt16V(v []int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceInt16V(v []int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceInt32R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceInt32V(rv.Interface().([]int32), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceInt32V(rv.Interface().([]int32), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceInt32V(v []int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceInt32V(v []int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceInt64R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceInt64V(rv.Interface().([]int64), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceInt64V(rv.Interface().([]int64), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceInt64V(v []int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceInt64V(v []int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeInt(int64(v2)) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncSliceBoolR(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.EncAsMapSliceBoolV(rv.Interface().([]bool), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.EncSliceBoolV(rv.Interface().([]bool), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) EncSliceBoolV(v []bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { + cr.sendContainerState(containerArrayElem) + } + ee.EncodeBool(v2) + } + if cr != nil { + cr.sendContainerState(containerArrayEnd) + } +} + +func (_ fastpathT) EncAsMapSliceBoolV(v []bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + ee.EncodeBool(v2) + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfIntfR(rv reflect.Value) { + fastpathTV.EncMapIntfIntfV(rv.Interface().(map[interface{}]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfIntfV(v map[interface{}]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfStringR(rv reflect.Value) { + fastpathTV.EncMapIntfStringV(rv.Interface().(map[interface{}]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfStringV(v map[interface{}]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUintR(rv reflect.Value) { + fastpathTV.EncMapIntfUintV(rv.Interface().(map[interface{}]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUintV(v map[interface{}]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUint8R(rv reflect.Value) { + fastpathTV.EncMapIntfUint8V(rv.Interface().(map[interface{}]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUint8V(v map[interface{}]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUint16R(rv reflect.Value) { + fastpathTV.EncMapIntfUint16V(rv.Interface().(map[interface{}]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUint16V(v map[interface{}]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUint32R(rv reflect.Value) { + fastpathTV.EncMapIntfUint32V(rv.Interface().(map[interface{}]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUint32V(v map[interface{}]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUint64R(rv reflect.Value) { + fastpathTV.EncMapIntfUint64V(rv.Interface().(map[interface{}]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUint64V(v map[interface{}]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfUintptrR(rv reflect.Value) { + fastpathTV.EncMapIntfUintptrV(rv.Interface().(map[interface{}]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfUintptrV(v map[interface{}]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfIntR(rv reflect.Value) { + fastpathTV.EncMapIntfIntV(rv.Interface().(map[interface{}]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfIntV(v map[interface{}]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfInt8R(rv reflect.Value) { + fastpathTV.EncMapIntfInt8V(rv.Interface().(map[interface{}]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfInt8V(v map[interface{}]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfInt16R(rv reflect.Value) { + fastpathTV.EncMapIntfInt16V(rv.Interface().(map[interface{}]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfInt16V(v map[interface{}]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfInt32R(rv reflect.Value) { + fastpathTV.EncMapIntfInt32V(rv.Interface().(map[interface{}]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfInt32V(v map[interface{}]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfInt64R(rv reflect.Value) { + fastpathTV.EncMapIntfInt64V(rv.Interface().(map[interface{}]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfInt64V(v map[interface{}]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfFloat32R(rv reflect.Value) { + fastpathTV.EncMapIntfFloat32V(rv.Interface().(map[interface{}]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfFloat32V(v map[interface{}]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfFloat64R(rv reflect.Value) { + fastpathTV.EncMapIntfFloat64V(rv.Interface().(map[interface{}]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfFloat64V(v map[interface{}]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntfBoolR(rv reflect.Value) { + fastpathTV.EncMapIntfBoolV(rv.Interface().(map[interface{}]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntfBoolV(v map[interface{}]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.asis(v2[j].v) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[v2[j].i]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringIntfR(rv reflect.Value) { + fastpathTV.EncMapStringIntfV(rv.Interface().(map[string]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringIntfV(v map[string]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringStringR(rv reflect.Value) { + fastpathTV.EncMapStringStringV(rv.Interface().(map[string]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringStringV(v map[string]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUintR(rv reflect.Value) { + fastpathTV.EncMapStringUintV(rv.Interface().(map[string]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUintV(v map[string]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUint8R(rv reflect.Value) { + fastpathTV.EncMapStringUint8V(rv.Interface().(map[string]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUint8V(v map[string]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUint16R(rv reflect.Value) { + fastpathTV.EncMapStringUint16V(rv.Interface().(map[string]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUint16V(v map[string]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUint32R(rv reflect.Value) { + fastpathTV.EncMapStringUint32V(rv.Interface().(map[string]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUint32V(v map[string]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUint64R(rv reflect.Value) { + fastpathTV.EncMapStringUint64V(rv.Interface().(map[string]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUint64V(v map[string]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringUintptrR(rv reflect.Value) { + fastpathTV.EncMapStringUintptrV(rv.Interface().(map[string]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringUintptrV(v map[string]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringIntR(rv reflect.Value) { + fastpathTV.EncMapStringIntV(rv.Interface().(map[string]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringIntV(v map[string]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringInt8R(rv reflect.Value) { + fastpathTV.EncMapStringInt8V(rv.Interface().(map[string]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringInt8V(v map[string]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringInt16R(rv reflect.Value) { + fastpathTV.EncMapStringInt16V(rv.Interface().(map[string]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringInt16V(v map[string]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringInt32R(rv reflect.Value) { + fastpathTV.EncMapStringInt32V(rv.Interface().(map[string]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringInt32V(v map[string]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringInt64R(rv reflect.Value) { + fastpathTV.EncMapStringInt64V(rv.Interface().(map[string]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringInt64V(v map[string]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[string(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringFloat32R(rv reflect.Value) { + fastpathTV.EncMapStringFloat32V(rv.Interface().(map[string]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringFloat32V(v map[string]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringFloat64R(rv reflect.Value) { + fastpathTV.EncMapStringFloat64V(rv.Interface().(map[string]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringFloat64V(v map[string]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapStringBoolR(rv reflect.Value) { + fastpathTV.EncMapStringBoolV(rv.Interface().(map[string]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapStringBoolV(v map[string]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + if e.h.Canonical { + v2 := make([]string, len(v)) + var i int + for k, _ := range v { + v2[i] = string(k) + i++ + } + sort.Sort(stringSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[string(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32IntfR(rv reflect.Value) { + fastpathTV.EncMapFloat32IntfV(rv.Interface().(map[float32]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32IntfV(v map[float32]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32StringR(rv reflect.Value) { + fastpathTV.EncMapFloat32StringV(rv.Interface().(map[float32]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32StringV(v map[float32]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32UintR(rv reflect.Value) { + fastpathTV.EncMapFloat32UintV(rv.Interface().(map[float32]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32UintV(v map[float32]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Uint8R(rv reflect.Value) { + fastpathTV.EncMapFloat32Uint8V(rv.Interface().(map[float32]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Uint8V(v map[float32]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Uint16R(rv reflect.Value) { + fastpathTV.EncMapFloat32Uint16V(rv.Interface().(map[float32]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Uint16V(v map[float32]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Uint32R(rv reflect.Value) { + fastpathTV.EncMapFloat32Uint32V(rv.Interface().(map[float32]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Uint32V(v map[float32]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Uint64R(rv reflect.Value) { + fastpathTV.EncMapFloat32Uint64V(rv.Interface().(map[float32]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Uint64V(v map[float32]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32UintptrR(rv reflect.Value) { + fastpathTV.EncMapFloat32UintptrV(rv.Interface().(map[float32]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32UintptrV(v map[float32]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32IntR(rv reflect.Value) { + fastpathTV.EncMapFloat32IntV(rv.Interface().(map[float32]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32IntV(v map[float32]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Int8R(rv reflect.Value) { + fastpathTV.EncMapFloat32Int8V(rv.Interface().(map[float32]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Int8V(v map[float32]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Int16R(rv reflect.Value) { + fastpathTV.EncMapFloat32Int16V(rv.Interface().(map[float32]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Int16V(v map[float32]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Int32R(rv reflect.Value) { + fastpathTV.EncMapFloat32Int32V(rv.Interface().(map[float32]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Int32V(v map[float32]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Int64R(rv reflect.Value) { + fastpathTV.EncMapFloat32Int64V(rv.Interface().(map[float32]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Int64V(v map[float32]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Float32R(rv reflect.Value) { + fastpathTV.EncMapFloat32Float32V(rv.Interface().(map[float32]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Float32V(v map[float32]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32Float64R(rv reflect.Value) { + fastpathTV.EncMapFloat32Float64V(rv.Interface().(map[float32]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32Float64V(v map[float32]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat32BoolR(rv reflect.Value) { + fastpathTV.EncMapFloat32BoolV(rv.Interface().(map[float32]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat32BoolV(v map[float32]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(float32(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[float32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat32(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64IntfR(rv reflect.Value) { + fastpathTV.EncMapFloat64IntfV(rv.Interface().(map[float64]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64IntfV(v map[float64]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64StringR(rv reflect.Value) { + fastpathTV.EncMapFloat64StringV(rv.Interface().(map[float64]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64StringV(v map[float64]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64UintR(rv reflect.Value) { + fastpathTV.EncMapFloat64UintV(rv.Interface().(map[float64]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64UintV(v map[float64]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Uint8R(rv reflect.Value) { + fastpathTV.EncMapFloat64Uint8V(rv.Interface().(map[float64]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Uint8V(v map[float64]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Uint16R(rv reflect.Value) { + fastpathTV.EncMapFloat64Uint16V(rv.Interface().(map[float64]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Uint16V(v map[float64]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Uint32R(rv reflect.Value) { + fastpathTV.EncMapFloat64Uint32V(rv.Interface().(map[float64]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Uint32V(v map[float64]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Uint64R(rv reflect.Value) { + fastpathTV.EncMapFloat64Uint64V(rv.Interface().(map[float64]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Uint64V(v map[float64]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64UintptrR(rv reflect.Value) { + fastpathTV.EncMapFloat64UintptrV(rv.Interface().(map[float64]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64UintptrV(v map[float64]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64IntR(rv reflect.Value) { + fastpathTV.EncMapFloat64IntV(rv.Interface().(map[float64]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64IntV(v map[float64]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Int8R(rv reflect.Value) { + fastpathTV.EncMapFloat64Int8V(rv.Interface().(map[float64]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Int8V(v map[float64]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Int16R(rv reflect.Value) { + fastpathTV.EncMapFloat64Int16V(rv.Interface().(map[float64]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Int16V(v map[float64]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Int32R(rv reflect.Value) { + fastpathTV.EncMapFloat64Int32V(rv.Interface().(map[float64]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Int32V(v map[float64]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Int64R(rv reflect.Value) { + fastpathTV.EncMapFloat64Int64V(rv.Interface().(map[float64]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Int64V(v map[float64]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[float64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Float32R(rv reflect.Value) { + fastpathTV.EncMapFloat64Float32V(rv.Interface().(map[float64]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Float32V(v map[float64]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64Float64R(rv reflect.Value) { + fastpathTV.EncMapFloat64Float64V(rv.Interface().(map[float64]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64Float64V(v map[float64]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapFloat64BoolR(rv reflect.Value) { + fastpathTV.EncMapFloat64BoolV(rv.Interface().(map[float64]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapFloat64BoolV(v map[float64]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]float64, len(v)) + var i int + for k, _ := range v { + v2[i] = float64(k) + i++ + } + sort.Sort(floatSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(float64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[float64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeFloat64(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintIntfR(rv reflect.Value) { + fastpathTV.EncMapUintIntfV(rv.Interface().(map[uint]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintIntfV(v map[uint]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintStringR(rv reflect.Value) { + fastpathTV.EncMapUintStringV(rv.Interface().(map[uint]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintStringV(v map[uint]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUintR(rv reflect.Value) { + fastpathTV.EncMapUintUintV(rv.Interface().(map[uint]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUintV(v map[uint]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUint8R(rv reflect.Value) { + fastpathTV.EncMapUintUint8V(rv.Interface().(map[uint]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUint8V(v map[uint]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUint16R(rv reflect.Value) { + fastpathTV.EncMapUintUint16V(rv.Interface().(map[uint]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUint16V(v map[uint]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUint32R(rv reflect.Value) { + fastpathTV.EncMapUintUint32V(rv.Interface().(map[uint]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUint32V(v map[uint]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUint64R(rv reflect.Value) { + fastpathTV.EncMapUintUint64V(rv.Interface().(map[uint]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUint64V(v map[uint]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintUintptrR(rv reflect.Value) { + fastpathTV.EncMapUintUintptrV(rv.Interface().(map[uint]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintUintptrV(v map[uint]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintIntR(rv reflect.Value) { + fastpathTV.EncMapUintIntV(rv.Interface().(map[uint]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintIntV(v map[uint]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintInt8R(rv reflect.Value) { + fastpathTV.EncMapUintInt8V(rv.Interface().(map[uint]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintInt8V(v map[uint]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintInt16R(rv reflect.Value) { + fastpathTV.EncMapUintInt16V(rv.Interface().(map[uint]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintInt16V(v map[uint]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintInt32R(rv reflect.Value) { + fastpathTV.EncMapUintInt32V(rv.Interface().(map[uint]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintInt32V(v map[uint]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintInt64R(rv reflect.Value) { + fastpathTV.EncMapUintInt64V(rv.Interface().(map[uint]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintInt64V(v map[uint]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintFloat32R(rv reflect.Value) { + fastpathTV.EncMapUintFloat32V(rv.Interface().(map[uint]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintFloat32V(v map[uint]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintFloat64R(rv reflect.Value) { + fastpathTV.EncMapUintFloat64V(rv.Interface().(map[uint]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintFloat64V(v map[uint]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintBoolR(rv reflect.Value) { + fastpathTV.EncMapUintBoolV(rv.Interface().(map[uint]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintBoolV(v map[uint]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uint(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8IntfR(rv reflect.Value) { + fastpathTV.EncMapUint8IntfV(rv.Interface().(map[uint8]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8IntfV(v map[uint8]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8StringR(rv reflect.Value) { + fastpathTV.EncMapUint8StringV(rv.Interface().(map[uint8]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8StringV(v map[uint8]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8UintR(rv reflect.Value) { + fastpathTV.EncMapUint8UintV(rv.Interface().(map[uint8]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8UintV(v map[uint8]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Uint8R(rv reflect.Value) { + fastpathTV.EncMapUint8Uint8V(rv.Interface().(map[uint8]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Uint8V(v map[uint8]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Uint16R(rv reflect.Value) { + fastpathTV.EncMapUint8Uint16V(rv.Interface().(map[uint8]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Uint16V(v map[uint8]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Uint32R(rv reflect.Value) { + fastpathTV.EncMapUint8Uint32V(rv.Interface().(map[uint8]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Uint32V(v map[uint8]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Uint64R(rv reflect.Value) { + fastpathTV.EncMapUint8Uint64V(rv.Interface().(map[uint8]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Uint64V(v map[uint8]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8UintptrR(rv reflect.Value) { + fastpathTV.EncMapUint8UintptrV(rv.Interface().(map[uint8]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8UintptrV(v map[uint8]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8IntR(rv reflect.Value) { + fastpathTV.EncMapUint8IntV(rv.Interface().(map[uint8]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8IntV(v map[uint8]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Int8R(rv reflect.Value) { + fastpathTV.EncMapUint8Int8V(rv.Interface().(map[uint8]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Int8V(v map[uint8]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Int16R(rv reflect.Value) { + fastpathTV.EncMapUint8Int16V(rv.Interface().(map[uint8]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Int16V(v map[uint8]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Int32R(rv reflect.Value) { + fastpathTV.EncMapUint8Int32V(rv.Interface().(map[uint8]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Int32V(v map[uint8]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Int64R(rv reflect.Value) { + fastpathTV.EncMapUint8Int64V(rv.Interface().(map[uint8]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Int64V(v map[uint8]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Float32R(rv reflect.Value) { + fastpathTV.EncMapUint8Float32V(rv.Interface().(map[uint8]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Float32V(v map[uint8]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8Float64R(rv reflect.Value) { + fastpathTV.EncMapUint8Float64V(rv.Interface().(map[uint8]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8Float64V(v map[uint8]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint8BoolR(rv reflect.Value) { + fastpathTV.EncMapUint8BoolV(rv.Interface().(map[uint8]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint8BoolV(v map[uint8]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uint8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16IntfR(rv reflect.Value) { + fastpathTV.EncMapUint16IntfV(rv.Interface().(map[uint16]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16IntfV(v map[uint16]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16StringR(rv reflect.Value) { + fastpathTV.EncMapUint16StringV(rv.Interface().(map[uint16]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16StringV(v map[uint16]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16UintR(rv reflect.Value) { + fastpathTV.EncMapUint16UintV(rv.Interface().(map[uint16]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16UintV(v map[uint16]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Uint8R(rv reflect.Value) { + fastpathTV.EncMapUint16Uint8V(rv.Interface().(map[uint16]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Uint8V(v map[uint16]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Uint16R(rv reflect.Value) { + fastpathTV.EncMapUint16Uint16V(rv.Interface().(map[uint16]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Uint16V(v map[uint16]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Uint32R(rv reflect.Value) { + fastpathTV.EncMapUint16Uint32V(rv.Interface().(map[uint16]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Uint32V(v map[uint16]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Uint64R(rv reflect.Value) { + fastpathTV.EncMapUint16Uint64V(rv.Interface().(map[uint16]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Uint64V(v map[uint16]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16UintptrR(rv reflect.Value) { + fastpathTV.EncMapUint16UintptrV(rv.Interface().(map[uint16]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16UintptrV(v map[uint16]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16IntR(rv reflect.Value) { + fastpathTV.EncMapUint16IntV(rv.Interface().(map[uint16]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16IntV(v map[uint16]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Int8R(rv reflect.Value) { + fastpathTV.EncMapUint16Int8V(rv.Interface().(map[uint16]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Int8V(v map[uint16]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Int16R(rv reflect.Value) { + fastpathTV.EncMapUint16Int16V(rv.Interface().(map[uint16]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Int16V(v map[uint16]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Int32R(rv reflect.Value) { + fastpathTV.EncMapUint16Int32V(rv.Interface().(map[uint16]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Int32V(v map[uint16]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Int64R(rv reflect.Value) { + fastpathTV.EncMapUint16Int64V(rv.Interface().(map[uint16]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Int64V(v map[uint16]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Float32R(rv reflect.Value) { + fastpathTV.EncMapUint16Float32V(rv.Interface().(map[uint16]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Float32V(v map[uint16]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16Float64R(rv reflect.Value) { + fastpathTV.EncMapUint16Float64V(rv.Interface().(map[uint16]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16Float64V(v map[uint16]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint16BoolR(rv reflect.Value) { + fastpathTV.EncMapUint16BoolV(rv.Interface().(map[uint16]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint16BoolV(v map[uint16]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uint16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32IntfR(rv reflect.Value) { + fastpathTV.EncMapUint32IntfV(rv.Interface().(map[uint32]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32IntfV(v map[uint32]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32StringR(rv reflect.Value) { + fastpathTV.EncMapUint32StringV(rv.Interface().(map[uint32]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32StringV(v map[uint32]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32UintR(rv reflect.Value) { + fastpathTV.EncMapUint32UintV(rv.Interface().(map[uint32]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32UintV(v map[uint32]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Uint8R(rv reflect.Value) { + fastpathTV.EncMapUint32Uint8V(rv.Interface().(map[uint32]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Uint8V(v map[uint32]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Uint16R(rv reflect.Value) { + fastpathTV.EncMapUint32Uint16V(rv.Interface().(map[uint32]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Uint16V(v map[uint32]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Uint32R(rv reflect.Value) { + fastpathTV.EncMapUint32Uint32V(rv.Interface().(map[uint32]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Uint32V(v map[uint32]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Uint64R(rv reflect.Value) { + fastpathTV.EncMapUint32Uint64V(rv.Interface().(map[uint32]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Uint64V(v map[uint32]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32UintptrR(rv reflect.Value) { + fastpathTV.EncMapUint32UintptrV(rv.Interface().(map[uint32]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32UintptrV(v map[uint32]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32IntR(rv reflect.Value) { + fastpathTV.EncMapUint32IntV(rv.Interface().(map[uint32]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32IntV(v map[uint32]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Int8R(rv reflect.Value) { + fastpathTV.EncMapUint32Int8V(rv.Interface().(map[uint32]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Int8V(v map[uint32]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Int16R(rv reflect.Value) { + fastpathTV.EncMapUint32Int16V(rv.Interface().(map[uint32]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Int16V(v map[uint32]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Int32R(rv reflect.Value) { + fastpathTV.EncMapUint32Int32V(rv.Interface().(map[uint32]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Int32V(v map[uint32]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Int64R(rv reflect.Value) { + fastpathTV.EncMapUint32Int64V(rv.Interface().(map[uint32]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Int64V(v map[uint32]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Float32R(rv reflect.Value) { + fastpathTV.EncMapUint32Float32V(rv.Interface().(map[uint32]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Float32V(v map[uint32]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32Float64R(rv reflect.Value) { + fastpathTV.EncMapUint32Float64V(rv.Interface().(map[uint32]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32Float64V(v map[uint32]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint32BoolR(rv reflect.Value) { + fastpathTV.EncMapUint32BoolV(rv.Interface().(map[uint32]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint32BoolV(v map[uint32]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uint32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64IntfR(rv reflect.Value) { + fastpathTV.EncMapUint64IntfV(rv.Interface().(map[uint64]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64IntfV(v map[uint64]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64StringR(rv reflect.Value) { + fastpathTV.EncMapUint64StringV(rv.Interface().(map[uint64]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64StringV(v map[uint64]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64UintR(rv reflect.Value) { + fastpathTV.EncMapUint64UintV(rv.Interface().(map[uint64]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64UintV(v map[uint64]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Uint8R(rv reflect.Value) { + fastpathTV.EncMapUint64Uint8V(rv.Interface().(map[uint64]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Uint8V(v map[uint64]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Uint16R(rv reflect.Value) { + fastpathTV.EncMapUint64Uint16V(rv.Interface().(map[uint64]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Uint16V(v map[uint64]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Uint32R(rv reflect.Value) { + fastpathTV.EncMapUint64Uint32V(rv.Interface().(map[uint64]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Uint32V(v map[uint64]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Uint64R(rv reflect.Value) { + fastpathTV.EncMapUint64Uint64V(rv.Interface().(map[uint64]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Uint64V(v map[uint64]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64UintptrR(rv reflect.Value) { + fastpathTV.EncMapUint64UintptrV(rv.Interface().(map[uint64]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64UintptrV(v map[uint64]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64IntR(rv reflect.Value) { + fastpathTV.EncMapUint64IntV(rv.Interface().(map[uint64]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64IntV(v map[uint64]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Int8R(rv reflect.Value) { + fastpathTV.EncMapUint64Int8V(rv.Interface().(map[uint64]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Int8V(v map[uint64]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Int16R(rv reflect.Value) { + fastpathTV.EncMapUint64Int16V(rv.Interface().(map[uint64]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Int16V(v map[uint64]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Int32R(rv reflect.Value) { + fastpathTV.EncMapUint64Int32V(rv.Interface().(map[uint64]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Int32V(v map[uint64]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Int64R(rv reflect.Value) { + fastpathTV.EncMapUint64Int64V(rv.Interface().(map[uint64]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Int64V(v map[uint64]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uint64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Float32R(rv reflect.Value) { + fastpathTV.EncMapUint64Float32V(rv.Interface().(map[uint64]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Float32V(v map[uint64]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64Float64R(rv reflect.Value) { + fastpathTV.EncMapUint64Float64V(rv.Interface().(map[uint64]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64Float64V(v map[uint64]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUint64BoolR(rv reflect.Value) { + fastpathTV.EncMapUint64BoolV(rv.Interface().(map[uint64]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUint64BoolV(v map[uint64]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(uint64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uint64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeUint(uint64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrIntfR(rv reflect.Value) { + fastpathTV.EncMapUintptrIntfV(rv.Interface().(map[uintptr]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrIntfV(v map[uintptr]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrStringR(rv reflect.Value) { + fastpathTV.EncMapUintptrStringV(rv.Interface().(map[uintptr]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrStringV(v map[uintptr]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUintR(rv reflect.Value) { + fastpathTV.EncMapUintptrUintV(rv.Interface().(map[uintptr]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUintV(v map[uintptr]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUint8R(rv reflect.Value) { + fastpathTV.EncMapUintptrUint8V(rv.Interface().(map[uintptr]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUint8V(v map[uintptr]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUint16R(rv reflect.Value) { + fastpathTV.EncMapUintptrUint16V(rv.Interface().(map[uintptr]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUint16V(v map[uintptr]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUint32R(rv reflect.Value) { + fastpathTV.EncMapUintptrUint32V(rv.Interface().(map[uintptr]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUint32V(v map[uintptr]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUint64R(rv reflect.Value) { + fastpathTV.EncMapUintptrUint64V(rv.Interface().(map[uintptr]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUint64V(v map[uintptr]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrUintptrR(rv reflect.Value) { + fastpathTV.EncMapUintptrUintptrV(rv.Interface().(map[uintptr]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrUintptrV(v map[uintptr]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrIntR(rv reflect.Value) { + fastpathTV.EncMapUintptrIntV(rv.Interface().(map[uintptr]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrIntV(v map[uintptr]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrInt8R(rv reflect.Value) { + fastpathTV.EncMapUintptrInt8V(rv.Interface().(map[uintptr]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrInt8V(v map[uintptr]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrInt16R(rv reflect.Value) { + fastpathTV.EncMapUintptrInt16V(rv.Interface().(map[uintptr]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrInt16V(v map[uintptr]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrInt32R(rv reflect.Value) { + fastpathTV.EncMapUintptrInt32V(rv.Interface().(map[uintptr]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrInt32V(v map[uintptr]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrInt64R(rv reflect.Value) { + fastpathTV.EncMapUintptrInt64V(rv.Interface().(map[uintptr]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrInt64V(v map[uintptr]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[uintptr(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrFloat32R(rv reflect.Value) { + fastpathTV.EncMapUintptrFloat32V(rv.Interface().(map[uintptr]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrFloat32V(v map[uintptr]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrFloat64R(rv reflect.Value) { + fastpathTV.EncMapUintptrFloat64V(rv.Interface().(map[uintptr]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrFloat64V(v map[uintptr]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapUintptrBoolR(rv reflect.Value) { + fastpathTV.EncMapUintptrBoolV(rv.Interface().(map[uintptr]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapUintptrBoolV(v map[uintptr]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]uint64, len(v)) + var i int + for k, _ := range v { + v2[i] = uint64(k) + i++ + } + sort.Sort(uintSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(uintptr(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[uintptr(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + e.encode(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntIntfR(rv reflect.Value) { + fastpathTV.EncMapIntIntfV(rv.Interface().(map[int]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntIntfV(v map[int]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntStringR(rv reflect.Value) { + fastpathTV.EncMapIntStringV(rv.Interface().(map[int]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntStringV(v map[int]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUintR(rv reflect.Value) { + fastpathTV.EncMapIntUintV(rv.Interface().(map[int]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUintV(v map[int]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUint8R(rv reflect.Value) { + fastpathTV.EncMapIntUint8V(rv.Interface().(map[int]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUint8V(v map[int]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUint16R(rv reflect.Value) { + fastpathTV.EncMapIntUint16V(rv.Interface().(map[int]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUint16V(v map[int]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUint32R(rv reflect.Value) { + fastpathTV.EncMapIntUint32V(rv.Interface().(map[int]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUint32V(v map[int]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUint64R(rv reflect.Value) { + fastpathTV.EncMapIntUint64V(rv.Interface().(map[int]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUint64V(v map[int]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntUintptrR(rv reflect.Value) { + fastpathTV.EncMapIntUintptrV(rv.Interface().(map[int]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntUintptrV(v map[int]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntIntR(rv reflect.Value) { + fastpathTV.EncMapIntIntV(rv.Interface().(map[int]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntIntV(v map[int]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntInt8R(rv reflect.Value) { + fastpathTV.EncMapIntInt8V(rv.Interface().(map[int]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntInt8V(v map[int]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntInt16R(rv reflect.Value) { + fastpathTV.EncMapIntInt16V(rv.Interface().(map[int]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntInt16V(v map[int]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntInt32R(rv reflect.Value) { + fastpathTV.EncMapIntInt32V(rv.Interface().(map[int]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntInt32V(v map[int]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntInt64R(rv reflect.Value) { + fastpathTV.EncMapIntInt64V(rv.Interface().(map[int]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntInt64V(v map[int]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntFloat32R(rv reflect.Value) { + fastpathTV.EncMapIntFloat32V(rv.Interface().(map[int]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntFloat32V(v map[int]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntFloat64R(rv reflect.Value) { + fastpathTV.EncMapIntFloat64V(rv.Interface().(map[int]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntFloat64V(v map[int]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapIntBoolR(rv reflect.Value) { + fastpathTV.EncMapIntBoolV(rv.Interface().(map[int]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapIntBoolV(v map[int]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[int(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8IntfR(rv reflect.Value) { + fastpathTV.EncMapInt8IntfV(rv.Interface().(map[int8]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8IntfV(v map[int8]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8StringR(rv reflect.Value) { + fastpathTV.EncMapInt8StringV(rv.Interface().(map[int8]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8StringV(v map[int8]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8UintR(rv reflect.Value) { + fastpathTV.EncMapInt8UintV(rv.Interface().(map[int8]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8UintV(v map[int8]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Uint8R(rv reflect.Value) { + fastpathTV.EncMapInt8Uint8V(rv.Interface().(map[int8]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Uint8V(v map[int8]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Uint16R(rv reflect.Value) { + fastpathTV.EncMapInt8Uint16V(rv.Interface().(map[int8]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Uint16V(v map[int8]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Uint32R(rv reflect.Value) { + fastpathTV.EncMapInt8Uint32V(rv.Interface().(map[int8]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Uint32V(v map[int8]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Uint64R(rv reflect.Value) { + fastpathTV.EncMapInt8Uint64V(rv.Interface().(map[int8]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Uint64V(v map[int8]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8UintptrR(rv reflect.Value) { + fastpathTV.EncMapInt8UintptrV(rv.Interface().(map[int8]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8UintptrV(v map[int8]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8IntR(rv reflect.Value) { + fastpathTV.EncMapInt8IntV(rv.Interface().(map[int8]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8IntV(v map[int8]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Int8R(rv reflect.Value) { + fastpathTV.EncMapInt8Int8V(rv.Interface().(map[int8]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Int8V(v map[int8]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Int16R(rv reflect.Value) { + fastpathTV.EncMapInt8Int16V(rv.Interface().(map[int8]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Int16V(v map[int8]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Int32R(rv reflect.Value) { + fastpathTV.EncMapInt8Int32V(rv.Interface().(map[int8]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Int32V(v map[int8]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Int64R(rv reflect.Value) { + fastpathTV.EncMapInt8Int64V(rv.Interface().(map[int8]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Int64V(v map[int8]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int8(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Float32R(rv reflect.Value) { + fastpathTV.EncMapInt8Float32V(rv.Interface().(map[int8]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Float32V(v map[int8]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8Float64R(rv reflect.Value) { + fastpathTV.EncMapInt8Float64V(rv.Interface().(map[int8]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8Float64V(v map[int8]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt8BoolR(rv reflect.Value) { + fastpathTV.EncMapInt8BoolV(rv.Interface().(map[int8]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt8BoolV(v map[int8]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int8(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[int8(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16IntfR(rv reflect.Value) { + fastpathTV.EncMapInt16IntfV(rv.Interface().(map[int16]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16IntfV(v map[int16]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16StringR(rv reflect.Value) { + fastpathTV.EncMapInt16StringV(rv.Interface().(map[int16]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16StringV(v map[int16]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16UintR(rv reflect.Value) { + fastpathTV.EncMapInt16UintV(rv.Interface().(map[int16]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16UintV(v map[int16]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Uint8R(rv reflect.Value) { + fastpathTV.EncMapInt16Uint8V(rv.Interface().(map[int16]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Uint8V(v map[int16]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Uint16R(rv reflect.Value) { + fastpathTV.EncMapInt16Uint16V(rv.Interface().(map[int16]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Uint16V(v map[int16]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Uint32R(rv reflect.Value) { + fastpathTV.EncMapInt16Uint32V(rv.Interface().(map[int16]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Uint32V(v map[int16]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Uint64R(rv reflect.Value) { + fastpathTV.EncMapInt16Uint64V(rv.Interface().(map[int16]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Uint64V(v map[int16]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16UintptrR(rv reflect.Value) { + fastpathTV.EncMapInt16UintptrV(rv.Interface().(map[int16]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16UintptrV(v map[int16]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16IntR(rv reflect.Value) { + fastpathTV.EncMapInt16IntV(rv.Interface().(map[int16]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16IntV(v map[int16]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Int8R(rv reflect.Value) { + fastpathTV.EncMapInt16Int8V(rv.Interface().(map[int16]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Int8V(v map[int16]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Int16R(rv reflect.Value) { + fastpathTV.EncMapInt16Int16V(rv.Interface().(map[int16]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Int16V(v map[int16]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Int32R(rv reflect.Value) { + fastpathTV.EncMapInt16Int32V(rv.Interface().(map[int16]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Int32V(v map[int16]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Int64R(rv reflect.Value) { + fastpathTV.EncMapInt16Int64V(rv.Interface().(map[int16]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Int64V(v map[int16]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int16(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Float32R(rv reflect.Value) { + fastpathTV.EncMapInt16Float32V(rv.Interface().(map[int16]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Float32V(v map[int16]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16Float64R(rv reflect.Value) { + fastpathTV.EncMapInt16Float64V(rv.Interface().(map[int16]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16Float64V(v map[int16]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt16BoolR(rv reflect.Value) { + fastpathTV.EncMapInt16BoolV(rv.Interface().(map[int16]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt16BoolV(v map[int16]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int16(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[int16(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32IntfR(rv reflect.Value) { + fastpathTV.EncMapInt32IntfV(rv.Interface().(map[int32]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32IntfV(v map[int32]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32StringR(rv reflect.Value) { + fastpathTV.EncMapInt32StringV(rv.Interface().(map[int32]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32StringV(v map[int32]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32UintR(rv reflect.Value) { + fastpathTV.EncMapInt32UintV(rv.Interface().(map[int32]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32UintV(v map[int32]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Uint8R(rv reflect.Value) { + fastpathTV.EncMapInt32Uint8V(rv.Interface().(map[int32]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Uint8V(v map[int32]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Uint16R(rv reflect.Value) { + fastpathTV.EncMapInt32Uint16V(rv.Interface().(map[int32]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Uint16V(v map[int32]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Uint32R(rv reflect.Value) { + fastpathTV.EncMapInt32Uint32V(rv.Interface().(map[int32]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Uint32V(v map[int32]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Uint64R(rv reflect.Value) { + fastpathTV.EncMapInt32Uint64V(rv.Interface().(map[int32]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Uint64V(v map[int32]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32UintptrR(rv reflect.Value) { + fastpathTV.EncMapInt32UintptrV(rv.Interface().(map[int32]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32UintptrV(v map[int32]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32IntR(rv reflect.Value) { + fastpathTV.EncMapInt32IntV(rv.Interface().(map[int32]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32IntV(v map[int32]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Int8R(rv reflect.Value) { + fastpathTV.EncMapInt32Int8V(rv.Interface().(map[int32]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Int8V(v map[int32]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Int16R(rv reflect.Value) { + fastpathTV.EncMapInt32Int16V(rv.Interface().(map[int32]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Int16V(v map[int32]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Int32R(rv reflect.Value) { + fastpathTV.EncMapInt32Int32V(rv.Interface().(map[int32]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Int32V(v map[int32]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Int64R(rv reflect.Value) { + fastpathTV.EncMapInt32Int64V(rv.Interface().(map[int32]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Int64V(v map[int32]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int32(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Float32R(rv reflect.Value) { + fastpathTV.EncMapInt32Float32V(rv.Interface().(map[int32]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Float32V(v map[int32]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32Float64R(rv reflect.Value) { + fastpathTV.EncMapInt32Float64V(rv.Interface().(map[int32]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32Float64V(v map[int32]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt32BoolR(rv reflect.Value) { + fastpathTV.EncMapInt32BoolV(rv.Interface().(map[int32]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt32BoolV(v map[int32]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int32(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[int32(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64IntfR(rv reflect.Value) { + fastpathTV.EncMapInt64IntfV(rv.Interface().(map[int64]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64IntfV(v map[int64]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64StringR(rv reflect.Value) { + fastpathTV.EncMapInt64StringV(rv.Interface().(map[int64]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64StringV(v map[int64]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64UintR(rv reflect.Value) { + fastpathTV.EncMapInt64UintV(rv.Interface().(map[int64]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64UintV(v map[int64]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Uint8R(rv reflect.Value) { + fastpathTV.EncMapInt64Uint8V(rv.Interface().(map[int64]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Uint8V(v map[int64]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Uint16R(rv reflect.Value) { + fastpathTV.EncMapInt64Uint16V(rv.Interface().(map[int64]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Uint16V(v map[int64]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Uint32R(rv reflect.Value) { + fastpathTV.EncMapInt64Uint32V(rv.Interface().(map[int64]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Uint32V(v map[int64]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Uint64R(rv reflect.Value) { + fastpathTV.EncMapInt64Uint64V(rv.Interface().(map[int64]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Uint64V(v map[int64]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64UintptrR(rv reflect.Value) { + fastpathTV.EncMapInt64UintptrV(rv.Interface().(map[int64]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64UintptrV(v map[int64]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64IntR(rv reflect.Value) { + fastpathTV.EncMapInt64IntV(rv.Interface().(map[int64]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64IntV(v map[int64]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Int8R(rv reflect.Value) { + fastpathTV.EncMapInt64Int8V(rv.Interface().(map[int64]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Int8V(v map[int64]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Int16R(rv reflect.Value) { + fastpathTV.EncMapInt64Int16V(rv.Interface().(map[int64]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Int16V(v map[int64]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Int32R(rv reflect.Value) { + fastpathTV.EncMapInt64Int32V(rv.Interface().(map[int64]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Int32V(v map[int64]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Int64R(rv reflect.Value) { + fastpathTV.EncMapInt64Int64V(rv.Interface().(map[int64]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Int64V(v map[int64]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[int64(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Float32R(rv reflect.Value) { + fastpathTV.EncMapInt64Float32V(rv.Interface().(map[int64]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Float32V(v map[int64]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64Float64R(rv reflect.Value) { + fastpathTV.EncMapInt64Float64V(rv.Interface().(map[int64]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64Float64V(v map[int64]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapInt64BoolR(rv reflect.Value) { + fastpathTV.EncMapInt64BoolV(rv.Interface().(map[int64]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapInt64BoolV(v map[int64]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]int64, len(v)) + var i int + for k, _ := range v { + v2[i] = int64(k) + i++ + } + sort.Sort(intSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(int64(k2))) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[int64(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeInt(int64(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolIntfR(rv reflect.Value) { + fastpathTV.EncMapBoolIntfV(rv.Interface().(map[bool]interface{}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolIntfV(v map[bool]interface{}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolStringR(rv reflect.Value) { + fastpathTV.EncMapBoolStringV(rv.Interface().(map[bool]string), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolStringV(v map[bool]string, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeString(c_UTF8, v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUintR(rv reflect.Value) { + fastpathTV.EncMapBoolUintV(rv.Interface().(map[bool]uint), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUintV(v map[bool]uint, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUint8R(rv reflect.Value) { + fastpathTV.EncMapBoolUint8V(rv.Interface().(map[bool]uint8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUint8V(v map[bool]uint8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUint16R(rv reflect.Value) { + fastpathTV.EncMapBoolUint16V(rv.Interface().(map[bool]uint16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUint16V(v map[bool]uint16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUint32R(rv reflect.Value) { + fastpathTV.EncMapBoolUint32V(rv.Interface().(map[bool]uint32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUint32V(v map[bool]uint32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUint64R(rv reflect.Value) { + fastpathTV.EncMapBoolUint64V(rv.Interface().(map[bool]uint64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUint64V(v map[bool]uint64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeUint(uint64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolUintptrR(rv reflect.Value) { + fastpathTV.EncMapBoolUintptrV(rv.Interface().(map[bool]uintptr), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolUintptrV(v map[bool]uintptr, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + e.encode(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolIntR(rv reflect.Value) { + fastpathTV.EncMapBoolIntV(rv.Interface().(map[bool]int), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolIntV(v map[bool]int, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolInt8R(rv reflect.Value) { + fastpathTV.EncMapBoolInt8V(rv.Interface().(map[bool]int8), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolInt8V(v map[bool]int8, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolInt16R(rv reflect.Value) { + fastpathTV.EncMapBoolInt16V(rv.Interface().(map[bool]int16), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolInt16V(v map[bool]int16, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolInt32R(rv reflect.Value) { + fastpathTV.EncMapBoolInt32V(rv.Interface().(map[bool]int32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolInt32V(v map[bool]int32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolInt64R(rv reflect.Value) { + fastpathTV.EncMapBoolInt64V(rv.Interface().(map[bool]int64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolInt64V(v map[bool]int64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v[bool(k2)])) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeInt(int64(v2)) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolFloat32R(rv reflect.Value) { + fastpathTV.EncMapBoolFloat32V(rv.Interface().(map[bool]float32), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolFloat32V(v map[bool]float32, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat32(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolFloat64R(rv reflect.Value) { + fastpathTV.EncMapBoolFloat64V(rv.Interface().(map[bool]float64), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolFloat64V(v map[bool]float64, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeFloat64(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +func (f *encFnInfo) fastpathEncMapBoolBoolR(rv reflect.Value) { + fastpathTV.EncMapBoolBoolV(rv.Interface().(map[bool]bool), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) EncMapBoolBoolV(v map[bool]bool, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + if e.h.Canonical { + v2 := make([]bool, len(v)) + var i int + for k, _ := range v { + v2[i] = bool(k) + i++ + } + sort.Sort(boolSlice(v2)) + for _, k2 := range v2 { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(bool(k2)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v[bool(k2)]) + } + } else { + for k2, v2 := range v { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + ee.EncodeBool(k2) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + ee.EncodeBool(v2) + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } +} + +// -- decode + +// -- -- fast path type switch +func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { + + case []interface{}: + fastpathTV.DecSliceIntfV(v, fastpathCheckNilFalse, false, d) + case *[]interface{}: + v2, changed2 := fastpathTV.DecSliceIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]interface{}: + fastpathTV.DecMapIntfIntfV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]interface{}: + v2, changed2 := fastpathTV.DecMapIntfIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]string: + fastpathTV.DecMapIntfStringV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]string: + v2, changed2 := fastpathTV.DecMapIntfStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uint: + fastpathTV.DecMapIntfUintV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uint: + v2, changed2 := fastpathTV.DecMapIntfUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uint8: + fastpathTV.DecMapIntfUint8V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uint8: + v2, changed2 := fastpathTV.DecMapIntfUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uint16: + fastpathTV.DecMapIntfUint16V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uint16: + v2, changed2 := fastpathTV.DecMapIntfUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uint32: + fastpathTV.DecMapIntfUint32V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uint32: + v2, changed2 := fastpathTV.DecMapIntfUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uint64: + fastpathTV.DecMapIntfUint64V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uint64: + v2, changed2 := fastpathTV.DecMapIntfUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]uintptr: + fastpathTV.DecMapIntfUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]uintptr: + v2, changed2 := fastpathTV.DecMapIntfUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]int: + fastpathTV.DecMapIntfIntV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]int: + v2, changed2 := fastpathTV.DecMapIntfIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]int8: + fastpathTV.DecMapIntfInt8V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]int8: + v2, changed2 := fastpathTV.DecMapIntfInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]int16: + fastpathTV.DecMapIntfInt16V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]int16: + v2, changed2 := fastpathTV.DecMapIntfInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]int32: + fastpathTV.DecMapIntfInt32V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]int32: + v2, changed2 := fastpathTV.DecMapIntfInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]int64: + fastpathTV.DecMapIntfInt64V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]int64: + v2, changed2 := fastpathTV.DecMapIntfInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]float32: + fastpathTV.DecMapIntfFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]float32: + v2, changed2 := fastpathTV.DecMapIntfFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]float64: + fastpathTV.DecMapIntfFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]float64: + v2, changed2 := fastpathTV.DecMapIntfFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[interface{}]bool: + fastpathTV.DecMapIntfBoolV(v, fastpathCheckNilFalse, false, d) + case *map[interface{}]bool: + v2, changed2 := fastpathTV.DecMapIntfBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []string: + fastpathTV.DecSliceStringV(v, fastpathCheckNilFalse, false, d) + case *[]string: + v2, changed2 := fastpathTV.DecSliceStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]interface{}: + fastpathTV.DecMapStringIntfV(v, fastpathCheckNilFalse, false, d) + case *map[string]interface{}: + v2, changed2 := fastpathTV.DecMapStringIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]string: + fastpathTV.DecMapStringStringV(v, fastpathCheckNilFalse, false, d) + case *map[string]string: + v2, changed2 := fastpathTV.DecMapStringStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uint: + fastpathTV.DecMapStringUintV(v, fastpathCheckNilFalse, false, d) + case *map[string]uint: + v2, changed2 := fastpathTV.DecMapStringUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uint8: + fastpathTV.DecMapStringUint8V(v, fastpathCheckNilFalse, false, d) + case *map[string]uint8: + v2, changed2 := fastpathTV.DecMapStringUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uint16: + fastpathTV.DecMapStringUint16V(v, fastpathCheckNilFalse, false, d) + case *map[string]uint16: + v2, changed2 := fastpathTV.DecMapStringUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uint32: + fastpathTV.DecMapStringUint32V(v, fastpathCheckNilFalse, false, d) + case *map[string]uint32: + v2, changed2 := fastpathTV.DecMapStringUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uint64: + fastpathTV.DecMapStringUint64V(v, fastpathCheckNilFalse, false, d) + case *map[string]uint64: + v2, changed2 := fastpathTV.DecMapStringUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]uintptr: + fastpathTV.DecMapStringUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[string]uintptr: + v2, changed2 := fastpathTV.DecMapStringUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]int: + fastpathTV.DecMapStringIntV(v, fastpathCheckNilFalse, false, d) + case *map[string]int: + v2, changed2 := fastpathTV.DecMapStringIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]int8: + fastpathTV.DecMapStringInt8V(v, fastpathCheckNilFalse, false, d) + case *map[string]int8: + v2, changed2 := fastpathTV.DecMapStringInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]int16: + fastpathTV.DecMapStringInt16V(v, fastpathCheckNilFalse, false, d) + case *map[string]int16: + v2, changed2 := fastpathTV.DecMapStringInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]int32: + fastpathTV.DecMapStringInt32V(v, fastpathCheckNilFalse, false, d) + case *map[string]int32: + v2, changed2 := fastpathTV.DecMapStringInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]int64: + fastpathTV.DecMapStringInt64V(v, fastpathCheckNilFalse, false, d) + case *map[string]int64: + v2, changed2 := fastpathTV.DecMapStringInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]float32: + fastpathTV.DecMapStringFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[string]float32: + v2, changed2 := fastpathTV.DecMapStringFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]float64: + fastpathTV.DecMapStringFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[string]float64: + v2, changed2 := fastpathTV.DecMapStringFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[string]bool: + fastpathTV.DecMapStringBoolV(v, fastpathCheckNilFalse, false, d) + case *map[string]bool: + v2, changed2 := fastpathTV.DecMapStringBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []float32: + fastpathTV.DecSliceFloat32V(v, fastpathCheckNilFalse, false, d) + case *[]float32: + v2, changed2 := fastpathTV.DecSliceFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]interface{}: + fastpathTV.DecMapFloat32IntfV(v, fastpathCheckNilFalse, false, d) + case *map[float32]interface{}: + v2, changed2 := fastpathTV.DecMapFloat32IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]string: + fastpathTV.DecMapFloat32StringV(v, fastpathCheckNilFalse, false, d) + case *map[float32]string: + v2, changed2 := fastpathTV.DecMapFloat32StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uint: + fastpathTV.DecMapFloat32UintV(v, fastpathCheckNilFalse, false, d) + case *map[float32]uint: + v2, changed2 := fastpathTV.DecMapFloat32UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uint8: + fastpathTV.DecMapFloat32Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[float32]uint8: + v2, changed2 := fastpathTV.DecMapFloat32Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uint16: + fastpathTV.DecMapFloat32Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[float32]uint16: + v2, changed2 := fastpathTV.DecMapFloat32Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uint32: + fastpathTV.DecMapFloat32Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[float32]uint32: + v2, changed2 := fastpathTV.DecMapFloat32Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uint64: + fastpathTV.DecMapFloat32Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[float32]uint64: + v2, changed2 := fastpathTV.DecMapFloat32Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]uintptr: + fastpathTV.DecMapFloat32UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[float32]uintptr: + v2, changed2 := fastpathTV.DecMapFloat32UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]int: + fastpathTV.DecMapFloat32IntV(v, fastpathCheckNilFalse, false, d) + case *map[float32]int: + v2, changed2 := fastpathTV.DecMapFloat32IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]int8: + fastpathTV.DecMapFloat32Int8V(v, fastpathCheckNilFalse, false, d) + case *map[float32]int8: + v2, changed2 := fastpathTV.DecMapFloat32Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]int16: + fastpathTV.DecMapFloat32Int16V(v, fastpathCheckNilFalse, false, d) + case *map[float32]int16: + v2, changed2 := fastpathTV.DecMapFloat32Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]int32: + fastpathTV.DecMapFloat32Int32V(v, fastpathCheckNilFalse, false, d) + case *map[float32]int32: + v2, changed2 := fastpathTV.DecMapFloat32Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]int64: + fastpathTV.DecMapFloat32Int64V(v, fastpathCheckNilFalse, false, d) + case *map[float32]int64: + v2, changed2 := fastpathTV.DecMapFloat32Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]float32: + fastpathTV.DecMapFloat32Float32V(v, fastpathCheckNilFalse, false, d) + case *map[float32]float32: + v2, changed2 := fastpathTV.DecMapFloat32Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]float64: + fastpathTV.DecMapFloat32Float64V(v, fastpathCheckNilFalse, false, d) + case *map[float32]float64: + v2, changed2 := fastpathTV.DecMapFloat32Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float32]bool: + fastpathTV.DecMapFloat32BoolV(v, fastpathCheckNilFalse, false, d) + case *map[float32]bool: + v2, changed2 := fastpathTV.DecMapFloat32BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []float64: + fastpathTV.DecSliceFloat64V(v, fastpathCheckNilFalse, false, d) + case *[]float64: + v2, changed2 := fastpathTV.DecSliceFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]interface{}: + fastpathTV.DecMapFloat64IntfV(v, fastpathCheckNilFalse, false, d) + case *map[float64]interface{}: + v2, changed2 := fastpathTV.DecMapFloat64IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]string: + fastpathTV.DecMapFloat64StringV(v, fastpathCheckNilFalse, false, d) + case *map[float64]string: + v2, changed2 := fastpathTV.DecMapFloat64StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uint: + fastpathTV.DecMapFloat64UintV(v, fastpathCheckNilFalse, false, d) + case *map[float64]uint: + v2, changed2 := fastpathTV.DecMapFloat64UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uint8: + fastpathTV.DecMapFloat64Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[float64]uint8: + v2, changed2 := fastpathTV.DecMapFloat64Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uint16: + fastpathTV.DecMapFloat64Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[float64]uint16: + v2, changed2 := fastpathTV.DecMapFloat64Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uint32: + fastpathTV.DecMapFloat64Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[float64]uint32: + v2, changed2 := fastpathTV.DecMapFloat64Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uint64: + fastpathTV.DecMapFloat64Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[float64]uint64: + v2, changed2 := fastpathTV.DecMapFloat64Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]uintptr: + fastpathTV.DecMapFloat64UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[float64]uintptr: + v2, changed2 := fastpathTV.DecMapFloat64UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]int: + fastpathTV.DecMapFloat64IntV(v, fastpathCheckNilFalse, false, d) + case *map[float64]int: + v2, changed2 := fastpathTV.DecMapFloat64IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]int8: + fastpathTV.DecMapFloat64Int8V(v, fastpathCheckNilFalse, false, d) + case *map[float64]int8: + v2, changed2 := fastpathTV.DecMapFloat64Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]int16: + fastpathTV.DecMapFloat64Int16V(v, fastpathCheckNilFalse, false, d) + case *map[float64]int16: + v2, changed2 := fastpathTV.DecMapFloat64Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]int32: + fastpathTV.DecMapFloat64Int32V(v, fastpathCheckNilFalse, false, d) + case *map[float64]int32: + v2, changed2 := fastpathTV.DecMapFloat64Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]int64: + fastpathTV.DecMapFloat64Int64V(v, fastpathCheckNilFalse, false, d) + case *map[float64]int64: + v2, changed2 := fastpathTV.DecMapFloat64Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]float32: + fastpathTV.DecMapFloat64Float32V(v, fastpathCheckNilFalse, false, d) + case *map[float64]float32: + v2, changed2 := fastpathTV.DecMapFloat64Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]float64: + fastpathTV.DecMapFloat64Float64V(v, fastpathCheckNilFalse, false, d) + case *map[float64]float64: + v2, changed2 := fastpathTV.DecMapFloat64Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[float64]bool: + fastpathTV.DecMapFloat64BoolV(v, fastpathCheckNilFalse, false, d) + case *map[float64]bool: + v2, changed2 := fastpathTV.DecMapFloat64BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []uint: + fastpathTV.DecSliceUintV(v, fastpathCheckNilFalse, false, d) + case *[]uint: + v2, changed2 := fastpathTV.DecSliceUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]interface{}: + fastpathTV.DecMapUintIntfV(v, fastpathCheckNilFalse, false, d) + case *map[uint]interface{}: + v2, changed2 := fastpathTV.DecMapUintIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]string: + fastpathTV.DecMapUintStringV(v, fastpathCheckNilFalse, false, d) + case *map[uint]string: + v2, changed2 := fastpathTV.DecMapUintStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uint: + fastpathTV.DecMapUintUintV(v, fastpathCheckNilFalse, false, d) + case *map[uint]uint: + v2, changed2 := fastpathTV.DecMapUintUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uint8: + fastpathTV.DecMapUintUint8V(v, fastpathCheckNilFalse, false, d) + case *map[uint]uint8: + v2, changed2 := fastpathTV.DecMapUintUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uint16: + fastpathTV.DecMapUintUint16V(v, fastpathCheckNilFalse, false, d) + case *map[uint]uint16: + v2, changed2 := fastpathTV.DecMapUintUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uint32: + fastpathTV.DecMapUintUint32V(v, fastpathCheckNilFalse, false, d) + case *map[uint]uint32: + v2, changed2 := fastpathTV.DecMapUintUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uint64: + fastpathTV.DecMapUintUint64V(v, fastpathCheckNilFalse, false, d) + case *map[uint]uint64: + v2, changed2 := fastpathTV.DecMapUintUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]uintptr: + fastpathTV.DecMapUintUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uint]uintptr: + v2, changed2 := fastpathTV.DecMapUintUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]int: + fastpathTV.DecMapUintIntV(v, fastpathCheckNilFalse, false, d) + case *map[uint]int: + v2, changed2 := fastpathTV.DecMapUintIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]int8: + fastpathTV.DecMapUintInt8V(v, fastpathCheckNilFalse, false, d) + case *map[uint]int8: + v2, changed2 := fastpathTV.DecMapUintInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]int16: + fastpathTV.DecMapUintInt16V(v, fastpathCheckNilFalse, false, d) + case *map[uint]int16: + v2, changed2 := fastpathTV.DecMapUintInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]int32: + fastpathTV.DecMapUintInt32V(v, fastpathCheckNilFalse, false, d) + case *map[uint]int32: + v2, changed2 := fastpathTV.DecMapUintInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]int64: + fastpathTV.DecMapUintInt64V(v, fastpathCheckNilFalse, false, d) + case *map[uint]int64: + v2, changed2 := fastpathTV.DecMapUintInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]float32: + fastpathTV.DecMapUintFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[uint]float32: + v2, changed2 := fastpathTV.DecMapUintFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]float64: + fastpathTV.DecMapUintFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[uint]float64: + v2, changed2 := fastpathTV.DecMapUintFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint]bool: + fastpathTV.DecMapUintBoolV(v, fastpathCheckNilFalse, false, d) + case *map[uint]bool: + v2, changed2 := fastpathTV.DecMapUintBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]interface{}: + fastpathTV.DecMapUint8IntfV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]interface{}: + v2, changed2 := fastpathTV.DecMapUint8IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]string: + fastpathTV.DecMapUint8StringV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]string: + v2, changed2 := fastpathTV.DecMapUint8StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uint: + fastpathTV.DecMapUint8UintV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uint: + v2, changed2 := fastpathTV.DecMapUint8UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uint8: + fastpathTV.DecMapUint8Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uint8: + v2, changed2 := fastpathTV.DecMapUint8Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uint16: + fastpathTV.DecMapUint8Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uint16: + v2, changed2 := fastpathTV.DecMapUint8Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uint32: + fastpathTV.DecMapUint8Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uint32: + v2, changed2 := fastpathTV.DecMapUint8Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uint64: + fastpathTV.DecMapUint8Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uint64: + v2, changed2 := fastpathTV.DecMapUint8Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]uintptr: + fastpathTV.DecMapUint8UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]uintptr: + v2, changed2 := fastpathTV.DecMapUint8UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]int: + fastpathTV.DecMapUint8IntV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]int: + v2, changed2 := fastpathTV.DecMapUint8IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]int8: + fastpathTV.DecMapUint8Int8V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]int8: + v2, changed2 := fastpathTV.DecMapUint8Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]int16: + fastpathTV.DecMapUint8Int16V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]int16: + v2, changed2 := fastpathTV.DecMapUint8Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]int32: + fastpathTV.DecMapUint8Int32V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]int32: + v2, changed2 := fastpathTV.DecMapUint8Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]int64: + fastpathTV.DecMapUint8Int64V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]int64: + v2, changed2 := fastpathTV.DecMapUint8Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]float32: + fastpathTV.DecMapUint8Float32V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]float32: + v2, changed2 := fastpathTV.DecMapUint8Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]float64: + fastpathTV.DecMapUint8Float64V(v, fastpathCheckNilFalse, false, d) + case *map[uint8]float64: + v2, changed2 := fastpathTV.DecMapUint8Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint8]bool: + fastpathTV.DecMapUint8BoolV(v, fastpathCheckNilFalse, false, d) + case *map[uint8]bool: + v2, changed2 := fastpathTV.DecMapUint8BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []uint16: + fastpathTV.DecSliceUint16V(v, fastpathCheckNilFalse, false, d) + case *[]uint16: + v2, changed2 := fastpathTV.DecSliceUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]interface{}: + fastpathTV.DecMapUint16IntfV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]interface{}: + v2, changed2 := fastpathTV.DecMapUint16IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]string: + fastpathTV.DecMapUint16StringV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]string: + v2, changed2 := fastpathTV.DecMapUint16StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uint: + fastpathTV.DecMapUint16UintV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uint: + v2, changed2 := fastpathTV.DecMapUint16UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uint8: + fastpathTV.DecMapUint16Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uint8: + v2, changed2 := fastpathTV.DecMapUint16Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uint16: + fastpathTV.DecMapUint16Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uint16: + v2, changed2 := fastpathTV.DecMapUint16Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uint32: + fastpathTV.DecMapUint16Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uint32: + v2, changed2 := fastpathTV.DecMapUint16Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uint64: + fastpathTV.DecMapUint16Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uint64: + v2, changed2 := fastpathTV.DecMapUint16Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]uintptr: + fastpathTV.DecMapUint16UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]uintptr: + v2, changed2 := fastpathTV.DecMapUint16UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]int: + fastpathTV.DecMapUint16IntV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]int: + v2, changed2 := fastpathTV.DecMapUint16IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]int8: + fastpathTV.DecMapUint16Int8V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]int8: + v2, changed2 := fastpathTV.DecMapUint16Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]int16: + fastpathTV.DecMapUint16Int16V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]int16: + v2, changed2 := fastpathTV.DecMapUint16Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]int32: + fastpathTV.DecMapUint16Int32V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]int32: + v2, changed2 := fastpathTV.DecMapUint16Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]int64: + fastpathTV.DecMapUint16Int64V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]int64: + v2, changed2 := fastpathTV.DecMapUint16Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]float32: + fastpathTV.DecMapUint16Float32V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]float32: + v2, changed2 := fastpathTV.DecMapUint16Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]float64: + fastpathTV.DecMapUint16Float64V(v, fastpathCheckNilFalse, false, d) + case *map[uint16]float64: + v2, changed2 := fastpathTV.DecMapUint16Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint16]bool: + fastpathTV.DecMapUint16BoolV(v, fastpathCheckNilFalse, false, d) + case *map[uint16]bool: + v2, changed2 := fastpathTV.DecMapUint16BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []uint32: + fastpathTV.DecSliceUint32V(v, fastpathCheckNilFalse, false, d) + case *[]uint32: + v2, changed2 := fastpathTV.DecSliceUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]interface{}: + fastpathTV.DecMapUint32IntfV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]interface{}: + v2, changed2 := fastpathTV.DecMapUint32IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]string: + fastpathTV.DecMapUint32StringV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]string: + v2, changed2 := fastpathTV.DecMapUint32StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uint: + fastpathTV.DecMapUint32UintV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uint: + v2, changed2 := fastpathTV.DecMapUint32UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uint8: + fastpathTV.DecMapUint32Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uint8: + v2, changed2 := fastpathTV.DecMapUint32Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uint16: + fastpathTV.DecMapUint32Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uint16: + v2, changed2 := fastpathTV.DecMapUint32Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uint32: + fastpathTV.DecMapUint32Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uint32: + v2, changed2 := fastpathTV.DecMapUint32Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uint64: + fastpathTV.DecMapUint32Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uint64: + v2, changed2 := fastpathTV.DecMapUint32Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]uintptr: + fastpathTV.DecMapUint32UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]uintptr: + v2, changed2 := fastpathTV.DecMapUint32UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]int: + fastpathTV.DecMapUint32IntV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]int: + v2, changed2 := fastpathTV.DecMapUint32IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]int8: + fastpathTV.DecMapUint32Int8V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]int8: + v2, changed2 := fastpathTV.DecMapUint32Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]int16: + fastpathTV.DecMapUint32Int16V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]int16: + v2, changed2 := fastpathTV.DecMapUint32Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]int32: + fastpathTV.DecMapUint32Int32V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]int32: + v2, changed2 := fastpathTV.DecMapUint32Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]int64: + fastpathTV.DecMapUint32Int64V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]int64: + v2, changed2 := fastpathTV.DecMapUint32Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]float32: + fastpathTV.DecMapUint32Float32V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]float32: + v2, changed2 := fastpathTV.DecMapUint32Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]float64: + fastpathTV.DecMapUint32Float64V(v, fastpathCheckNilFalse, false, d) + case *map[uint32]float64: + v2, changed2 := fastpathTV.DecMapUint32Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint32]bool: + fastpathTV.DecMapUint32BoolV(v, fastpathCheckNilFalse, false, d) + case *map[uint32]bool: + v2, changed2 := fastpathTV.DecMapUint32BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []uint64: + fastpathTV.DecSliceUint64V(v, fastpathCheckNilFalse, false, d) + case *[]uint64: + v2, changed2 := fastpathTV.DecSliceUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]interface{}: + fastpathTV.DecMapUint64IntfV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]interface{}: + v2, changed2 := fastpathTV.DecMapUint64IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]string: + fastpathTV.DecMapUint64StringV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]string: + v2, changed2 := fastpathTV.DecMapUint64StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uint: + fastpathTV.DecMapUint64UintV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uint: + v2, changed2 := fastpathTV.DecMapUint64UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uint8: + fastpathTV.DecMapUint64Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uint8: + v2, changed2 := fastpathTV.DecMapUint64Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uint16: + fastpathTV.DecMapUint64Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uint16: + v2, changed2 := fastpathTV.DecMapUint64Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uint32: + fastpathTV.DecMapUint64Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uint32: + v2, changed2 := fastpathTV.DecMapUint64Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uint64: + fastpathTV.DecMapUint64Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uint64: + v2, changed2 := fastpathTV.DecMapUint64Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]uintptr: + fastpathTV.DecMapUint64UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]uintptr: + v2, changed2 := fastpathTV.DecMapUint64UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]int: + fastpathTV.DecMapUint64IntV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]int: + v2, changed2 := fastpathTV.DecMapUint64IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]int8: + fastpathTV.DecMapUint64Int8V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]int8: + v2, changed2 := fastpathTV.DecMapUint64Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]int16: + fastpathTV.DecMapUint64Int16V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]int16: + v2, changed2 := fastpathTV.DecMapUint64Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]int32: + fastpathTV.DecMapUint64Int32V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]int32: + v2, changed2 := fastpathTV.DecMapUint64Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]int64: + fastpathTV.DecMapUint64Int64V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]int64: + v2, changed2 := fastpathTV.DecMapUint64Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]float32: + fastpathTV.DecMapUint64Float32V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]float32: + v2, changed2 := fastpathTV.DecMapUint64Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]float64: + fastpathTV.DecMapUint64Float64V(v, fastpathCheckNilFalse, false, d) + case *map[uint64]float64: + v2, changed2 := fastpathTV.DecMapUint64Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uint64]bool: + fastpathTV.DecMapUint64BoolV(v, fastpathCheckNilFalse, false, d) + case *map[uint64]bool: + v2, changed2 := fastpathTV.DecMapUint64BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []uintptr: + fastpathTV.DecSliceUintptrV(v, fastpathCheckNilFalse, false, d) + case *[]uintptr: + v2, changed2 := fastpathTV.DecSliceUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]interface{}: + fastpathTV.DecMapUintptrIntfV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]interface{}: + v2, changed2 := fastpathTV.DecMapUintptrIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]string: + fastpathTV.DecMapUintptrStringV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]string: + v2, changed2 := fastpathTV.DecMapUintptrStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uint: + fastpathTV.DecMapUintptrUintV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uint: + v2, changed2 := fastpathTV.DecMapUintptrUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uint8: + fastpathTV.DecMapUintptrUint8V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uint8: + v2, changed2 := fastpathTV.DecMapUintptrUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uint16: + fastpathTV.DecMapUintptrUint16V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uint16: + v2, changed2 := fastpathTV.DecMapUintptrUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uint32: + fastpathTV.DecMapUintptrUint32V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uint32: + v2, changed2 := fastpathTV.DecMapUintptrUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uint64: + fastpathTV.DecMapUintptrUint64V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uint64: + v2, changed2 := fastpathTV.DecMapUintptrUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]uintptr: + fastpathTV.DecMapUintptrUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]uintptr: + v2, changed2 := fastpathTV.DecMapUintptrUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]int: + fastpathTV.DecMapUintptrIntV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]int: + v2, changed2 := fastpathTV.DecMapUintptrIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]int8: + fastpathTV.DecMapUintptrInt8V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]int8: + v2, changed2 := fastpathTV.DecMapUintptrInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]int16: + fastpathTV.DecMapUintptrInt16V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]int16: + v2, changed2 := fastpathTV.DecMapUintptrInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]int32: + fastpathTV.DecMapUintptrInt32V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]int32: + v2, changed2 := fastpathTV.DecMapUintptrInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]int64: + fastpathTV.DecMapUintptrInt64V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]int64: + v2, changed2 := fastpathTV.DecMapUintptrInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]float32: + fastpathTV.DecMapUintptrFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]float32: + v2, changed2 := fastpathTV.DecMapUintptrFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]float64: + fastpathTV.DecMapUintptrFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]float64: + v2, changed2 := fastpathTV.DecMapUintptrFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[uintptr]bool: + fastpathTV.DecMapUintptrBoolV(v, fastpathCheckNilFalse, false, d) + case *map[uintptr]bool: + v2, changed2 := fastpathTV.DecMapUintptrBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []int: + fastpathTV.DecSliceIntV(v, fastpathCheckNilFalse, false, d) + case *[]int: + v2, changed2 := fastpathTV.DecSliceIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]interface{}: + fastpathTV.DecMapIntIntfV(v, fastpathCheckNilFalse, false, d) + case *map[int]interface{}: + v2, changed2 := fastpathTV.DecMapIntIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]string: + fastpathTV.DecMapIntStringV(v, fastpathCheckNilFalse, false, d) + case *map[int]string: + v2, changed2 := fastpathTV.DecMapIntStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uint: + fastpathTV.DecMapIntUintV(v, fastpathCheckNilFalse, false, d) + case *map[int]uint: + v2, changed2 := fastpathTV.DecMapIntUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uint8: + fastpathTV.DecMapIntUint8V(v, fastpathCheckNilFalse, false, d) + case *map[int]uint8: + v2, changed2 := fastpathTV.DecMapIntUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uint16: + fastpathTV.DecMapIntUint16V(v, fastpathCheckNilFalse, false, d) + case *map[int]uint16: + v2, changed2 := fastpathTV.DecMapIntUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uint32: + fastpathTV.DecMapIntUint32V(v, fastpathCheckNilFalse, false, d) + case *map[int]uint32: + v2, changed2 := fastpathTV.DecMapIntUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uint64: + fastpathTV.DecMapIntUint64V(v, fastpathCheckNilFalse, false, d) + case *map[int]uint64: + v2, changed2 := fastpathTV.DecMapIntUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]uintptr: + fastpathTV.DecMapIntUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[int]uintptr: + v2, changed2 := fastpathTV.DecMapIntUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]int: + fastpathTV.DecMapIntIntV(v, fastpathCheckNilFalse, false, d) + case *map[int]int: + v2, changed2 := fastpathTV.DecMapIntIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]int8: + fastpathTV.DecMapIntInt8V(v, fastpathCheckNilFalse, false, d) + case *map[int]int8: + v2, changed2 := fastpathTV.DecMapIntInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]int16: + fastpathTV.DecMapIntInt16V(v, fastpathCheckNilFalse, false, d) + case *map[int]int16: + v2, changed2 := fastpathTV.DecMapIntInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]int32: + fastpathTV.DecMapIntInt32V(v, fastpathCheckNilFalse, false, d) + case *map[int]int32: + v2, changed2 := fastpathTV.DecMapIntInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]int64: + fastpathTV.DecMapIntInt64V(v, fastpathCheckNilFalse, false, d) + case *map[int]int64: + v2, changed2 := fastpathTV.DecMapIntInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]float32: + fastpathTV.DecMapIntFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[int]float32: + v2, changed2 := fastpathTV.DecMapIntFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]float64: + fastpathTV.DecMapIntFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[int]float64: + v2, changed2 := fastpathTV.DecMapIntFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int]bool: + fastpathTV.DecMapIntBoolV(v, fastpathCheckNilFalse, false, d) + case *map[int]bool: + v2, changed2 := fastpathTV.DecMapIntBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []int8: + fastpathTV.DecSliceInt8V(v, fastpathCheckNilFalse, false, d) + case *[]int8: + v2, changed2 := fastpathTV.DecSliceInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]interface{}: + fastpathTV.DecMapInt8IntfV(v, fastpathCheckNilFalse, false, d) + case *map[int8]interface{}: + v2, changed2 := fastpathTV.DecMapInt8IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]string: + fastpathTV.DecMapInt8StringV(v, fastpathCheckNilFalse, false, d) + case *map[int8]string: + v2, changed2 := fastpathTV.DecMapInt8StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uint: + fastpathTV.DecMapInt8UintV(v, fastpathCheckNilFalse, false, d) + case *map[int8]uint: + v2, changed2 := fastpathTV.DecMapInt8UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uint8: + fastpathTV.DecMapInt8Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[int8]uint8: + v2, changed2 := fastpathTV.DecMapInt8Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uint16: + fastpathTV.DecMapInt8Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[int8]uint16: + v2, changed2 := fastpathTV.DecMapInt8Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uint32: + fastpathTV.DecMapInt8Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[int8]uint32: + v2, changed2 := fastpathTV.DecMapInt8Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uint64: + fastpathTV.DecMapInt8Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[int8]uint64: + v2, changed2 := fastpathTV.DecMapInt8Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]uintptr: + fastpathTV.DecMapInt8UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[int8]uintptr: + v2, changed2 := fastpathTV.DecMapInt8UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]int: + fastpathTV.DecMapInt8IntV(v, fastpathCheckNilFalse, false, d) + case *map[int8]int: + v2, changed2 := fastpathTV.DecMapInt8IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]int8: + fastpathTV.DecMapInt8Int8V(v, fastpathCheckNilFalse, false, d) + case *map[int8]int8: + v2, changed2 := fastpathTV.DecMapInt8Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]int16: + fastpathTV.DecMapInt8Int16V(v, fastpathCheckNilFalse, false, d) + case *map[int8]int16: + v2, changed2 := fastpathTV.DecMapInt8Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]int32: + fastpathTV.DecMapInt8Int32V(v, fastpathCheckNilFalse, false, d) + case *map[int8]int32: + v2, changed2 := fastpathTV.DecMapInt8Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]int64: + fastpathTV.DecMapInt8Int64V(v, fastpathCheckNilFalse, false, d) + case *map[int8]int64: + v2, changed2 := fastpathTV.DecMapInt8Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]float32: + fastpathTV.DecMapInt8Float32V(v, fastpathCheckNilFalse, false, d) + case *map[int8]float32: + v2, changed2 := fastpathTV.DecMapInt8Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]float64: + fastpathTV.DecMapInt8Float64V(v, fastpathCheckNilFalse, false, d) + case *map[int8]float64: + v2, changed2 := fastpathTV.DecMapInt8Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int8]bool: + fastpathTV.DecMapInt8BoolV(v, fastpathCheckNilFalse, false, d) + case *map[int8]bool: + v2, changed2 := fastpathTV.DecMapInt8BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []int16: + fastpathTV.DecSliceInt16V(v, fastpathCheckNilFalse, false, d) + case *[]int16: + v2, changed2 := fastpathTV.DecSliceInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]interface{}: + fastpathTV.DecMapInt16IntfV(v, fastpathCheckNilFalse, false, d) + case *map[int16]interface{}: + v2, changed2 := fastpathTV.DecMapInt16IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]string: + fastpathTV.DecMapInt16StringV(v, fastpathCheckNilFalse, false, d) + case *map[int16]string: + v2, changed2 := fastpathTV.DecMapInt16StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uint: + fastpathTV.DecMapInt16UintV(v, fastpathCheckNilFalse, false, d) + case *map[int16]uint: + v2, changed2 := fastpathTV.DecMapInt16UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uint8: + fastpathTV.DecMapInt16Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[int16]uint8: + v2, changed2 := fastpathTV.DecMapInt16Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uint16: + fastpathTV.DecMapInt16Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[int16]uint16: + v2, changed2 := fastpathTV.DecMapInt16Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uint32: + fastpathTV.DecMapInt16Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[int16]uint32: + v2, changed2 := fastpathTV.DecMapInt16Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uint64: + fastpathTV.DecMapInt16Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[int16]uint64: + v2, changed2 := fastpathTV.DecMapInt16Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]uintptr: + fastpathTV.DecMapInt16UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[int16]uintptr: + v2, changed2 := fastpathTV.DecMapInt16UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]int: + fastpathTV.DecMapInt16IntV(v, fastpathCheckNilFalse, false, d) + case *map[int16]int: + v2, changed2 := fastpathTV.DecMapInt16IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]int8: + fastpathTV.DecMapInt16Int8V(v, fastpathCheckNilFalse, false, d) + case *map[int16]int8: + v2, changed2 := fastpathTV.DecMapInt16Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]int16: + fastpathTV.DecMapInt16Int16V(v, fastpathCheckNilFalse, false, d) + case *map[int16]int16: + v2, changed2 := fastpathTV.DecMapInt16Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]int32: + fastpathTV.DecMapInt16Int32V(v, fastpathCheckNilFalse, false, d) + case *map[int16]int32: + v2, changed2 := fastpathTV.DecMapInt16Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]int64: + fastpathTV.DecMapInt16Int64V(v, fastpathCheckNilFalse, false, d) + case *map[int16]int64: + v2, changed2 := fastpathTV.DecMapInt16Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]float32: + fastpathTV.DecMapInt16Float32V(v, fastpathCheckNilFalse, false, d) + case *map[int16]float32: + v2, changed2 := fastpathTV.DecMapInt16Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]float64: + fastpathTV.DecMapInt16Float64V(v, fastpathCheckNilFalse, false, d) + case *map[int16]float64: + v2, changed2 := fastpathTV.DecMapInt16Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int16]bool: + fastpathTV.DecMapInt16BoolV(v, fastpathCheckNilFalse, false, d) + case *map[int16]bool: + v2, changed2 := fastpathTV.DecMapInt16BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []int32: + fastpathTV.DecSliceInt32V(v, fastpathCheckNilFalse, false, d) + case *[]int32: + v2, changed2 := fastpathTV.DecSliceInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]interface{}: + fastpathTV.DecMapInt32IntfV(v, fastpathCheckNilFalse, false, d) + case *map[int32]interface{}: + v2, changed2 := fastpathTV.DecMapInt32IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]string: + fastpathTV.DecMapInt32StringV(v, fastpathCheckNilFalse, false, d) + case *map[int32]string: + v2, changed2 := fastpathTV.DecMapInt32StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uint: + fastpathTV.DecMapInt32UintV(v, fastpathCheckNilFalse, false, d) + case *map[int32]uint: + v2, changed2 := fastpathTV.DecMapInt32UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uint8: + fastpathTV.DecMapInt32Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[int32]uint8: + v2, changed2 := fastpathTV.DecMapInt32Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uint16: + fastpathTV.DecMapInt32Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[int32]uint16: + v2, changed2 := fastpathTV.DecMapInt32Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uint32: + fastpathTV.DecMapInt32Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[int32]uint32: + v2, changed2 := fastpathTV.DecMapInt32Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uint64: + fastpathTV.DecMapInt32Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[int32]uint64: + v2, changed2 := fastpathTV.DecMapInt32Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]uintptr: + fastpathTV.DecMapInt32UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[int32]uintptr: + v2, changed2 := fastpathTV.DecMapInt32UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]int: + fastpathTV.DecMapInt32IntV(v, fastpathCheckNilFalse, false, d) + case *map[int32]int: + v2, changed2 := fastpathTV.DecMapInt32IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]int8: + fastpathTV.DecMapInt32Int8V(v, fastpathCheckNilFalse, false, d) + case *map[int32]int8: + v2, changed2 := fastpathTV.DecMapInt32Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]int16: + fastpathTV.DecMapInt32Int16V(v, fastpathCheckNilFalse, false, d) + case *map[int32]int16: + v2, changed2 := fastpathTV.DecMapInt32Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]int32: + fastpathTV.DecMapInt32Int32V(v, fastpathCheckNilFalse, false, d) + case *map[int32]int32: + v2, changed2 := fastpathTV.DecMapInt32Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]int64: + fastpathTV.DecMapInt32Int64V(v, fastpathCheckNilFalse, false, d) + case *map[int32]int64: + v2, changed2 := fastpathTV.DecMapInt32Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]float32: + fastpathTV.DecMapInt32Float32V(v, fastpathCheckNilFalse, false, d) + case *map[int32]float32: + v2, changed2 := fastpathTV.DecMapInt32Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]float64: + fastpathTV.DecMapInt32Float64V(v, fastpathCheckNilFalse, false, d) + case *map[int32]float64: + v2, changed2 := fastpathTV.DecMapInt32Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int32]bool: + fastpathTV.DecMapInt32BoolV(v, fastpathCheckNilFalse, false, d) + case *map[int32]bool: + v2, changed2 := fastpathTV.DecMapInt32BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []int64: + fastpathTV.DecSliceInt64V(v, fastpathCheckNilFalse, false, d) + case *[]int64: + v2, changed2 := fastpathTV.DecSliceInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]interface{}: + fastpathTV.DecMapInt64IntfV(v, fastpathCheckNilFalse, false, d) + case *map[int64]interface{}: + v2, changed2 := fastpathTV.DecMapInt64IntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]string: + fastpathTV.DecMapInt64StringV(v, fastpathCheckNilFalse, false, d) + case *map[int64]string: + v2, changed2 := fastpathTV.DecMapInt64StringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uint: + fastpathTV.DecMapInt64UintV(v, fastpathCheckNilFalse, false, d) + case *map[int64]uint: + v2, changed2 := fastpathTV.DecMapInt64UintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uint8: + fastpathTV.DecMapInt64Uint8V(v, fastpathCheckNilFalse, false, d) + case *map[int64]uint8: + v2, changed2 := fastpathTV.DecMapInt64Uint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uint16: + fastpathTV.DecMapInt64Uint16V(v, fastpathCheckNilFalse, false, d) + case *map[int64]uint16: + v2, changed2 := fastpathTV.DecMapInt64Uint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uint32: + fastpathTV.DecMapInt64Uint32V(v, fastpathCheckNilFalse, false, d) + case *map[int64]uint32: + v2, changed2 := fastpathTV.DecMapInt64Uint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uint64: + fastpathTV.DecMapInt64Uint64V(v, fastpathCheckNilFalse, false, d) + case *map[int64]uint64: + v2, changed2 := fastpathTV.DecMapInt64Uint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]uintptr: + fastpathTV.DecMapInt64UintptrV(v, fastpathCheckNilFalse, false, d) + case *map[int64]uintptr: + v2, changed2 := fastpathTV.DecMapInt64UintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]int: + fastpathTV.DecMapInt64IntV(v, fastpathCheckNilFalse, false, d) + case *map[int64]int: + v2, changed2 := fastpathTV.DecMapInt64IntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]int8: + fastpathTV.DecMapInt64Int8V(v, fastpathCheckNilFalse, false, d) + case *map[int64]int8: + v2, changed2 := fastpathTV.DecMapInt64Int8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]int16: + fastpathTV.DecMapInt64Int16V(v, fastpathCheckNilFalse, false, d) + case *map[int64]int16: + v2, changed2 := fastpathTV.DecMapInt64Int16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]int32: + fastpathTV.DecMapInt64Int32V(v, fastpathCheckNilFalse, false, d) + case *map[int64]int32: + v2, changed2 := fastpathTV.DecMapInt64Int32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]int64: + fastpathTV.DecMapInt64Int64V(v, fastpathCheckNilFalse, false, d) + case *map[int64]int64: + v2, changed2 := fastpathTV.DecMapInt64Int64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]float32: + fastpathTV.DecMapInt64Float32V(v, fastpathCheckNilFalse, false, d) + case *map[int64]float32: + v2, changed2 := fastpathTV.DecMapInt64Float32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]float64: + fastpathTV.DecMapInt64Float64V(v, fastpathCheckNilFalse, false, d) + case *map[int64]float64: + v2, changed2 := fastpathTV.DecMapInt64Float64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[int64]bool: + fastpathTV.DecMapInt64BoolV(v, fastpathCheckNilFalse, false, d) + case *map[int64]bool: + v2, changed2 := fastpathTV.DecMapInt64BoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case []bool: + fastpathTV.DecSliceBoolV(v, fastpathCheckNilFalse, false, d) + case *[]bool: + v2, changed2 := fastpathTV.DecSliceBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]interface{}: + fastpathTV.DecMapBoolIntfV(v, fastpathCheckNilFalse, false, d) + case *map[bool]interface{}: + v2, changed2 := fastpathTV.DecMapBoolIntfV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]string: + fastpathTV.DecMapBoolStringV(v, fastpathCheckNilFalse, false, d) + case *map[bool]string: + v2, changed2 := fastpathTV.DecMapBoolStringV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uint: + fastpathTV.DecMapBoolUintV(v, fastpathCheckNilFalse, false, d) + case *map[bool]uint: + v2, changed2 := fastpathTV.DecMapBoolUintV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uint8: + fastpathTV.DecMapBoolUint8V(v, fastpathCheckNilFalse, false, d) + case *map[bool]uint8: + v2, changed2 := fastpathTV.DecMapBoolUint8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uint16: + fastpathTV.DecMapBoolUint16V(v, fastpathCheckNilFalse, false, d) + case *map[bool]uint16: + v2, changed2 := fastpathTV.DecMapBoolUint16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uint32: + fastpathTV.DecMapBoolUint32V(v, fastpathCheckNilFalse, false, d) + case *map[bool]uint32: + v2, changed2 := fastpathTV.DecMapBoolUint32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uint64: + fastpathTV.DecMapBoolUint64V(v, fastpathCheckNilFalse, false, d) + case *map[bool]uint64: + v2, changed2 := fastpathTV.DecMapBoolUint64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]uintptr: + fastpathTV.DecMapBoolUintptrV(v, fastpathCheckNilFalse, false, d) + case *map[bool]uintptr: + v2, changed2 := fastpathTV.DecMapBoolUintptrV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]int: + fastpathTV.DecMapBoolIntV(v, fastpathCheckNilFalse, false, d) + case *map[bool]int: + v2, changed2 := fastpathTV.DecMapBoolIntV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]int8: + fastpathTV.DecMapBoolInt8V(v, fastpathCheckNilFalse, false, d) + case *map[bool]int8: + v2, changed2 := fastpathTV.DecMapBoolInt8V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]int16: + fastpathTV.DecMapBoolInt16V(v, fastpathCheckNilFalse, false, d) + case *map[bool]int16: + v2, changed2 := fastpathTV.DecMapBoolInt16V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]int32: + fastpathTV.DecMapBoolInt32V(v, fastpathCheckNilFalse, false, d) + case *map[bool]int32: + v2, changed2 := fastpathTV.DecMapBoolInt32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]int64: + fastpathTV.DecMapBoolInt64V(v, fastpathCheckNilFalse, false, d) + case *map[bool]int64: + v2, changed2 := fastpathTV.DecMapBoolInt64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]float32: + fastpathTV.DecMapBoolFloat32V(v, fastpathCheckNilFalse, false, d) + case *map[bool]float32: + v2, changed2 := fastpathTV.DecMapBoolFloat32V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]float64: + fastpathTV.DecMapBoolFloat64V(v, fastpathCheckNilFalse, false, d) + case *map[bool]float64: + v2, changed2 := fastpathTV.DecMapBoolFloat64V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + case map[bool]bool: + fastpathTV.DecMapBoolBoolV(v, fastpathCheckNilFalse, false, d) + case *map[bool]bool: + v2, changed2 := fastpathTV.DecMapBoolBoolV(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } + + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +// -- -- fast path functions + +func (f *decFnInfo) fastpathDecSliceIntfR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]interface{}) + v, changed := fastpathTV.DecSliceIntfV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]interface{}) + fastpathTV.DecSliceIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceIntfX(vp *[]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecSliceIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceIntfV(v []interface{}, checkNil bool, canChange bool, d *Decoder) (_ []interface{}, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []interface{}{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 16) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]interface{}, xlen) + } + } else { + v = make([]interface{}, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + d.decode(&v[j]) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, nil) + slh.ElemContainerState(j) + d.decode(&v[j]) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []interface{}{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]interface{}, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, nil) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + d.decode(&v[j]) + + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceStringR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]string) + v, changed := fastpathTV.DecSliceStringV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]string) + fastpathTV.DecSliceStringV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceStringX(vp *[]string, checkNil bool, d *Decoder) { + v, changed := f.DecSliceStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceStringV(v []string, checkNil bool, canChange bool, d *Decoder) (_ []string, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []string{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 16) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]string, xlen) + } + } else { + v = make([]string, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = dd.DecodeString() + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, "") + slh.ElemContainerState(j) + v[j] = dd.DecodeString() + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []string{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]string, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, "") + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = dd.DecodeString() + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceFloat32R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]float32) + v, changed := fastpathTV.DecSliceFloat32V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]float32) + fastpathTV.DecSliceFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceFloat32X(vp *[]float32, checkNil bool, d *Decoder) { + v, changed := f.DecSliceFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceFloat32V(v []float32, checkNil bool, canChange bool, d *Decoder) (_ []float32, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []float32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 4) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]float32, xlen) + } + } else { + v = make([]float32, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = float32(dd.DecodeFloat(true)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = float32(dd.DecodeFloat(true)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []float32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]float32, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = float32(dd.DecodeFloat(true)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceFloat64R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]float64) + v, changed := fastpathTV.DecSliceFloat64V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]float64) + fastpathTV.DecSliceFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceFloat64X(vp *[]float64, checkNil bool, d *Decoder) { + v, changed := f.DecSliceFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceFloat64V(v []float64, checkNil bool, canChange bool, d *Decoder) (_ []float64, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []float64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]float64, xlen) + } + } else { + v = make([]float64, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = dd.DecodeFloat(false) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = dd.DecodeFloat(false) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []float64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]float64, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = dd.DecodeFloat(false) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceUintR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]uint) + v, changed := fastpathTV.DecSliceUintV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]uint) + fastpathTV.DecSliceUintV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceUintX(vp *[]uint, checkNil bool, d *Decoder) { + v, changed := f.DecSliceUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceUintV(v []uint, checkNil bool, canChange bool, d *Decoder) (_ []uint, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []uint{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]uint, xlen) + } + } else { + v = make([]uint, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = uint(dd.DecodeUint(uintBitsize)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = uint(dd.DecodeUint(uintBitsize)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []uint{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]uint, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = uint(dd.DecodeUint(uintBitsize)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceUint16R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]uint16) + v, changed := fastpathTV.DecSliceUint16V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]uint16) + fastpathTV.DecSliceUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceUint16X(vp *[]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecSliceUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceUint16V(v []uint16, checkNil bool, canChange bool, d *Decoder) (_ []uint16, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []uint16{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 2) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]uint16, xlen) + } + } else { + v = make([]uint16, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = uint16(dd.DecodeUint(16)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = uint16(dd.DecodeUint(16)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []uint16{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]uint16, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = uint16(dd.DecodeUint(16)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceUint32R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]uint32) + v, changed := fastpathTV.DecSliceUint32V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]uint32) + fastpathTV.DecSliceUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceUint32X(vp *[]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecSliceUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceUint32V(v []uint32, checkNil bool, canChange bool, d *Decoder) (_ []uint32, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []uint32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 4) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]uint32, xlen) + } + } else { + v = make([]uint32, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = uint32(dd.DecodeUint(32)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = uint32(dd.DecodeUint(32)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []uint32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]uint32, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = uint32(dd.DecodeUint(32)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceUint64R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]uint64) + v, changed := fastpathTV.DecSliceUint64V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]uint64) + fastpathTV.DecSliceUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceUint64X(vp *[]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecSliceUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceUint64V(v []uint64, checkNil bool, canChange bool, d *Decoder) (_ []uint64, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []uint64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]uint64, xlen) + } + } else { + v = make([]uint64, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = dd.DecodeUint(64) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = dd.DecodeUint(64) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []uint64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]uint64, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = dd.DecodeUint(64) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceUintptrR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]uintptr) + v, changed := fastpathTV.DecSliceUintptrV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]uintptr) + fastpathTV.DecSliceUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceUintptrX(vp *[]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecSliceUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceUintptrV(v []uintptr, checkNil bool, canChange bool, d *Decoder) (_ []uintptr, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []uintptr{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]uintptr, xlen) + } + } else { + v = make([]uintptr, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = uintptr(dd.DecodeUint(uintBitsize)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = uintptr(dd.DecodeUint(uintBitsize)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []uintptr{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]uintptr, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = uintptr(dd.DecodeUint(uintBitsize)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceIntR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]int) + v, changed := fastpathTV.DecSliceIntV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]int) + fastpathTV.DecSliceIntV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceIntX(vp *[]int, checkNil bool, d *Decoder) { + v, changed := f.DecSliceIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceIntV(v []int, checkNil bool, canChange bool, d *Decoder) (_ []int, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []int{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]int, xlen) + } + } else { + v = make([]int, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = int(dd.DecodeInt(intBitsize)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = int(dd.DecodeInt(intBitsize)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []int{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]int, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = int(dd.DecodeInt(intBitsize)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceInt8R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]int8) + v, changed := fastpathTV.DecSliceInt8V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]int8) + fastpathTV.DecSliceInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceInt8X(vp *[]int8, checkNil bool, d *Decoder) { + v, changed := f.DecSliceInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceInt8V(v []int8, checkNil bool, canChange bool, d *Decoder) (_ []int8, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []int8{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 1) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]int8, xlen) + } + } else { + v = make([]int8, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = int8(dd.DecodeInt(8)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = int8(dd.DecodeInt(8)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []int8{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]int8, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = int8(dd.DecodeInt(8)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceInt16R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]int16) + v, changed := fastpathTV.DecSliceInt16V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]int16) + fastpathTV.DecSliceInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceInt16X(vp *[]int16, checkNil bool, d *Decoder) { + v, changed := f.DecSliceInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceInt16V(v []int16, checkNil bool, canChange bool, d *Decoder) (_ []int16, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []int16{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 2) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]int16, xlen) + } + } else { + v = make([]int16, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = int16(dd.DecodeInt(16)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = int16(dd.DecodeInt(16)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []int16{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]int16, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = int16(dd.DecodeInt(16)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceInt32R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]int32) + v, changed := fastpathTV.DecSliceInt32V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]int32) + fastpathTV.DecSliceInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceInt32X(vp *[]int32, checkNil bool, d *Decoder) { + v, changed := f.DecSliceInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceInt32V(v []int32, checkNil bool, canChange bool, d *Decoder) (_ []int32, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []int32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 4) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]int32, xlen) + } + } else { + v = make([]int32, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = int32(dd.DecodeInt(32)) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = int32(dd.DecodeInt(32)) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []int32{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]int32, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = int32(dd.DecodeInt(32)) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceInt64R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]int64) + v, changed := fastpathTV.DecSliceInt64V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]int64) + fastpathTV.DecSliceInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceInt64X(vp *[]int64, checkNil bool, d *Decoder) { + v, changed := f.DecSliceInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceInt64V(v []int64, checkNil bool, canChange bool, d *Decoder) (_ []int64, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []int64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 8) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]int64, xlen) + } + } else { + v = make([]int64, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = dd.DecodeInt(64) + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, 0) + slh.ElemContainerState(j) + v[j] = dd.DecodeInt(64) + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []int64{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]int64, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, 0) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = dd.DecodeInt(64) + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecSliceBoolR(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { + vp := rv.Addr().Interface().(*[]bool) + v, changed := fastpathTV.DecSliceBoolV(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]bool) + fastpathTV.DecSliceBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) DecSliceBoolX(vp *[]bool, checkNil bool, d *Decoder) { + v, changed := f.DecSliceBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecSliceBoolV(v []bool, checkNil bool, canChange bool, d *Decoder) (_ []bool, changed bool) { + dd := d.d + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []bool{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, 1) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]bool, xlen) + } + } else { + v = make([]bool, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + v[j] = dd.DecodeBool() + } + if xtrunc { + for ; j < containerLenS; j++ { + v = append(v, false) + slh.ElemContainerState(j) + v[j] = dd.DecodeBool() + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() + if breakFound { + if canChange { + if v == nil { + v = []bool{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]bool, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, false) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { + v[j] = dd.DecodeBool() + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]interface{}) + v, changed := fastpathTV.DecMapIntfIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]interface{}) + fastpathTV.DecMapIntfIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfIntfX(vp *map[interface{}]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfIntfV(v map[interface{}]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 32) + v = make(map[interface{}]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk interface{} + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]string) + v, changed := fastpathTV.DecMapIntfStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]string) + fastpathTV.DecMapIntfStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfStringX(vp *map[interface{}]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfStringV(v map[interface{}]string, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 32) + v = make(map[interface{}]string, xlen) + changed = true + } + + var mk interface{} + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uint) + v, changed := fastpathTV.DecMapIntfUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uint) + fastpathTV.DecMapIntfUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUintX(vp *map[interface{}]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUintV(v map[interface{}]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]uint, xlen) + changed = true + } + + var mk interface{} + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uint8) + v, changed := fastpathTV.DecMapIntfUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uint8) + fastpathTV.DecMapIntfUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUint8X(vp *map[interface{}]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUint8V(v map[interface{}]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[interface{}]uint8, xlen) + changed = true + } + + var mk interface{} + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uint16) + v, changed := fastpathTV.DecMapIntfUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uint16) + fastpathTV.DecMapIntfUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUint16X(vp *map[interface{}]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUint16V(v map[interface{}]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[interface{}]uint16, xlen) + changed = true + } + + var mk interface{} + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uint32) + v, changed := fastpathTV.DecMapIntfUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uint32) + fastpathTV.DecMapIntfUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUint32X(vp *map[interface{}]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUint32V(v map[interface{}]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[interface{}]uint32, xlen) + changed = true + } + + var mk interface{} + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uint64) + v, changed := fastpathTV.DecMapIntfUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uint64) + fastpathTV.DecMapIntfUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUint64X(vp *map[interface{}]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUint64V(v map[interface{}]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]uint64, xlen) + changed = true + } + + var mk interface{} + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]uintptr) + v, changed := fastpathTV.DecMapIntfUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]uintptr) + fastpathTV.DecMapIntfUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfUintptrX(vp *map[interface{}]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfUintptrV(v map[interface{}]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]uintptr, xlen) + changed = true + } + + var mk interface{} + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]int) + v, changed := fastpathTV.DecMapIntfIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]int) + fastpathTV.DecMapIntfIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfIntX(vp *map[interface{}]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfIntV(v map[interface{}]int, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]int, xlen) + changed = true + } + + var mk interface{} + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]int8) + v, changed := fastpathTV.DecMapIntfInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]int8) + fastpathTV.DecMapIntfInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfInt8X(vp *map[interface{}]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfInt8V(v map[interface{}]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[interface{}]int8, xlen) + changed = true + } + + var mk interface{} + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]int16) + v, changed := fastpathTV.DecMapIntfInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]int16) + fastpathTV.DecMapIntfInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfInt16X(vp *map[interface{}]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfInt16V(v map[interface{}]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[interface{}]int16, xlen) + changed = true + } + + var mk interface{} + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]int32) + v, changed := fastpathTV.DecMapIntfInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]int32) + fastpathTV.DecMapIntfInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfInt32X(vp *map[interface{}]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfInt32V(v map[interface{}]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[interface{}]int32, xlen) + changed = true + } + + var mk interface{} + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]int64) + v, changed := fastpathTV.DecMapIntfInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]int64) + fastpathTV.DecMapIntfInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfInt64X(vp *map[interface{}]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfInt64V(v map[interface{}]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]int64, xlen) + changed = true + } + + var mk interface{} + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]float32) + v, changed := fastpathTV.DecMapIntfFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]float32) + fastpathTV.DecMapIntfFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfFloat32X(vp *map[interface{}]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfFloat32V(v map[interface{}]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[interface{}]float32, xlen) + changed = true + } + + var mk interface{} + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]float64) + v, changed := fastpathTV.DecMapIntfFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]float64) + fastpathTV.DecMapIntfFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfFloat64X(vp *map[interface{}]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfFloat64V(v map[interface{}]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[interface{}]float64, xlen) + changed = true + } + + var mk interface{} + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntfBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[interface{}]bool) + v, changed := fastpathTV.DecMapIntfBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[interface{}]bool) + fastpathTV.DecMapIntfBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntfBoolX(vp *map[interface{}]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntfBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntfBoolV(v map[interface{}]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[interface{}]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[interface{}]bool, xlen) + changed = true + } + + var mk interface{} + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) + } + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]interface{}) + v, changed := fastpathTV.DecMapStringIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]interface{}) + fastpathTV.DecMapStringIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringIntfX(vp *map[string]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringIntfV(v map[string]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[string]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 32) + v = make(map[string]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk string + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]string) + v, changed := fastpathTV.DecMapStringStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]string) + fastpathTV.DecMapStringStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringStringX(vp *map[string]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringStringV(v map[string]string, checkNil bool, canChange bool, + d *Decoder) (_ map[string]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 32) + v = make(map[string]string, xlen) + changed = true + } + + var mk string + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uint) + v, changed := fastpathTV.DecMapStringUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uint) + fastpathTV.DecMapStringUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUintX(vp *map[string]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUintV(v map[string]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]uint, xlen) + changed = true + } + + var mk string + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uint8) + v, changed := fastpathTV.DecMapStringUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uint8) + fastpathTV.DecMapStringUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUint8X(vp *map[string]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUint8V(v map[string]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[string]uint8, xlen) + changed = true + } + + var mk string + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uint16) + v, changed := fastpathTV.DecMapStringUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uint16) + fastpathTV.DecMapStringUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUint16X(vp *map[string]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUint16V(v map[string]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[string]uint16, xlen) + changed = true + } + + var mk string + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uint32) + v, changed := fastpathTV.DecMapStringUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uint32) + fastpathTV.DecMapStringUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUint32X(vp *map[string]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUint32V(v map[string]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[string]uint32, xlen) + changed = true + } + + var mk string + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uint64) + v, changed := fastpathTV.DecMapStringUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uint64) + fastpathTV.DecMapStringUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUint64X(vp *map[string]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUint64V(v map[string]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]uint64, xlen) + changed = true + } + + var mk string + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]uintptr) + v, changed := fastpathTV.DecMapStringUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]uintptr) + fastpathTV.DecMapStringUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringUintptrX(vp *map[string]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringUintptrV(v map[string]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[string]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]uintptr, xlen) + changed = true + } + + var mk string + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]int) + v, changed := fastpathTV.DecMapStringIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]int) + fastpathTV.DecMapStringIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringIntX(vp *map[string]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringIntV(v map[string]int, checkNil bool, canChange bool, + d *Decoder) (_ map[string]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]int, xlen) + changed = true + } + + var mk string + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]int8) + v, changed := fastpathTV.DecMapStringInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]int8) + fastpathTV.DecMapStringInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringInt8X(vp *map[string]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringInt8V(v map[string]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[string]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[string]int8, xlen) + changed = true + } + + var mk string + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]int16) + v, changed := fastpathTV.DecMapStringInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]int16) + fastpathTV.DecMapStringInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringInt16X(vp *map[string]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringInt16V(v map[string]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[string]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[string]int16, xlen) + changed = true + } + + var mk string + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]int32) + v, changed := fastpathTV.DecMapStringInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]int32) + fastpathTV.DecMapStringInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringInt32X(vp *map[string]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringInt32V(v map[string]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[string]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[string]int32, xlen) + changed = true + } + + var mk string + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]int64) + v, changed := fastpathTV.DecMapStringInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]int64) + fastpathTV.DecMapStringInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringInt64X(vp *map[string]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringInt64V(v map[string]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[string]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]int64, xlen) + changed = true + } + + var mk string + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]float32) + v, changed := fastpathTV.DecMapStringFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]float32) + fastpathTV.DecMapStringFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringFloat32X(vp *map[string]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringFloat32V(v map[string]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[string]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[string]float32, xlen) + changed = true + } + + var mk string + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]float64) + v, changed := fastpathTV.DecMapStringFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]float64) + fastpathTV.DecMapStringFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringFloat64X(vp *map[string]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringFloat64V(v map[string]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[string]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[string]float64, xlen) + changed = true + } + + var mk string + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapStringBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[string]bool) + v, changed := fastpathTV.DecMapStringBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[string]bool) + fastpathTV.DecMapStringBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapStringBoolX(vp *map[string]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapStringBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapStringBoolV(v map[string]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[string]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[string]bool, xlen) + changed = true + } + + var mk string + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeString() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]interface{}) + v, changed := fastpathTV.DecMapFloat32IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]interface{}) + fastpathTV.DecMapFloat32IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32IntfX(vp *map[float32]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32IntfV(v map[float32]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[float32]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk float32 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]string) + v, changed := fastpathTV.DecMapFloat32StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]string) + fastpathTV.DecMapFloat32StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32StringX(vp *map[float32]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32StringV(v map[float32]string, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[float32]string, xlen) + changed = true + } + + var mk float32 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uint) + v, changed := fastpathTV.DecMapFloat32UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uint) + fastpathTV.DecMapFloat32UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32UintX(vp *map[float32]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32UintV(v map[float32]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]uint, xlen) + changed = true + } + + var mk float32 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uint8) + v, changed := fastpathTV.DecMapFloat32Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uint8) + fastpathTV.DecMapFloat32Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Uint8X(vp *map[float32]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Uint8V(v map[float32]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[float32]uint8, xlen) + changed = true + } + + var mk float32 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uint16) + v, changed := fastpathTV.DecMapFloat32Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uint16) + fastpathTV.DecMapFloat32Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Uint16X(vp *map[float32]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Uint16V(v map[float32]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[float32]uint16, xlen) + changed = true + } + + var mk float32 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uint32) + v, changed := fastpathTV.DecMapFloat32Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uint32) + fastpathTV.DecMapFloat32Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Uint32X(vp *map[float32]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Uint32V(v map[float32]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[float32]uint32, xlen) + changed = true + } + + var mk float32 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uint64) + v, changed := fastpathTV.DecMapFloat32Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uint64) + fastpathTV.DecMapFloat32Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Uint64X(vp *map[float32]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Uint64V(v map[float32]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]uint64, xlen) + changed = true + } + + var mk float32 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]uintptr) + v, changed := fastpathTV.DecMapFloat32UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]uintptr) + fastpathTV.DecMapFloat32UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32UintptrX(vp *map[float32]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32UintptrV(v map[float32]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]uintptr, xlen) + changed = true + } + + var mk float32 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]int) + v, changed := fastpathTV.DecMapFloat32IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]int) + fastpathTV.DecMapFloat32IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32IntX(vp *map[float32]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32IntV(v map[float32]int, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]int, xlen) + changed = true + } + + var mk float32 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]int8) + v, changed := fastpathTV.DecMapFloat32Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]int8) + fastpathTV.DecMapFloat32Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Int8X(vp *map[float32]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Int8V(v map[float32]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[float32]int8, xlen) + changed = true + } + + var mk float32 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]int16) + v, changed := fastpathTV.DecMapFloat32Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]int16) + fastpathTV.DecMapFloat32Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Int16X(vp *map[float32]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Int16V(v map[float32]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[float32]int16, xlen) + changed = true + } + + var mk float32 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]int32) + v, changed := fastpathTV.DecMapFloat32Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]int32) + fastpathTV.DecMapFloat32Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Int32X(vp *map[float32]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Int32V(v map[float32]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[float32]int32, xlen) + changed = true + } + + var mk float32 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]int64) + v, changed := fastpathTV.DecMapFloat32Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]int64) + fastpathTV.DecMapFloat32Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Int64X(vp *map[float32]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Int64V(v map[float32]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]int64, xlen) + changed = true + } + + var mk float32 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]float32) + v, changed := fastpathTV.DecMapFloat32Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]float32) + fastpathTV.DecMapFloat32Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Float32X(vp *map[float32]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Float32V(v map[float32]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[float32]float32, xlen) + changed = true + } + + var mk float32 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]float64) + v, changed := fastpathTV.DecMapFloat32Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]float64) + fastpathTV.DecMapFloat32Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32Float64X(vp *map[float32]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32Float64V(v map[float32]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float32]float64, xlen) + changed = true + } + + var mk float32 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat32BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float32]bool) + v, changed := fastpathTV.DecMapFloat32BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float32]bool) + fastpathTV.DecMapFloat32BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat32BoolX(vp *map[float32]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat32BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat32BoolV(v map[float32]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[float32]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[float32]bool, xlen) + changed = true + } + + var mk float32 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = float32(dd.DecodeFloat(true)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]interface{}) + v, changed := fastpathTV.DecMapFloat64IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]interface{}) + fastpathTV.DecMapFloat64IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64IntfX(vp *map[float64]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64IntfV(v map[float64]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[float64]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk float64 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]string) + v, changed := fastpathTV.DecMapFloat64StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]string) + fastpathTV.DecMapFloat64StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64StringX(vp *map[float64]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64StringV(v map[float64]string, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[float64]string, xlen) + changed = true + } + + var mk float64 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uint) + v, changed := fastpathTV.DecMapFloat64UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uint) + fastpathTV.DecMapFloat64UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64UintX(vp *map[float64]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64UintV(v map[float64]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]uint, xlen) + changed = true + } + + var mk float64 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uint8) + v, changed := fastpathTV.DecMapFloat64Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uint8) + fastpathTV.DecMapFloat64Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Uint8X(vp *map[float64]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Uint8V(v map[float64]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[float64]uint8, xlen) + changed = true + } + + var mk float64 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uint16) + v, changed := fastpathTV.DecMapFloat64Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uint16) + fastpathTV.DecMapFloat64Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Uint16X(vp *map[float64]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Uint16V(v map[float64]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[float64]uint16, xlen) + changed = true + } + + var mk float64 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uint32) + v, changed := fastpathTV.DecMapFloat64Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uint32) + fastpathTV.DecMapFloat64Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Uint32X(vp *map[float64]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Uint32V(v map[float64]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float64]uint32, xlen) + changed = true + } + + var mk float64 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uint64) + v, changed := fastpathTV.DecMapFloat64Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uint64) + fastpathTV.DecMapFloat64Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Uint64X(vp *map[float64]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Uint64V(v map[float64]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]uint64, xlen) + changed = true + } + + var mk float64 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]uintptr) + v, changed := fastpathTV.DecMapFloat64UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]uintptr) + fastpathTV.DecMapFloat64UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64UintptrX(vp *map[float64]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64UintptrV(v map[float64]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]uintptr, xlen) + changed = true + } + + var mk float64 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]int) + v, changed := fastpathTV.DecMapFloat64IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]int) + fastpathTV.DecMapFloat64IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64IntX(vp *map[float64]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64IntV(v map[float64]int, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]int, xlen) + changed = true + } + + var mk float64 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]int8) + v, changed := fastpathTV.DecMapFloat64Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]int8) + fastpathTV.DecMapFloat64Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Int8X(vp *map[float64]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Int8V(v map[float64]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[float64]int8, xlen) + changed = true + } + + var mk float64 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]int16) + v, changed := fastpathTV.DecMapFloat64Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]int16) + fastpathTV.DecMapFloat64Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Int16X(vp *map[float64]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Int16V(v map[float64]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[float64]int16, xlen) + changed = true + } + + var mk float64 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]int32) + v, changed := fastpathTV.DecMapFloat64Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]int32) + fastpathTV.DecMapFloat64Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Int32X(vp *map[float64]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Int32V(v map[float64]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float64]int32, xlen) + changed = true + } + + var mk float64 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]int64) + v, changed := fastpathTV.DecMapFloat64Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]int64) + fastpathTV.DecMapFloat64Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Int64X(vp *map[float64]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Int64V(v map[float64]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]int64, xlen) + changed = true + } + + var mk float64 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]float32) + v, changed := fastpathTV.DecMapFloat64Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]float32) + fastpathTV.DecMapFloat64Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Float32X(vp *map[float64]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Float32V(v map[float64]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[float64]float32, xlen) + changed = true + } + + var mk float64 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]float64) + v, changed := fastpathTV.DecMapFloat64Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]float64) + fastpathTV.DecMapFloat64Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64Float64X(vp *map[float64]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64Float64V(v map[float64]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[float64]float64, xlen) + changed = true + } + + var mk float64 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapFloat64BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[float64]bool) + v, changed := fastpathTV.DecMapFloat64BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[float64]bool) + fastpathTV.DecMapFloat64BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapFloat64BoolX(vp *map[float64]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapFloat64BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapFloat64BoolV(v map[float64]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[float64]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[float64]bool, xlen) + changed = true + } + + var mk float64 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeFloat(false) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]interface{}) + v, changed := fastpathTV.DecMapUintIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]interface{}) + fastpathTV.DecMapUintIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintIntfX(vp *map[uint]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintIntfV(v map[uint]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uint]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uint + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]string) + v, changed := fastpathTV.DecMapUintStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]string) + fastpathTV.DecMapUintStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintStringX(vp *map[uint]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintStringV(v map[uint]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uint]string, xlen) + changed = true + } + + var mk uint + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uint) + v, changed := fastpathTV.DecMapUintUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uint) + fastpathTV.DecMapUintUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUintX(vp *map[uint]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUintV(v map[uint]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]uint, xlen) + changed = true + } + + var mk uint + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uint8) + v, changed := fastpathTV.DecMapUintUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uint8) + fastpathTV.DecMapUintUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUint8X(vp *map[uint]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUint8V(v map[uint]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint]uint8, xlen) + changed = true + } + + var mk uint + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uint16) + v, changed := fastpathTV.DecMapUintUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uint16) + fastpathTV.DecMapUintUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUint16X(vp *map[uint]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUint16V(v map[uint]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint]uint16, xlen) + changed = true + } + + var mk uint + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uint32) + v, changed := fastpathTV.DecMapUintUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uint32) + fastpathTV.DecMapUintUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUint32X(vp *map[uint]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUint32V(v map[uint]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint]uint32, xlen) + changed = true + } + + var mk uint + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uint64) + v, changed := fastpathTV.DecMapUintUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uint64) + fastpathTV.DecMapUintUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUint64X(vp *map[uint]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUint64V(v map[uint]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]uint64, xlen) + changed = true + } + + var mk uint + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]uintptr) + v, changed := fastpathTV.DecMapUintUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]uintptr) + fastpathTV.DecMapUintUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintUintptrX(vp *map[uint]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintUintptrV(v map[uint]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]uintptr, xlen) + changed = true + } + + var mk uint + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]int) + v, changed := fastpathTV.DecMapUintIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]int) + fastpathTV.DecMapUintIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintIntX(vp *map[uint]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintIntV(v map[uint]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]int, xlen) + changed = true + } + + var mk uint + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]int8) + v, changed := fastpathTV.DecMapUintInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]int8) + fastpathTV.DecMapUintInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintInt8X(vp *map[uint]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintInt8V(v map[uint]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint]int8, xlen) + changed = true + } + + var mk uint + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]int16) + v, changed := fastpathTV.DecMapUintInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]int16) + fastpathTV.DecMapUintInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintInt16X(vp *map[uint]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintInt16V(v map[uint]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint]int16, xlen) + changed = true + } + + var mk uint + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]int32) + v, changed := fastpathTV.DecMapUintInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]int32) + fastpathTV.DecMapUintInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintInt32X(vp *map[uint]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintInt32V(v map[uint]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint]int32, xlen) + changed = true + } + + var mk uint + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]int64) + v, changed := fastpathTV.DecMapUintInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]int64) + fastpathTV.DecMapUintInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintInt64X(vp *map[uint]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintInt64V(v map[uint]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]int64, xlen) + changed = true + } + + var mk uint + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]float32) + v, changed := fastpathTV.DecMapUintFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]float32) + fastpathTV.DecMapUintFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintFloat32X(vp *map[uint]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintFloat32V(v map[uint]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint]float32, xlen) + changed = true + } + + var mk uint + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]float64) + v, changed := fastpathTV.DecMapUintFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]float64) + fastpathTV.DecMapUintFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintFloat64X(vp *map[uint]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintFloat64V(v map[uint]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint]float64, xlen) + changed = true + } + + var mk uint + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint]bool) + v, changed := fastpathTV.DecMapUintBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint]bool) + fastpathTV.DecMapUintBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintBoolX(vp *map[uint]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintBoolV(v map[uint]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uint]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint]bool, xlen) + changed = true + } + + var mk uint + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]interface{}) + v, changed := fastpathTV.DecMapUint8IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]interface{}) + fastpathTV.DecMapUint8IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8IntfX(vp *map[uint8]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8IntfV(v map[uint8]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[uint8]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uint8 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]string) + v, changed := fastpathTV.DecMapUint8StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]string) + fastpathTV.DecMapUint8StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8StringX(vp *map[uint8]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8StringV(v map[uint8]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[uint8]string, xlen) + changed = true + } + + var mk uint8 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uint) + v, changed := fastpathTV.DecMapUint8UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uint) + fastpathTV.DecMapUint8UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8UintX(vp *map[uint8]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8UintV(v map[uint8]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]uint, xlen) + changed = true + } + + var mk uint8 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uint8) + v, changed := fastpathTV.DecMapUint8Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uint8) + fastpathTV.DecMapUint8Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Uint8X(vp *map[uint8]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Uint8V(v map[uint8]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[uint8]uint8, xlen) + changed = true + } + + var mk uint8 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uint16) + v, changed := fastpathTV.DecMapUint8Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uint16) + fastpathTV.DecMapUint8Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Uint16X(vp *map[uint8]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Uint16V(v map[uint8]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[uint8]uint16, xlen) + changed = true + } + + var mk uint8 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uint32) + v, changed := fastpathTV.DecMapUint8Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uint32) + fastpathTV.DecMapUint8Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Uint32X(vp *map[uint8]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Uint32V(v map[uint8]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint8]uint32, xlen) + changed = true + } + + var mk uint8 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uint64) + v, changed := fastpathTV.DecMapUint8Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uint64) + fastpathTV.DecMapUint8Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Uint64X(vp *map[uint8]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Uint64V(v map[uint8]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]uint64, xlen) + changed = true + } + + var mk uint8 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]uintptr) + v, changed := fastpathTV.DecMapUint8UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]uintptr) + fastpathTV.DecMapUint8UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8UintptrX(vp *map[uint8]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8UintptrV(v map[uint8]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]uintptr, xlen) + changed = true + } + + var mk uint8 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]int) + v, changed := fastpathTV.DecMapUint8IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]int) + fastpathTV.DecMapUint8IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8IntX(vp *map[uint8]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8IntV(v map[uint8]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]int, xlen) + changed = true + } + + var mk uint8 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]int8) + v, changed := fastpathTV.DecMapUint8Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]int8) + fastpathTV.DecMapUint8Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Int8X(vp *map[uint8]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Int8V(v map[uint8]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[uint8]int8, xlen) + changed = true + } + + var mk uint8 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]int16) + v, changed := fastpathTV.DecMapUint8Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]int16) + fastpathTV.DecMapUint8Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Int16X(vp *map[uint8]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Int16V(v map[uint8]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[uint8]int16, xlen) + changed = true + } + + var mk uint8 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]int32) + v, changed := fastpathTV.DecMapUint8Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]int32) + fastpathTV.DecMapUint8Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Int32X(vp *map[uint8]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Int32V(v map[uint8]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint8]int32, xlen) + changed = true + } + + var mk uint8 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]int64) + v, changed := fastpathTV.DecMapUint8Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]int64) + fastpathTV.DecMapUint8Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Int64X(vp *map[uint8]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Int64V(v map[uint8]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]int64, xlen) + changed = true + } + + var mk uint8 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]float32) + v, changed := fastpathTV.DecMapUint8Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]float32) + fastpathTV.DecMapUint8Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Float32X(vp *map[uint8]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Float32V(v map[uint8]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint8]float32, xlen) + changed = true + } + + var mk uint8 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]float64) + v, changed := fastpathTV.DecMapUint8Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]float64) + fastpathTV.DecMapUint8Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8Float64X(vp *map[uint8]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8Float64V(v map[uint8]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint8]float64, xlen) + changed = true + } + + var mk uint8 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint8BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint8]bool) + v, changed := fastpathTV.DecMapUint8BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint8]bool) + fastpathTV.DecMapUint8BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint8BoolX(vp *map[uint8]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint8BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint8BoolV(v map[uint8]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uint8]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[uint8]bool, xlen) + changed = true + } + + var mk uint8 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint8(dd.DecodeUint(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]interface{}) + v, changed := fastpathTV.DecMapUint16IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]interface{}) + fastpathTV.DecMapUint16IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16IntfX(vp *map[uint16]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16IntfV(v map[uint16]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[uint16]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uint16 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]string) + v, changed := fastpathTV.DecMapUint16StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]string) + fastpathTV.DecMapUint16StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16StringX(vp *map[uint16]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16StringV(v map[uint16]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[uint16]string, xlen) + changed = true + } + + var mk uint16 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uint) + v, changed := fastpathTV.DecMapUint16UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uint) + fastpathTV.DecMapUint16UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16UintX(vp *map[uint16]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16UintV(v map[uint16]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]uint, xlen) + changed = true + } + + var mk uint16 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uint8) + v, changed := fastpathTV.DecMapUint16Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uint8) + fastpathTV.DecMapUint16Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Uint8X(vp *map[uint16]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Uint8V(v map[uint16]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[uint16]uint8, xlen) + changed = true + } + + var mk uint16 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uint16) + v, changed := fastpathTV.DecMapUint16Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uint16) + fastpathTV.DecMapUint16Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Uint16X(vp *map[uint16]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Uint16V(v map[uint16]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 4) + v = make(map[uint16]uint16, xlen) + changed = true + } + + var mk uint16 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uint32) + v, changed := fastpathTV.DecMapUint16Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uint32) + fastpathTV.DecMapUint16Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Uint32X(vp *map[uint16]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Uint32V(v map[uint16]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[uint16]uint32, xlen) + changed = true + } + + var mk uint16 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uint64) + v, changed := fastpathTV.DecMapUint16Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uint64) + fastpathTV.DecMapUint16Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Uint64X(vp *map[uint16]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Uint64V(v map[uint16]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]uint64, xlen) + changed = true + } + + var mk uint16 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]uintptr) + v, changed := fastpathTV.DecMapUint16UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]uintptr) + fastpathTV.DecMapUint16UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16UintptrX(vp *map[uint16]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16UintptrV(v map[uint16]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]uintptr, xlen) + changed = true + } + + var mk uint16 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]int) + v, changed := fastpathTV.DecMapUint16IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]int) + fastpathTV.DecMapUint16IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16IntX(vp *map[uint16]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16IntV(v map[uint16]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]int, xlen) + changed = true + } + + var mk uint16 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]int8) + v, changed := fastpathTV.DecMapUint16Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]int8) + fastpathTV.DecMapUint16Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Int8X(vp *map[uint16]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Int8V(v map[uint16]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[uint16]int8, xlen) + changed = true + } + + var mk uint16 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]int16) + v, changed := fastpathTV.DecMapUint16Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]int16) + fastpathTV.DecMapUint16Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Int16X(vp *map[uint16]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Int16V(v map[uint16]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 4) + v = make(map[uint16]int16, xlen) + changed = true + } + + var mk uint16 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]int32) + v, changed := fastpathTV.DecMapUint16Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]int32) + fastpathTV.DecMapUint16Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Int32X(vp *map[uint16]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Int32V(v map[uint16]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[uint16]int32, xlen) + changed = true + } + + var mk uint16 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]int64) + v, changed := fastpathTV.DecMapUint16Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]int64) + fastpathTV.DecMapUint16Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Int64X(vp *map[uint16]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Int64V(v map[uint16]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]int64, xlen) + changed = true + } + + var mk uint16 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]float32) + v, changed := fastpathTV.DecMapUint16Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]float32) + fastpathTV.DecMapUint16Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Float32X(vp *map[uint16]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Float32V(v map[uint16]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[uint16]float32, xlen) + changed = true + } + + var mk uint16 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]float64) + v, changed := fastpathTV.DecMapUint16Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]float64) + fastpathTV.DecMapUint16Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16Float64X(vp *map[uint16]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16Float64V(v map[uint16]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint16]float64, xlen) + changed = true + } + + var mk uint16 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint16BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint16]bool) + v, changed := fastpathTV.DecMapUint16BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint16]bool) + fastpathTV.DecMapUint16BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint16BoolX(vp *map[uint16]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint16BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint16BoolV(v map[uint16]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uint16]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[uint16]bool, xlen) + changed = true + } + + var mk uint16 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint16(dd.DecodeUint(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]interface{}) + v, changed := fastpathTV.DecMapUint32IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]interface{}) + fastpathTV.DecMapUint32IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32IntfX(vp *map[uint32]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32IntfV(v map[uint32]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[uint32]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uint32 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]string) + v, changed := fastpathTV.DecMapUint32StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]string) + fastpathTV.DecMapUint32StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32StringX(vp *map[uint32]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32StringV(v map[uint32]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[uint32]string, xlen) + changed = true + } + + var mk uint32 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uint) + v, changed := fastpathTV.DecMapUint32UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uint) + fastpathTV.DecMapUint32UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32UintX(vp *map[uint32]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32UintV(v map[uint32]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]uint, xlen) + changed = true + } + + var mk uint32 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uint8) + v, changed := fastpathTV.DecMapUint32Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uint8) + fastpathTV.DecMapUint32Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Uint8X(vp *map[uint32]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Uint8V(v map[uint32]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint32]uint8, xlen) + changed = true + } + + var mk uint32 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uint16) + v, changed := fastpathTV.DecMapUint32Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uint16) + fastpathTV.DecMapUint32Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Uint16X(vp *map[uint32]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Uint16V(v map[uint32]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[uint32]uint16, xlen) + changed = true + } + + var mk uint32 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uint32) + v, changed := fastpathTV.DecMapUint32Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uint32) + fastpathTV.DecMapUint32Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Uint32X(vp *map[uint32]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Uint32V(v map[uint32]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[uint32]uint32, xlen) + changed = true + } + + var mk uint32 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uint64) + v, changed := fastpathTV.DecMapUint32Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uint64) + fastpathTV.DecMapUint32Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Uint64X(vp *map[uint32]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Uint64V(v map[uint32]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]uint64, xlen) + changed = true + } + + var mk uint32 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]uintptr) + v, changed := fastpathTV.DecMapUint32UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]uintptr) + fastpathTV.DecMapUint32UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32UintptrX(vp *map[uint32]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32UintptrV(v map[uint32]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]uintptr, xlen) + changed = true + } + + var mk uint32 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]int) + v, changed := fastpathTV.DecMapUint32IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]int) + fastpathTV.DecMapUint32IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32IntX(vp *map[uint32]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32IntV(v map[uint32]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]int, xlen) + changed = true + } + + var mk uint32 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]int8) + v, changed := fastpathTV.DecMapUint32Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]int8) + fastpathTV.DecMapUint32Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Int8X(vp *map[uint32]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Int8V(v map[uint32]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint32]int8, xlen) + changed = true + } + + var mk uint32 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]int16) + v, changed := fastpathTV.DecMapUint32Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]int16) + fastpathTV.DecMapUint32Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Int16X(vp *map[uint32]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Int16V(v map[uint32]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[uint32]int16, xlen) + changed = true + } + + var mk uint32 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]int32) + v, changed := fastpathTV.DecMapUint32Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]int32) + fastpathTV.DecMapUint32Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Int32X(vp *map[uint32]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Int32V(v map[uint32]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[uint32]int32, xlen) + changed = true + } + + var mk uint32 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]int64) + v, changed := fastpathTV.DecMapUint32Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]int64) + fastpathTV.DecMapUint32Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Int64X(vp *map[uint32]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Int64V(v map[uint32]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]int64, xlen) + changed = true + } + + var mk uint32 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]float32) + v, changed := fastpathTV.DecMapUint32Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]float32) + fastpathTV.DecMapUint32Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Float32X(vp *map[uint32]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Float32V(v map[uint32]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[uint32]float32, xlen) + changed = true + } + + var mk uint32 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]float64) + v, changed := fastpathTV.DecMapUint32Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]float64) + fastpathTV.DecMapUint32Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32Float64X(vp *map[uint32]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32Float64V(v map[uint32]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint32]float64, xlen) + changed = true + } + + var mk uint32 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint32BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint32]bool) + v, changed := fastpathTV.DecMapUint32BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint32]bool) + fastpathTV.DecMapUint32BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint32BoolX(vp *map[uint32]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint32BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint32BoolV(v map[uint32]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uint32]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[uint32]bool, xlen) + changed = true + } + + var mk uint32 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uint32(dd.DecodeUint(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]interface{}) + v, changed := fastpathTV.DecMapUint64IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]interface{}) + fastpathTV.DecMapUint64IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64IntfX(vp *map[uint64]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64IntfV(v map[uint64]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uint64]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uint64 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]string) + v, changed := fastpathTV.DecMapUint64StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]string) + fastpathTV.DecMapUint64StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64StringX(vp *map[uint64]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64StringV(v map[uint64]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uint64]string, xlen) + changed = true + } + + var mk uint64 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uint) + v, changed := fastpathTV.DecMapUint64UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uint) + fastpathTV.DecMapUint64UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64UintX(vp *map[uint64]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64UintV(v map[uint64]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]uint, xlen) + changed = true + } + + var mk uint64 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uint8) + v, changed := fastpathTV.DecMapUint64Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uint8) + fastpathTV.DecMapUint64Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Uint8X(vp *map[uint64]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Uint8V(v map[uint64]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint64]uint8, xlen) + changed = true + } + + var mk uint64 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uint16) + v, changed := fastpathTV.DecMapUint64Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uint16) + fastpathTV.DecMapUint64Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Uint16X(vp *map[uint64]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Uint16V(v map[uint64]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint64]uint16, xlen) + changed = true + } + + var mk uint64 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uint32) + v, changed := fastpathTV.DecMapUint64Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uint32) + fastpathTV.DecMapUint64Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Uint32X(vp *map[uint64]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Uint32V(v map[uint64]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint64]uint32, xlen) + changed = true + } + + var mk uint64 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uint64) + v, changed := fastpathTV.DecMapUint64Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uint64) + fastpathTV.DecMapUint64Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Uint64X(vp *map[uint64]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Uint64V(v map[uint64]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]uint64, xlen) + changed = true + } + + var mk uint64 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]uintptr) + v, changed := fastpathTV.DecMapUint64UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]uintptr) + fastpathTV.DecMapUint64UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64UintptrX(vp *map[uint64]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64UintptrV(v map[uint64]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]uintptr, xlen) + changed = true + } + + var mk uint64 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]int) + v, changed := fastpathTV.DecMapUint64IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]int) + fastpathTV.DecMapUint64IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64IntX(vp *map[uint64]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64IntV(v map[uint64]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]int, xlen) + changed = true + } + + var mk uint64 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]int8) + v, changed := fastpathTV.DecMapUint64Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]int8) + fastpathTV.DecMapUint64Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Int8X(vp *map[uint64]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Int8V(v map[uint64]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint64]int8, xlen) + changed = true + } + + var mk uint64 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]int16) + v, changed := fastpathTV.DecMapUint64Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]int16) + fastpathTV.DecMapUint64Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Int16X(vp *map[uint64]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Int16V(v map[uint64]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uint64]int16, xlen) + changed = true + } + + var mk uint64 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]int32) + v, changed := fastpathTV.DecMapUint64Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]int32) + fastpathTV.DecMapUint64Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Int32X(vp *map[uint64]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Int32V(v map[uint64]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint64]int32, xlen) + changed = true + } + + var mk uint64 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]int64) + v, changed := fastpathTV.DecMapUint64Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]int64) + fastpathTV.DecMapUint64Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Int64X(vp *map[uint64]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Int64V(v map[uint64]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]int64, xlen) + changed = true + } + + var mk uint64 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]float32) + v, changed := fastpathTV.DecMapUint64Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]float32) + fastpathTV.DecMapUint64Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Float32X(vp *map[uint64]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Float32V(v map[uint64]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uint64]float32, xlen) + changed = true + } + + var mk uint64 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]float64) + v, changed := fastpathTV.DecMapUint64Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]float64) + fastpathTV.DecMapUint64Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64Float64X(vp *map[uint64]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64Float64V(v map[uint64]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uint64]float64, xlen) + changed = true + } + + var mk uint64 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUint64BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uint64]bool) + v, changed := fastpathTV.DecMapUint64BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uint64]bool) + fastpathTV.DecMapUint64BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUint64BoolX(vp *map[uint64]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUint64BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUint64BoolV(v map[uint64]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uint64]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uint64]bool, xlen) + changed = true + } + + var mk uint64 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeUint(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]interface{}) + v, changed := fastpathTV.DecMapUintptrIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]interface{}) + fastpathTV.DecMapUintptrIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrIntfX(vp *map[uintptr]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrIntfV(v map[uintptr]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uintptr]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk uintptr + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]string) + v, changed := fastpathTV.DecMapUintptrStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]string) + fastpathTV.DecMapUintptrStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrStringX(vp *map[uintptr]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrStringV(v map[uintptr]string, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[uintptr]string, xlen) + changed = true + } + + var mk uintptr + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uint) + v, changed := fastpathTV.DecMapUintptrUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uint) + fastpathTV.DecMapUintptrUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUintX(vp *map[uintptr]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUintV(v map[uintptr]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]uint, xlen) + changed = true + } + + var mk uintptr + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uint8) + v, changed := fastpathTV.DecMapUintptrUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uint8) + fastpathTV.DecMapUintptrUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUint8X(vp *map[uintptr]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUint8V(v map[uintptr]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uintptr]uint8, xlen) + changed = true + } + + var mk uintptr + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uint16) + v, changed := fastpathTV.DecMapUintptrUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uint16) + fastpathTV.DecMapUintptrUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUint16X(vp *map[uintptr]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUint16V(v map[uintptr]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uintptr]uint16, xlen) + changed = true + } + + var mk uintptr + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uint32) + v, changed := fastpathTV.DecMapUintptrUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uint32) + fastpathTV.DecMapUintptrUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUint32X(vp *map[uintptr]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUint32V(v map[uintptr]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uintptr]uint32, xlen) + changed = true + } + + var mk uintptr + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uint64) + v, changed := fastpathTV.DecMapUintptrUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uint64) + fastpathTV.DecMapUintptrUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUint64X(vp *map[uintptr]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUint64V(v map[uintptr]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]uint64, xlen) + changed = true + } + + var mk uintptr + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]uintptr) + v, changed := fastpathTV.DecMapUintptrUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]uintptr) + fastpathTV.DecMapUintptrUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrUintptrX(vp *map[uintptr]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrUintptrV(v map[uintptr]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]uintptr, xlen) + changed = true + } + + var mk uintptr + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]int) + v, changed := fastpathTV.DecMapUintptrIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]int) + fastpathTV.DecMapUintptrIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrIntX(vp *map[uintptr]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrIntV(v map[uintptr]int, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]int, xlen) + changed = true + } + + var mk uintptr + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]int8) + v, changed := fastpathTV.DecMapUintptrInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]int8) + fastpathTV.DecMapUintptrInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrInt8X(vp *map[uintptr]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrInt8V(v map[uintptr]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uintptr]int8, xlen) + changed = true + } + + var mk uintptr + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]int16) + v, changed := fastpathTV.DecMapUintptrInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]int16) + fastpathTV.DecMapUintptrInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrInt16X(vp *map[uintptr]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrInt16V(v map[uintptr]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[uintptr]int16, xlen) + changed = true + } + + var mk uintptr + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]int32) + v, changed := fastpathTV.DecMapUintptrInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]int32) + fastpathTV.DecMapUintptrInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrInt32X(vp *map[uintptr]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrInt32V(v map[uintptr]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uintptr]int32, xlen) + changed = true + } + + var mk uintptr + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]int64) + v, changed := fastpathTV.DecMapUintptrInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]int64) + fastpathTV.DecMapUintptrInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrInt64X(vp *map[uintptr]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrInt64V(v map[uintptr]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]int64, xlen) + changed = true + } + + var mk uintptr + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]float32) + v, changed := fastpathTV.DecMapUintptrFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]float32) + fastpathTV.DecMapUintptrFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrFloat32X(vp *map[uintptr]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrFloat32V(v map[uintptr]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[uintptr]float32, xlen) + changed = true + } + + var mk uintptr + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]float64) + v, changed := fastpathTV.DecMapUintptrFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]float64) + fastpathTV.DecMapUintptrFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrFloat64X(vp *map[uintptr]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrFloat64V(v map[uintptr]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[uintptr]float64, xlen) + changed = true + } + + var mk uintptr + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapUintptrBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[uintptr]bool) + v, changed := fastpathTV.DecMapUintptrBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[uintptr]bool) + fastpathTV.DecMapUintptrBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapUintptrBoolX(vp *map[uintptr]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapUintptrBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapUintptrBoolV(v map[uintptr]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[uintptr]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[uintptr]bool, xlen) + changed = true + } + + var mk uintptr + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = uintptr(dd.DecodeUint(uintBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]interface{}) + v, changed := fastpathTV.DecMapIntIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]interface{}) + fastpathTV.DecMapIntIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntIntfX(vp *map[int]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntIntfV(v map[int]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[int]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[int]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk int + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]string) + v, changed := fastpathTV.DecMapIntStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]string) + fastpathTV.DecMapIntStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntStringX(vp *map[int]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntStringV(v map[int]string, checkNil bool, canChange bool, + d *Decoder) (_ map[int]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[int]string, xlen) + changed = true + } + + var mk int + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uint) + v, changed := fastpathTV.DecMapIntUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uint) + fastpathTV.DecMapIntUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUintX(vp *map[int]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUintV(v map[int]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]uint, xlen) + changed = true + } + + var mk int + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uint8) + v, changed := fastpathTV.DecMapIntUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uint8) + fastpathTV.DecMapIntUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUint8X(vp *map[int]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUint8V(v map[int]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int]uint8, xlen) + changed = true + } + + var mk int + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uint16) + v, changed := fastpathTV.DecMapIntUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uint16) + fastpathTV.DecMapIntUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUint16X(vp *map[int]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUint16V(v map[int]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int]uint16, xlen) + changed = true + } + + var mk int + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uint32) + v, changed := fastpathTV.DecMapIntUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uint32) + fastpathTV.DecMapIntUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUint32X(vp *map[int]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUint32V(v map[int]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int]uint32, xlen) + changed = true + } + + var mk int + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uint64) + v, changed := fastpathTV.DecMapIntUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uint64) + fastpathTV.DecMapIntUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUint64X(vp *map[int]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUint64V(v map[int]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]uint64, xlen) + changed = true + } + + var mk int + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]uintptr) + v, changed := fastpathTV.DecMapIntUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]uintptr) + fastpathTV.DecMapIntUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntUintptrX(vp *map[int]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntUintptrV(v map[int]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[int]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]uintptr, xlen) + changed = true + } + + var mk int + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]int) + v, changed := fastpathTV.DecMapIntIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]int) + fastpathTV.DecMapIntIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntIntX(vp *map[int]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntIntV(v map[int]int, checkNil bool, canChange bool, + d *Decoder) (_ map[int]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]int, xlen) + changed = true + } + + var mk int + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]int8) + v, changed := fastpathTV.DecMapIntInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]int8) + fastpathTV.DecMapIntInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntInt8X(vp *map[int]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntInt8V(v map[int]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[int]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int]int8, xlen) + changed = true + } + + var mk int + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]int16) + v, changed := fastpathTV.DecMapIntInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]int16) + fastpathTV.DecMapIntInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntInt16X(vp *map[int]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntInt16V(v map[int]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[int]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int]int16, xlen) + changed = true + } + + var mk int + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]int32) + v, changed := fastpathTV.DecMapIntInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]int32) + fastpathTV.DecMapIntInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntInt32X(vp *map[int]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntInt32V(v map[int]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[int]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int]int32, xlen) + changed = true + } + + var mk int + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]int64) + v, changed := fastpathTV.DecMapIntInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]int64) + fastpathTV.DecMapIntInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntInt64X(vp *map[int]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntInt64V(v map[int]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[int]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]int64, xlen) + changed = true + } + + var mk int + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]float32) + v, changed := fastpathTV.DecMapIntFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]float32) + fastpathTV.DecMapIntFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntFloat32X(vp *map[int]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntFloat32V(v map[int]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[int]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int]float32, xlen) + changed = true + } + + var mk int + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]float64) + v, changed := fastpathTV.DecMapIntFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]float64) + fastpathTV.DecMapIntFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntFloat64X(vp *map[int]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntFloat64V(v map[int]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[int]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int]float64, xlen) + changed = true + } + + var mk int + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapIntBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int]bool) + v, changed := fastpathTV.DecMapIntBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int]bool) + fastpathTV.DecMapIntBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapIntBoolX(vp *map[int]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapIntBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapIntBoolV(v map[int]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[int]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int]bool, xlen) + changed = true + } + + var mk int + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int(dd.DecodeInt(intBitsize)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]interface{}) + v, changed := fastpathTV.DecMapInt8IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]interface{}) + fastpathTV.DecMapInt8IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8IntfX(vp *map[int8]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8IntfV(v map[int8]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[int8]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk int8 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]string) + v, changed := fastpathTV.DecMapInt8StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]string) + fastpathTV.DecMapInt8StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8StringX(vp *map[int8]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8StringV(v map[int8]string, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[int8]string, xlen) + changed = true + } + + var mk int8 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uint) + v, changed := fastpathTV.DecMapInt8UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uint) + fastpathTV.DecMapInt8UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8UintX(vp *map[int8]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8UintV(v map[int8]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]uint, xlen) + changed = true + } + + var mk int8 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uint8) + v, changed := fastpathTV.DecMapInt8Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uint8) + fastpathTV.DecMapInt8Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Uint8X(vp *map[int8]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Uint8V(v map[int8]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[int8]uint8, xlen) + changed = true + } + + var mk int8 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uint16) + v, changed := fastpathTV.DecMapInt8Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uint16) + fastpathTV.DecMapInt8Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Uint16X(vp *map[int8]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Uint16V(v map[int8]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[int8]uint16, xlen) + changed = true + } + + var mk int8 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uint32) + v, changed := fastpathTV.DecMapInt8Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uint32) + fastpathTV.DecMapInt8Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Uint32X(vp *map[int8]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Uint32V(v map[int8]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int8]uint32, xlen) + changed = true + } + + var mk int8 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uint64) + v, changed := fastpathTV.DecMapInt8Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uint64) + fastpathTV.DecMapInt8Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Uint64X(vp *map[int8]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Uint64V(v map[int8]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]uint64, xlen) + changed = true + } + + var mk int8 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]uintptr) + v, changed := fastpathTV.DecMapInt8UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]uintptr) + fastpathTV.DecMapInt8UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8UintptrX(vp *map[int8]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8UintptrV(v map[int8]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]uintptr, xlen) + changed = true + } + + var mk int8 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]int) + v, changed := fastpathTV.DecMapInt8IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]int) + fastpathTV.DecMapInt8IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8IntX(vp *map[int8]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8IntV(v map[int8]int, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]int, xlen) + changed = true + } + + var mk int8 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]int8) + v, changed := fastpathTV.DecMapInt8Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]int8) + fastpathTV.DecMapInt8Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Int8X(vp *map[int8]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Int8V(v map[int8]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[int8]int8, xlen) + changed = true + } + + var mk int8 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]int16) + v, changed := fastpathTV.DecMapInt8Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]int16) + fastpathTV.DecMapInt8Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Int16X(vp *map[int8]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Int16V(v map[int8]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[int8]int16, xlen) + changed = true + } + + var mk int8 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]int32) + v, changed := fastpathTV.DecMapInt8Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]int32) + fastpathTV.DecMapInt8Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Int32X(vp *map[int8]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Int32V(v map[int8]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int8]int32, xlen) + changed = true + } + + var mk int8 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]int64) + v, changed := fastpathTV.DecMapInt8Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]int64) + fastpathTV.DecMapInt8Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Int64X(vp *map[int8]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Int64V(v map[int8]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]int64, xlen) + changed = true + } + + var mk int8 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]float32) + v, changed := fastpathTV.DecMapInt8Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]float32) + fastpathTV.DecMapInt8Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Float32X(vp *map[int8]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Float32V(v map[int8]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int8]float32, xlen) + changed = true + } + + var mk int8 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]float64) + v, changed := fastpathTV.DecMapInt8Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]float64) + fastpathTV.DecMapInt8Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8Float64X(vp *map[int8]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8Float64V(v map[int8]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int8]float64, xlen) + changed = true + } + + var mk int8 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt8BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int8]bool) + v, changed := fastpathTV.DecMapInt8BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int8]bool) + fastpathTV.DecMapInt8BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt8BoolX(vp *map[int8]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt8BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt8BoolV(v map[int8]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[int8]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[int8]bool, xlen) + changed = true + } + + var mk int8 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int8(dd.DecodeInt(8)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]interface{}) + v, changed := fastpathTV.DecMapInt16IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]interface{}) + fastpathTV.DecMapInt16IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16IntfX(vp *map[int16]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16IntfV(v map[int16]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[int16]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk int16 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]string) + v, changed := fastpathTV.DecMapInt16StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]string) + fastpathTV.DecMapInt16StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16StringX(vp *map[int16]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16StringV(v map[int16]string, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 18) + v = make(map[int16]string, xlen) + changed = true + } + + var mk int16 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uint) + v, changed := fastpathTV.DecMapInt16UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uint) + fastpathTV.DecMapInt16UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16UintX(vp *map[int16]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16UintV(v map[int16]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]uint, xlen) + changed = true + } + + var mk int16 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uint8) + v, changed := fastpathTV.DecMapInt16Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uint8) + fastpathTV.DecMapInt16Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Uint8X(vp *map[int16]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Uint8V(v map[int16]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[int16]uint8, xlen) + changed = true + } + + var mk int16 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uint16) + v, changed := fastpathTV.DecMapInt16Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uint16) + fastpathTV.DecMapInt16Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Uint16X(vp *map[int16]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Uint16V(v map[int16]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 4) + v = make(map[int16]uint16, xlen) + changed = true + } + + var mk int16 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uint32) + v, changed := fastpathTV.DecMapInt16Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uint32) + fastpathTV.DecMapInt16Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Uint32X(vp *map[int16]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Uint32V(v map[int16]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[int16]uint32, xlen) + changed = true + } + + var mk int16 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uint64) + v, changed := fastpathTV.DecMapInt16Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uint64) + fastpathTV.DecMapInt16Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Uint64X(vp *map[int16]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Uint64V(v map[int16]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]uint64, xlen) + changed = true + } + + var mk int16 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]uintptr) + v, changed := fastpathTV.DecMapInt16UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]uintptr) + fastpathTV.DecMapInt16UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16UintptrX(vp *map[int16]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16UintptrV(v map[int16]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]uintptr, xlen) + changed = true + } + + var mk int16 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]int) + v, changed := fastpathTV.DecMapInt16IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]int) + fastpathTV.DecMapInt16IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16IntX(vp *map[int16]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16IntV(v map[int16]int, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]int, xlen) + changed = true + } + + var mk int16 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]int8) + v, changed := fastpathTV.DecMapInt16Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]int8) + fastpathTV.DecMapInt16Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Int8X(vp *map[int16]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Int8V(v map[int16]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[int16]int8, xlen) + changed = true + } + + var mk int16 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]int16) + v, changed := fastpathTV.DecMapInt16Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]int16) + fastpathTV.DecMapInt16Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Int16X(vp *map[int16]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Int16V(v map[int16]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 4) + v = make(map[int16]int16, xlen) + changed = true + } + + var mk int16 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]int32) + v, changed := fastpathTV.DecMapInt16Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]int32) + fastpathTV.DecMapInt16Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Int32X(vp *map[int16]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Int32V(v map[int16]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[int16]int32, xlen) + changed = true + } + + var mk int16 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]int64) + v, changed := fastpathTV.DecMapInt16Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]int64) + fastpathTV.DecMapInt16Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Int64X(vp *map[int16]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Int64V(v map[int16]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]int64, xlen) + changed = true + } + + var mk int16 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]float32) + v, changed := fastpathTV.DecMapInt16Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]float32) + fastpathTV.DecMapInt16Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Float32X(vp *map[int16]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Float32V(v map[int16]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[int16]float32, xlen) + changed = true + } + + var mk int16 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]float64) + v, changed := fastpathTV.DecMapInt16Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]float64) + fastpathTV.DecMapInt16Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16Float64X(vp *map[int16]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16Float64V(v map[int16]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int16]float64, xlen) + changed = true + } + + var mk int16 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt16BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int16]bool) + v, changed := fastpathTV.DecMapInt16BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int16]bool) + fastpathTV.DecMapInt16BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt16BoolX(vp *map[int16]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt16BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt16BoolV(v map[int16]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[int16]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[int16]bool, xlen) + changed = true + } + + var mk int16 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int16(dd.DecodeInt(16)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]interface{}) + v, changed := fastpathTV.DecMapInt32IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]interface{}) + fastpathTV.DecMapInt32IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32IntfX(vp *map[int32]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32IntfV(v map[int32]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[int32]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk int32 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]string) + v, changed := fastpathTV.DecMapInt32StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]string) + fastpathTV.DecMapInt32StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32StringX(vp *map[int32]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32StringV(v map[int32]string, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 20) + v = make(map[int32]string, xlen) + changed = true + } + + var mk int32 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uint) + v, changed := fastpathTV.DecMapInt32UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uint) + fastpathTV.DecMapInt32UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32UintX(vp *map[int32]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32UintV(v map[int32]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]uint, xlen) + changed = true + } + + var mk int32 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uint8) + v, changed := fastpathTV.DecMapInt32Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uint8) + fastpathTV.DecMapInt32Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Uint8X(vp *map[int32]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Uint8V(v map[int32]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int32]uint8, xlen) + changed = true + } + + var mk int32 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uint16) + v, changed := fastpathTV.DecMapInt32Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uint16) + fastpathTV.DecMapInt32Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Uint16X(vp *map[int32]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Uint16V(v map[int32]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[int32]uint16, xlen) + changed = true + } + + var mk int32 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uint32) + v, changed := fastpathTV.DecMapInt32Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uint32) + fastpathTV.DecMapInt32Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Uint32X(vp *map[int32]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Uint32V(v map[int32]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[int32]uint32, xlen) + changed = true + } + + var mk int32 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uint64) + v, changed := fastpathTV.DecMapInt32Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uint64) + fastpathTV.DecMapInt32Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Uint64X(vp *map[int32]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Uint64V(v map[int32]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]uint64, xlen) + changed = true + } + + var mk int32 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]uintptr) + v, changed := fastpathTV.DecMapInt32UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]uintptr) + fastpathTV.DecMapInt32UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32UintptrX(vp *map[int32]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32UintptrV(v map[int32]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]uintptr, xlen) + changed = true + } + + var mk int32 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]int) + v, changed := fastpathTV.DecMapInt32IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]int) + fastpathTV.DecMapInt32IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32IntX(vp *map[int32]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32IntV(v map[int32]int, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]int, xlen) + changed = true + } + + var mk int32 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]int8) + v, changed := fastpathTV.DecMapInt32Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]int8) + fastpathTV.DecMapInt32Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Int8X(vp *map[int32]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Int8V(v map[int32]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int32]int8, xlen) + changed = true + } + + var mk int32 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]int16) + v, changed := fastpathTV.DecMapInt32Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]int16) + fastpathTV.DecMapInt32Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Int16X(vp *map[int32]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Int16V(v map[int32]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 6) + v = make(map[int32]int16, xlen) + changed = true + } + + var mk int32 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]int32) + v, changed := fastpathTV.DecMapInt32Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]int32) + fastpathTV.DecMapInt32Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Int32X(vp *map[int32]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Int32V(v map[int32]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[int32]int32, xlen) + changed = true + } + + var mk int32 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]int64) + v, changed := fastpathTV.DecMapInt32Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]int64) + fastpathTV.DecMapInt32Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Int64X(vp *map[int32]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Int64V(v map[int32]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]int64, xlen) + changed = true + } + + var mk int32 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]float32) + v, changed := fastpathTV.DecMapInt32Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]float32) + fastpathTV.DecMapInt32Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Float32X(vp *map[int32]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Float32V(v map[int32]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 8) + v = make(map[int32]float32, xlen) + changed = true + } + + var mk int32 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]float64) + v, changed := fastpathTV.DecMapInt32Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]float64) + fastpathTV.DecMapInt32Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32Float64X(vp *map[int32]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32Float64V(v map[int32]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int32]float64, xlen) + changed = true + } + + var mk int32 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt32BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int32]bool) + v, changed := fastpathTV.DecMapInt32BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int32]bool) + fastpathTV.DecMapInt32BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt32BoolX(vp *map[int32]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt32BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt32BoolV(v map[int32]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[int32]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[int32]bool, xlen) + changed = true + } + + var mk int32 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = int32(dd.DecodeInt(32)) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64IntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]interface{}) + v, changed := fastpathTV.DecMapInt64IntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]interface{}) + fastpathTV.DecMapInt64IntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64IntfX(vp *map[int64]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64IntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64IntfV(v map[int64]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[int64]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk int64 + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64StringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]string) + v, changed := fastpathTV.DecMapInt64StringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]string) + fastpathTV.DecMapInt64StringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64StringX(vp *map[int64]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64StringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64StringV(v map[int64]string, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 24) + v = make(map[int64]string, xlen) + changed = true + } + + var mk int64 + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64UintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uint) + v, changed := fastpathTV.DecMapInt64UintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uint) + fastpathTV.DecMapInt64UintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64UintX(vp *map[int64]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64UintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64UintV(v map[int64]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]uint, xlen) + changed = true + } + + var mk int64 + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Uint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uint8) + v, changed := fastpathTV.DecMapInt64Uint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uint8) + fastpathTV.DecMapInt64Uint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Uint8X(vp *map[int64]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Uint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Uint8V(v map[int64]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int64]uint8, xlen) + changed = true + } + + var mk int64 + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Uint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uint16) + v, changed := fastpathTV.DecMapInt64Uint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uint16) + fastpathTV.DecMapInt64Uint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Uint16X(vp *map[int64]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Uint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Uint16V(v map[int64]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int64]uint16, xlen) + changed = true + } + + var mk int64 + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Uint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uint32) + v, changed := fastpathTV.DecMapInt64Uint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uint32) + fastpathTV.DecMapInt64Uint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Uint32X(vp *map[int64]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Uint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Uint32V(v map[int64]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int64]uint32, xlen) + changed = true + } + + var mk int64 + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Uint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uint64) + v, changed := fastpathTV.DecMapInt64Uint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uint64) + fastpathTV.DecMapInt64Uint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Uint64X(vp *map[int64]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Uint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Uint64V(v map[int64]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]uint64, xlen) + changed = true + } + + var mk int64 + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64UintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]uintptr) + v, changed := fastpathTV.DecMapInt64UintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]uintptr) + fastpathTV.DecMapInt64UintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64UintptrX(vp *map[int64]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64UintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64UintptrV(v map[int64]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]uintptr, xlen) + changed = true + } + + var mk int64 + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64IntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]int) + v, changed := fastpathTV.DecMapInt64IntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]int) + fastpathTV.DecMapInt64IntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64IntX(vp *map[int64]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64IntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64IntV(v map[int64]int, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]int, xlen) + changed = true + } + + var mk int64 + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Int8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]int8) + v, changed := fastpathTV.DecMapInt64Int8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]int8) + fastpathTV.DecMapInt64Int8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Int8X(vp *map[int64]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Int8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Int8V(v map[int64]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int64]int8, xlen) + changed = true + } + + var mk int64 + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Int16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]int16) + v, changed := fastpathTV.DecMapInt64Int16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]int16) + fastpathTV.DecMapInt64Int16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Int16X(vp *map[int64]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Int16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Int16V(v map[int64]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 10) + v = make(map[int64]int16, xlen) + changed = true + } + + var mk int64 + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Int32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]int32) + v, changed := fastpathTV.DecMapInt64Int32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]int32) + fastpathTV.DecMapInt64Int32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Int32X(vp *map[int64]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Int32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Int32V(v map[int64]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int64]int32, xlen) + changed = true + } + + var mk int64 + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Int64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]int64) + v, changed := fastpathTV.DecMapInt64Int64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]int64) + fastpathTV.DecMapInt64Int64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Int64X(vp *map[int64]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Int64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Int64V(v map[int64]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]int64, xlen) + changed = true + } + + var mk int64 + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Float32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]float32) + v, changed := fastpathTV.DecMapInt64Float32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]float32) + fastpathTV.DecMapInt64Float32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Float32X(vp *map[int64]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Float32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Float32V(v map[int64]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 12) + v = make(map[int64]float32, xlen) + changed = true + } + + var mk int64 + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64Float64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]float64) + v, changed := fastpathTV.DecMapInt64Float64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]float64) + fastpathTV.DecMapInt64Float64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64Float64X(vp *map[int64]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64Float64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64Float64V(v map[int64]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 16) + v = make(map[int64]float64, xlen) + changed = true + } + + var mk int64 + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapInt64BoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[int64]bool) + v, changed := fastpathTV.DecMapInt64BoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[int64]bool) + fastpathTV.DecMapInt64BoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapInt64BoolX(vp *map[int64]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapInt64BoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapInt64BoolV(v map[int64]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[int64]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[int64]bool, xlen) + changed = true + } + + var mk int64 + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeInt(64) + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolIntfR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]interface{}) + v, changed := fastpathTV.DecMapBoolIntfV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]interface{}) + fastpathTV.DecMapBoolIntfV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolIntfX(vp *map[bool]interface{}, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolIntfV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolIntfV(v map[bool]interface{}, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]interface{}, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[bool]interface{}, xlen) + changed = true + } + mapGet := !d.h.MapValueReset && !d.h.InterfaceReset + var mk bool + var mv interface{} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + if mapGet { + mv = v[mk] + } else { + mv = nil + } + d.decode(&mv) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolStringR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]string) + v, changed := fastpathTV.DecMapBoolStringV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]string) + fastpathTV.DecMapBoolStringV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolStringX(vp *map[bool]string, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolStringV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolStringV(v map[bool]string, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]string, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 17) + v = make(map[bool]string, xlen) + changed = true + } + + var mk bool + var mv string + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeString() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUintR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uint) + v, changed := fastpathTV.DecMapBoolUintV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uint) + fastpathTV.DecMapBoolUintV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUintX(vp *map[bool]uint, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUintV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUintV(v map[bool]uint, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uint, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]uint, xlen) + changed = true + } + + var mk bool + var mv uint + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUint8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uint8) + v, changed := fastpathTV.DecMapBoolUint8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uint8) + fastpathTV.DecMapBoolUint8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUint8X(vp *map[bool]uint8, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUint8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUint8V(v map[bool]uint8, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uint8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[bool]uint8, xlen) + changed = true + } + + var mk bool + var mv uint8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint8(dd.DecodeUint(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUint16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uint16) + v, changed := fastpathTV.DecMapBoolUint16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uint16) + fastpathTV.DecMapBoolUint16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUint16X(vp *map[bool]uint16, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUint16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUint16V(v map[bool]uint16, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uint16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[bool]uint16, xlen) + changed = true + } + + var mk bool + var mv uint16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint16(dd.DecodeUint(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUint32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uint32) + v, changed := fastpathTV.DecMapBoolUint32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uint32) + fastpathTV.DecMapBoolUint32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUint32X(vp *map[bool]uint32, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUint32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUint32V(v map[bool]uint32, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uint32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[bool]uint32, xlen) + changed = true + } + + var mk bool + var mv uint32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uint32(dd.DecodeUint(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUint64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uint64) + v, changed := fastpathTV.DecMapBoolUint64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uint64) + fastpathTV.DecMapBoolUint64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUint64X(vp *map[bool]uint64, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUint64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUint64V(v map[bool]uint64, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uint64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]uint64, xlen) + changed = true + } + + var mk bool + var mv uint64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeUint(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolUintptrR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]uintptr) + v, changed := fastpathTV.DecMapBoolUintptrV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]uintptr) + fastpathTV.DecMapBoolUintptrV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolUintptrX(vp *map[bool]uintptr, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolUintptrV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolUintptrV(v map[bool]uintptr, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]uintptr, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]uintptr, xlen) + changed = true + } + + var mk bool + var mv uintptr + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = uintptr(dd.DecodeUint(uintBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolIntR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]int) + v, changed := fastpathTV.DecMapBoolIntV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]int) + fastpathTV.DecMapBoolIntV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolIntX(vp *map[bool]int, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolIntV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolIntV(v map[bool]int, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]int, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]int, xlen) + changed = true + } + + var mk bool + var mv int + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int(dd.DecodeInt(intBitsize)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolInt8R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]int8) + v, changed := fastpathTV.DecMapBoolInt8V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]int8) + fastpathTV.DecMapBoolInt8V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolInt8X(vp *map[bool]int8, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolInt8V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolInt8V(v map[bool]int8, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]int8, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[bool]int8, xlen) + changed = true + } + + var mk bool + var mv int8 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int8(dd.DecodeInt(8)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolInt16R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]int16) + v, changed := fastpathTV.DecMapBoolInt16V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]int16) + fastpathTV.DecMapBoolInt16V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolInt16X(vp *map[bool]int16, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolInt16V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolInt16V(v map[bool]int16, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]int16, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 3) + v = make(map[bool]int16, xlen) + changed = true + } + + var mk bool + var mv int16 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int16(dd.DecodeInt(16)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolInt32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]int32) + v, changed := fastpathTV.DecMapBoolInt32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]int32) + fastpathTV.DecMapBoolInt32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolInt32X(vp *map[bool]int32, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolInt32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolInt32V(v map[bool]int32, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]int32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[bool]int32, xlen) + changed = true + } + + var mk bool + var mv int32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = int32(dd.DecodeInt(32)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolInt64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]int64) + v, changed := fastpathTV.DecMapBoolInt64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]int64) + fastpathTV.DecMapBoolInt64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolInt64X(vp *map[bool]int64, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolInt64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolInt64V(v map[bool]int64, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]int64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]int64, xlen) + changed = true + } + + var mk bool + var mv int64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeInt(64) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolFloat32R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]float32) + v, changed := fastpathTV.DecMapBoolFloat32V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]float32) + fastpathTV.DecMapBoolFloat32V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolFloat32X(vp *map[bool]float32, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolFloat32V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolFloat32V(v map[bool]float32, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]float32, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 5) + v = make(map[bool]float32, xlen) + changed = true + } + + var mk bool + var mv float32 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = float32(dd.DecodeFloat(true)) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolFloat64R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]float64) + v, changed := fastpathTV.DecMapBoolFloat64V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]float64) + fastpathTV.DecMapBoolFloat64V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolFloat64X(vp *map[bool]float64, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolFloat64V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolFloat64V(v map[bool]float64, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]float64, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 9) + v = make(map[bool]float64, xlen) + changed = true + } + + var mk bool + var mv float64 + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeFloat(false) + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} + +func (f *decFnInfo) fastpathDecMapBoolBoolR(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[bool]bool) + v, changed := fastpathTV.DecMapBoolBoolV(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[bool]bool) + fastpathTV.DecMapBoolBoolV(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) DecMapBoolBoolX(vp *map[bool]bool, checkNil bool, d *Decoder) { + v, changed := f.DecMapBoolBoolV(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) DecMapBoolBoolV(v map[bool]bool, checkNil bool, canChange bool, + d *Decoder) (_ map[bool]bool, changed bool) { + dd := d.d + cr := d.cr + + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, 2) + v = make(map[bool]bool, xlen) + changed = true + } + + var mk bool + var mv bool + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { + cr.sendContainerState(containerMapKey) + } + mk = dd.DecodeBool() + if cr != nil { + cr.sendContainerState(containerMapValue) + } + mv = dd.DecodeBool() + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { + cr.sendContainerState(containerMapEnd) + } + return v, changed +} diff --git a/vendor/github.com/ugorji/go/codec/fast-path.go.tmpl b/vendor/github.com/ugorji/go/codec/fast-path.go.tmpl new file mode 100644 index 000000000..04c173fba --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/fast-path.go.tmpl @@ -0,0 +1,540 @@ +// +build !notfastpath + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +// ************************************************************ +// DO NOT EDIT. +// THIS FILE IS AUTO-GENERATED from fast-path.go.tmpl +// ************************************************************ + +package codec + +// Fast path functions try to create a fast path encode or decode implementation +// for common maps and slices. +// +// We define the functions and register then in this single file +// so as not to pollute the encode.go and decode.go, and create a dependency in there. +// This file can be omitted without causing a build failure. +// +// The advantage of fast paths is: +// - Many calls bypass reflection altogether +// +// Currently support +// - slice of all builtin types, +// - map of all builtin types to string or interface value +// - symetrical maps of all builtin types (e.g. str-str, uint8-uint8) +// This should provide adequate "typical" implementations. +// +// Note that fast track decode functions must handle values for which an address cannot be obtained. +// For example: +// m2 := map[string]int{} +// p2 := []interface{}{m2} +// // decoding into p2 will bomb if fast track functions do not treat like unaddressable. +// + +import ( + "reflect" + "sort" +) + +const fastpathCheckNilFalse = false // for reflect +const fastpathCheckNilTrue = true // for type switch + +type fastpathT struct {} + +var fastpathTV fastpathT + +type fastpathE struct { + rtid uintptr + rt reflect.Type + encfn func(*encFnInfo, reflect.Value) + decfn func(*decFnInfo, reflect.Value) +} + +type fastpathA [{{ .FastpathLen }}]fastpathE + +func (x *fastpathA) index(rtid uintptr) int { + // use binary search to grab the index (adapted from sort/search.go) + h, i, j := 0, 0, {{ .FastpathLen }} // len(x) + for i < j { + h = i + (j-i)/2 + if x[h].rtid < rtid { + i = h + 1 + } else { + j = h + } + } + if i < {{ .FastpathLen }} && x[i].rtid == rtid { + return i + } + return -1 +} + +type fastpathAslice []fastpathE + +func (x fastpathAslice) Len() int { return len(x) } +func (x fastpathAslice) Less(i, j int) bool { return x[i].rtid < x[j].rtid } +func (x fastpathAslice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +var fastpathAV fastpathA + +// due to possible initialization loop error, make fastpath in an init() +func init() { + if !fastpathEnabled { + return + } + i := 0 + fn := func(v interface{}, fe func(*encFnInfo, reflect.Value), fd func(*decFnInfo, reflect.Value)) (f fastpathE) { + xrt := reflect.TypeOf(v) + xptr := reflect.ValueOf(xrt).Pointer() + fastpathAV[i] = fastpathE{xptr, xrt, fe, fd} + i++ + return + } + + {{range .Values}}{{if not .Primitive}}{{if not .MapKey }} + fn([]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}} + + {{range .Values}}{{if not .Primitive}}{{if .MapKey }} + fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}} + + sort.Sort(fastpathAslice(fastpathAV[:])) +} + +// -- encode + +// -- -- fast path type switch +func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { +{{range .Values}}{{if not .Primitive}}{{if not .MapKey }} + case []{{ .Elem }}:{{else}} + case map[{{ .MapKey }}]{{ .Elem }}:{{end}} + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e){{if not .MapKey }} + case *[]{{ .Elem }}:{{else}} + case *map[{{ .MapKey }}]{{ .Elem }}:{{end}} + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e) +{{end}}{{end}} + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { +{{range .Values}}{{if not .Primitive}}{{if not .MapKey }} + case []{{ .Elem }}: + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e) + case *[]{{ .Elem }}: + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e) +{{end}}{{end}}{{end}} + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { +{{range .Values}}{{if not .Primitive}}{{if .MapKey }} + case map[{{ .MapKey }}]{{ .Elem }}: + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e) + case *map[{{ .MapKey }}]{{ .Elem }}: + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e) +{{end}}{{end}}{{end}} + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +// -- -- fast path functions +{{range .Values}}{{if not .Primitive}}{{if not .MapKey }} + +func (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) { + if f.ti.mbs { + fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e) + } else { + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e) + } +} +func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeArrayStart(len(v)) + for _, v2 := range v { + if cr != nil { cr.sendContainerState(containerArrayElem) } + {{ encmd .Elem "v2"}} + } + if cr != nil { cr.sendContainerState(containerArrayEnd) }{{/* ee.EncodeEnd() */}} +} + +func (_ fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + if len(v)%2 == 1 { + e.errorf("mapBySlice requires even slice length, but got %v", len(v)) + return + } + ee.EncodeMapStart(len(v) / 2) + for j, v2 := range v { + if cr != nil { + if j%2 == 0 { + cr.sendContainerState(containerMapKey) + } else { + cr.sendContainerState(containerMapValue) + } + } + {{ encmd .Elem "v2"}} + } + if cr != nil { cr.sendContainerState(containerMapEnd) } +} + +{{end}}{{end}}{{end}} + +{{range .Values}}{{if not .Primitive}}{{if .MapKey }} + +func (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) { + fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().(map[{{ .MapKey }}]{{ .Elem }}), fastpathCheckNilFalse, f.e) +} +func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, e *Encoder) { + ee := e.e + cr := e.cr + if checkNil && v == nil { + ee.EncodeNil() + return + } + ee.EncodeMapStart(len(v)) + {{if eq .MapKey "string"}}asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + {{end}}if e.h.Canonical { + {{if eq .MapKey "interface{}"}}{{/* out of band + */}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding + e2 := NewEncoderBytes(&mksv, e.hh) + v2 := make([]bytesI, len(v)) + var i, l int + var vp *bytesI {{/* put loop variables outside. seems currently needed for better perf */}} + for k2, _ := range v { + l = len(mksv) + e2.MustEncode(k2) + vp = &v2[i] + vp.v = mksv[l:] + vp.i = k2 + i++ + } + sort.Sort(bytesISlice(v2)) + for j := range v2 { + if cr != nil { cr.sendContainerState(containerMapKey) } + e.asis(v2[j].v) + if cr != nil { cr.sendContainerState(containerMapValue) } + e.encode(v[v2[j].i]) + } {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v)) + var i int + for k, _ := range v { + v2[i] = {{ $x }}(k) + i++ + } + sort.Sort({{ sorttype .MapKey false}}(v2)) + for _, k2 := range v2 { + if cr != nil { cr.sendContainerState(containerMapKey) } + {{if eq .MapKey "string"}}if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + }{{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}} + if cr != nil { cr.sendContainerState(containerMapValue) } + {{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }} + } {{end}} + } else { + for k2, v2 := range v { + if cr != nil { cr.sendContainerState(containerMapKey) } + {{if eq .MapKey "string"}}if asSymbols { + ee.EncodeSymbol(k2) + } else { + ee.EncodeString(c_UTF8, k2) + }{{else}}{{ encmd .MapKey "k2"}}{{end}} + if cr != nil { cr.sendContainerState(containerMapValue) } + {{ encmd .Elem "v2"}} + } + } + if cr != nil { cr.sendContainerState(containerMapEnd) }{{/* ee.EncodeEnd() */}} +} + +{{end}}{{end}}{{end}} + +// -- decode + +// -- -- fast path type switch +func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { + if !fastpathEnabled { + return false + } + switch v := iv.(type) { +{{range .Values}}{{if not .Primitive}}{{if not .MapKey }} + case []{{ .Elem }}:{{else}} + case map[{{ .MapKey }}]{{ .Elem }}:{{end}} + fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, d){{if not .MapKey }} + case *[]{{ .Elem }}:{{else}} + case *map[{{ .MapKey }}]{{ .Elem }}:{{end}} + v2, changed2 := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, fastpathCheckNilFalse, true, d) + if changed2 { + *v = v2 + } +{{end}}{{end}} + default: + _ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release) + return false + } + return true +} + +// -- -- fast path functions +{{range .Values}}{{if not .Primitive}}{{if not .MapKey }} +{{/* +Slices can change if they +- did not come from an array +- are addressable (from a ptr) +- are settable (e.g. contained in an interface{}) +*/}} +func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) { + array := f.seq == seqTypeArray + if !array && rv.CanAddr() { {{/* // CanSet => CanAddr + Exported */}} + vp := rv.Addr().Interface().(*[]{{ .Elem }}) + v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, !array, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().([]{{ .Elem }}) + fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d) + } +} + +func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, checkNil bool, d *Decoder) { + v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, checkNil bool, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) { + dd := d.d + {{/* // if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil() */}} + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + slh, containerLenS := d.decSliceHelperStart() + if containerLenS == 0 { + if canChange { + if v == nil { + v = []{{ .Elem }}{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + + if containerLenS > 0 { + x2read := containerLenS + var xtrunc bool + if containerLenS > cap(v) { + if canChange { {{/* + // fast-path is for "basic" immutable types, so no need to copy them over + // s := make([]{{ .Elem }}, decInferLen(containerLenS, d.h.MaxInitLen)) + // copy(s, v[:cap(v)]) + // v = s */}} + var xlen int + xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }}) + if xtrunc { + if xlen <= cap(v) { + v = v[:xlen] + } else { + v = make([]{{ .Elem }}, xlen) + } + } else { + v = make([]{{ .Elem }}, xlen) + } + changed = true + } else { + d.arrayCannotExpand(len(v), containerLenS) + } + x2read = len(v) + } else if containerLenS != len(v) { + if canChange { + v = v[:containerLenS] + changed = true + } + } {{/* // all checks done. cannot go past len. */}} + j := 0 + for ; j < x2read; j++ { + slh.ElemContainerState(j) + {{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }} + } + if xtrunc { {{/* // means canChange=true, changed=true already. */}} + for ; j < containerLenS; j++ { + v = append(v, {{ zerocmd .Elem }}) + slh.ElemContainerState(j) + {{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }} + } + } else if !canChange { + for ; j < containerLenS; j++ { + slh.ElemContainerState(j) + d.swallow() + } + } + } else { + breakFound := dd.CheckBreak() {{/* check break first, so we can initialize v with a capacity of 4 if necessary */}} + if breakFound { + if canChange { + if v == nil { + v = []{{ .Elem }}{} + } else if len(v) != 0 { + v = v[:0] + } + changed = true + } + slh.End() + return v, changed + } + if cap(v) == 0 { + v = make([]{{ .Elem }}, 1, 4) + changed = true + } + j := 0 + for ; !breakFound; j++ { + if j >= len(v) { + if canChange { + v = append(v, {{ zerocmd .Elem }}) + changed = true + } else { + d.arrayCannotExpand(len(v), j+1) + } + } + slh.ElemContainerState(j) + if j < len(v) { {{/* // all checks done. cannot go past len. */}} + {{ if eq .Elem "interface{}" }}d.decode(&v[j]) + {{ else }}v[j] = {{ decmd .Elem }}{{ end }} + } else { + d.swallow() + } + breakFound = dd.CheckBreak() + } + if canChange && j < len(v) { + v = v[:j] + changed = true + } + } + slh.End() + return v, changed +} + +{{end}}{{end}}{{end}} + + +{{range .Values}}{{if not .Primitive}}{{if .MapKey }} +{{/* +Maps can change if they are +- addressable (from a ptr) +- settable (e.g. contained in an interface{}) +*/}} +func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) { + if rv.CanAddr() { + vp := rv.Addr().Interface().(*map[{{ .MapKey }}]{{ .Elem }}) + v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, true, f.d) + if changed { + *vp = v + } + } else { + v := rv.Interface().(map[{{ .MapKey }}]{{ .Elem }}) + fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d) + } +} +func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, d *Decoder) { + v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d) + if changed { + *vp = v + } +} +func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, canChange bool, + d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) { + dd := d.d + cr := d.cr + {{/* // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil() */}} + if checkNil && dd.TryDecodeAsNil() { + if v != nil { + changed = true + } + return nil, changed + } + + containerLen := dd.ReadMapStart() + if canChange && v == nil { + xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}) + v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen) + changed = true + } + {{ if eq .Elem "interface{}" }}mapGet := !d.h.MapValueReset && !d.h.InterfaceReset{{end}} + var mk {{ .MapKey }} + var mv {{ .Elem }} + if containerLen > 0 { + for j := 0; j < containerLen; j++ { + if cr != nil { cr.sendContainerState(containerMapKey) } + {{ if eq .MapKey "interface{}" }}mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}} + }{{ else }}mk = {{ decmd .MapKey }}{{ end }} + if cr != nil { cr.sendContainerState(containerMapValue) } + {{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil } + d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }} + if v != nil { + v[mk] = mv + } + } + } else if containerLen < 0 { + for j := 0; !dd.CheckBreak(); j++ { + if cr != nil { cr.sendContainerState(containerMapKey) } + {{ if eq .MapKey "interface{}" }}mk = nil + d.decode(&mk) + if bv, bok := mk.([]byte); bok { + mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}} + }{{ else }}mk = {{ decmd .MapKey }}{{ end }} + if cr != nil { cr.sendContainerState(containerMapValue) } + {{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil } + d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }} + if v != nil { + v[mk] = mv + } + } + } + if cr != nil { cr.sendContainerState(containerMapEnd) } + return v, changed +} + +{{end}}{{end}}{{end}} diff --git a/vendor/github.com/ugorji/go/codec/fast-path.not.go b/vendor/github.com/ugorji/go/codec/fast-path.not.go new file mode 100644 index 000000000..d6f5f0c91 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/fast-path.not.go @@ -0,0 +1,32 @@ +// +build notfastpath + +package codec + +import "reflect" + +// The generated fast-path code is very large, and adds a few seconds to the build time. +// This causes test execution, execution of small tools which use codec, etc +// to take a long time. +// +// To mitigate, we now support the notfastpath tag. +// This tag disables fastpath during build, allowing for faster build, test execution, +// short-program runs, etc. + +func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false } +func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false } +func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false } +func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false } + +type fastpathT struct{} +type fastpathE struct { + rtid uintptr + rt reflect.Type + encfn func(*encFnInfo, reflect.Value) + decfn func(*decFnInfo, reflect.Value) +} +type fastpathA [0]fastpathE + +func (x fastpathA) index(rtid uintptr) int { return -1 } + +var fastpathAV fastpathA +var fastpathTV fastpathT diff --git a/vendor/github.com/ugorji/go/codec/gen-dec-array.go.tmpl b/vendor/github.com/ugorji/go/codec/gen-dec-array.go.tmpl new file mode 100644 index 000000000..32df54144 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen-dec-array.go.tmpl @@ -0,0 +1,104 @@ +{{var "v"}} := {{if not isArray}}*{{end}}{{ .Varname }} +{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}{{if not isArray}} +var {{var "c"}} bool {{/* // changed */}} +_ = {{var "c"}}{{end}} +if {{var "l"}} == 0 { + {{if isSlice }}if {{var "v"}} == nil { + {{var "v"}} = []{{ .Typ }}{} + {{var "c"}} = true + } else if len({{var "v"}}) != 0 { + {{var "v"}} = {{var "v"}}[:0] + {{var "c"}} = true + } {{end}} {{if isChan }}if {{var "v"}} == nil { + {{var "v"}} = make({{ .CTyp }}, 0) + {{var "c"}} = true + } {{end}} +} else if {{var "l"}} > 0 { + {{if isChan }}if {{var "v"}} == nil { + {{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }}) + {{var "v"}} = make({{ .CTyp }}, {{var "rl"}}) + {{var "c"}} = true + } + for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ { + {{var "h"}}.ElemContainerState({{var "r"}}) + var {{var "t"}} {{ .Typ }} + {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} + {{var "v"}} <- {{var "t"}} + } + {{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}} + var {{var "rt"}} bool {{/* truncated */}} + _, _ = {{var "rl"}}, {{var "rt"}} + {{var "rr"}} = {{var "l"}} // len({{var "v"}}) + if {{var "l"}} > cap({{var "v"}}) { + {{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}}) + {{ else }}{{if not .Immutable }} + {{var "rg"}} := len({{var "v"}}) > 0 + {{var "v2"}} := {{var "v"}} {{end}} + {{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }}) + if {{var "rt"}} { + if {{var "rl"}} <= cap({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "rl"}}] + } else { + {{var "v"}} = make([]{{ .Typ }}, {{var "rl"}}) + } + } else { + {{var "v"}} = make([]{{ .Typ }}, {{var "rl"}}) + } + {{var "c"}} = true + {{var "rr"}} = len({{var "v"}}) {{if not .Immutable }} + if {{var "rg"}} { copy({{var "v"}}, {{var "v2"}}) } {{end}} {{end}}{{/* end not Immutable, isArray */}} + } {{if isSlice }} else if {{var "l"}} != len({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "l"}}] + {{var "c"}} = true + } {{end}} {{/* end isSlice:47 */}} + {{var "j"}} := 0 + for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ { + {{var "h"}}.ElemContainerState({{var "j"}}) + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } + {{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { + {{var "h"}}.ElemContainerState({{var "j"}}) + z.DecSwallow() + } + {{ else }}if {{var "rt"}} { + for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { + {{var "v"}} = append({{var "v"}}, {{ zero}}) + {{var "h"}}.ElemContainerState({{var "j"}}) + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } + } {{end}} {{/* end isArray:56 */}} + {{end}} {{/* end isChan:16 */}} +} else { {{/* len < 0 */}} + {{var "j"}} := 0 + for ; !r.CheckBreak(); {{var "j"}}++ { + {{if isChan }} + {{var "h"}}.ElemContainerState({{var "j"}}) + var {{var "t"}} {{ .Typ }} + {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} + {{var "v"}} <- {{var "t"}} + {{ else }} + if {{var "j"}} >= len({{var "v"}}) { + {{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1) + {{ else }}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }} + {{var "c"}} = true {{end}} + } + {{var "h"}}.ElemContainerState({{var "j"}}) + if {{var "j"}} < len({{var "v"}}) { + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } else { + z.DecSwallow() + } + {{end}} + } + {{if isSlice }}if {{var "j"}} < len({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "j"}}] + {{var "c"}} = true + } else if {{var "j"}} == 0 && {{var "v"}} == nil { + {{var "v"}} = []{{ .Typ }}{} + {{var "c"}} = true + }{{end}} +} +{{var "h"}}.End() +{{if not isArray }}if {{var "c"}} { + *{{ .Varname }} = {{var "v"}} +}{{end}} diff --git a/vendor/github.com/ugorji/go/codec/gen-dec-map.go.tmpl b/vendor/github.com/ugorji/go/codec/gen-dec-map.go.tmpl new file mode 100644 index 000000000..77400e0a1 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen-dec-map.go.tmpl @@ -0,0 +1,58 @@ +{{var "v"}} := *{{ .Varname }} +{{var "l"}} := r.ReadMapStart() +{{var "bh"}} := z.DecBasicHandle() +if {{var "v"}} == nil { + {{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }}) + {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}}) + *{{ .Varname }} = {{var "v"}} +} +var {{var "mk"}} {{ .KTyp }} +var {{var "mv"}} {{ .Typ }} +var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool +if {{var "bh"}}.MapValueReset { + {{if decElemKindPtr}}{{var "mg"}} = true + {{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true } + {{else if not decElemKindImmutable}}{{var "mg"}} = true + {{end}} } +if {{var "l"}} > 0 { +for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ { + z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) + {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} +{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { + {{var "mk"}} = string({{var "bv"}}) + }{{ end }}{{if decElemKindPtr}} + {{var "ms"}} = true{{end}} + if {{var "mg"}} { + {{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}] + if {{var "mok"}} { + {{var "ms"}} = false + } {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}} + } {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}} + z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) + {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} + if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil { + {{var "v"}}[{{var "mk"}}] = {{var "mv"}} + } +} +} else if {{var "l"}} < 0 { +for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { + z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) + {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} +{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { + {{var "mk"}} = string({{var "bv"}}) + }{{ end }}{{if decElemKindPtr}} + {{var "ms"}} = true {{ end }} + if {{var "mg"}} { + {{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}] + if {{var "mok"}} { + {{var "ms"}} = false + } {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}} + } {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}} + z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) + {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} + if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil { + {{var "v"}}[{{var "mk"}}] = {{var "mv"}} + } +} +} // else len==0: TODO: Should we clear map entries? +z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) diff --git a/vendor/github.com/ugorji/go/codec/gen-helper.generated.go b/vendor/github.com/ugorji/go/codec/gen-helper.generated.go new file mode 100644 index 000000000..22bce776b --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen-helper.generated.go @@ -0,0 +1,233 @@ +// //+build ignore + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +// ************************************************************ +// DO NOT EDIT. +// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl +// ************************************************************ + +package codec + +import ( + "encoding" + "reflect" +) + +// This file is used to generate helper code for codecgen. +// The values here i.e. genHelper(En|De)coder are not to be used directly by +// library users. They WILL change continously and without notice. +// +// To help enforce this, we create an unexported type with exported members. +// The only way to get the type is via the one exported type that we control (somewhat). +// +// When static codecs are created for types, they will use this value +// to perform encoding or decoding of primitives or known slice or map types. + +// GenHelperEncoder is exported so that it can be used externally by codecgen. +// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. +func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) { + return genHelperEncoder{e: e}, e.e +} + +// GenHelperDecoder is exported so that it can be used externally by codecgen. +// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. +func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) { + return genHelperDecoder{d: d}, d.d +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +type genHelperEncoder struct { + e *Encoder + F fastpathT +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +type genHelperDecoder struct { + d *Decoder + F fastpathT +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBasicHandle() *BasicHandle { + return f.e.h +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBinary() bool { + return f.e.be // f.e.hh.isBinaryEncoding() +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncFallback(iv interface{}) { + // println(">>>>>>>>> EncFallback") + f.e.encodeI(iv, false, false) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) { + bs, fnerr := iv.MarshalText() + f.e.marshal(bs, fnerr, false, c_UTF8) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) { + bs, fnerr := iv.MarshalJSON() + f.e.marshal(bs, fnerr, true, c_UTF8) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) { + bs, fnerr := iv.MarshalBinary() + f.e.marshal(bs, fnerr, false, c_RAW) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) TimeRtidIfBinc() uintptr { + if _, ok := f.e.hh.(*BincHandle); ok { + return timeTypId + } + return 0 +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) IsJSONHandle() bool { + return f.e.js +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) HasExtensions() bool { + return len(f.e.h.extHandle) != 0 +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncExt(v interface{}) (r bool) { + rt := reflect.TypeOf(v) + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + } + rtid := reflect.ValueOf(rt).Pointer() + if xfFn := f.e.h.getExt(rtid); xfFn != nil { + f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e) + return true + } + return false +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncSendContainerState(c containerState) { + if f.e.cr != nil { + f.e.cr.sendContainerState(c) + } +} + +// ---------------- DECODER FOLLOWS ----------------- + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBasicHandle() *BasicHandle { + return f.d.h +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBinary() bool { + return f.d.be // f.d.hh.isBinaryEncoding() +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSwallow() { + f.d.swallow() +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecScratchBuffer() []byte { + return f.d.b[:] +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) { + // println(">>>>>>>>> DecFallback") + f.d.decodeI(iv, chkPtr, false, false, false) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) { + return f.d.decSliceHelperStart() +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecStructFieldNotFound(index int, name string) { + f.d.structFieldNotFound(index, name) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) { + f.d.arrayCannotExpand(sliceLen, streamLen) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) { + fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true)) + if fnerr != nil { + panic(fnerr) + } +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) { + // bs := f.dd.DecodeBytes(f.d.b[:], true, true) + // grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself. + fnerr := tm.UnmarshalJSON(f.d.nextValueBytes()) + if fnerr != nil { + panic(fnerr) + } +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) { + fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true)) + if fnerr != nil { + panic(fnerr) + } +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) TimeRtidIfBinc() uintptr { + if _, ok := f.d.hh.(*BincHandle); ok { + return timeTypId + } + return 0 +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) IsJSONHandle() bool { + return f.d.js +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) HasExtensions() bool { + return len(f.d.h.extHandle) != 0 +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecExt(v interface{}) (r bool) { + rt := reflect.TypeOf(v).Elem() + rtid := reflect.ValueOf(rt).Pointer() + if xfFn := f.d.h.getExt(rtid); xfFn != nil { + f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext) + return true + } + return false +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) { + return decInferLen(clen, maxlen, unit) +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSendContainerState(c containerState) { + if f.d.cr != nil { + f.d.cr.sendContainerState(c) + } +} diff --git a/vendor/github.com/ugorji/go/codec/gen-helper.go.tmpl b/vendor/github.com/ugorji/go/codec/gen-helper.go.tmpl new file mode 100644 index 000000000..31958574f --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen-helper.go.tmpl @@ -0,0 +1,364 @@ +// //+build ignore + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +// ************************************************************ +// DO NOT EDIT. +// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl +// ************************************************************ + +package codec + +import ( + "encoding" + "reflect" +) + +// This file is used to generate helper code for codecgen. +// The values here i.e. genHelper(En|De)coder are not to be used directly by +// library users. They WILL change continously and without notice. +// +// To help enforce this, we create an unexported type with exported members. +// The only way to get the type is via the one exported type that we control (somewhat). +// +// When static codecs are created for types, they will use this value +// to perform encoding or decoding of primitives or known slice or map types. + +// GenHelperEncoder is exported so that it can be used externally by codecgen. +// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. +func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) { + return genHelperEncoder{e:e}, e.e +} + +// GenHelperDecoder is exported so that it can be used externally by codecgen. +// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. +func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) { + return genHelperDecoder{d:d}, d.d +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +type genHelperEncoder struct { + e *Encoder + F fastpathT +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +type genHelperDecoder struct { + d *Decoder + F fastpathT +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBasicHandle() *BasicHandle { + return f.e.h +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBinary() bool { + return f.e.be // f.e.hh.isBinaryEncoding() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncFallback(iv interface{}) { + // println(">>>>>>>>> EncFallback") + f.e.encodeI(iv, false, false) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) { + bs, fnerr := iv.MarshalText() + f.e.marshal(bs, fnerr, false, c_UTF8) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) { + bs, fnerr := iv.MarshalJSON() + f.e.marshal(bs, fnerr, true, c_UTF8) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) { + bs, fnerr := iv.MarshalBinary() + f.e.marshal(bs, fnerr, false, c_RAW) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) TimeRtidIfBinc() uintptr { + if _, ok := f.e.hh.(*BincHandle); ok { + return timeTypId + } + return 0 +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) IsJSONHandle() bool { + return f.e.js +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) HasExtensions() bool { + return len(f.e.h.extHandle) != 0 +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncExt(v interface{}) (r bool) { + rt := reflect.TypeOf(v) + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + } + rtid := reflect.ValueOf(rt).Pointer() + if xfFn := f.e.h.getExt(rtid); xfFn != nil { + f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e) + return true + } + return false +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncSendContainerState(c containerState) { + if f.e.cr != nil { + f.e.cr.sendContainerState(c) + } +} + +// ---------------- DECODER FOLLOWS ----------------- + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBasicHandle() *BasicHandle { + return f.d.h +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBinary() bool { + return f.d.be // f.d.hh.isBinaryEncoding() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSwallow() { + f.d.swallow() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecScratchBuffer() []byte { + return f.d.b[:] +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) { + // println(">>>>>>>>> DecFallback") + f.d.decodeI(iv, chkPtr, false, false, false) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) { + return f.d.decSliceHelperStart() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecStructFieldNotFound(index int, name string) { + f.d.structFieldNotFound(index, name) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) { + f.d.arrayCannotExpand(sliceLen, streamLen) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) { + fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true)) + if fnerr != nil { + panic(fnerr) + } +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) { + // bs := f.dd.DecodeBytes(f.d.b[:], true, true) + // grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself. + fnerr := tm.UnmarshalJSON(f.d.nextValueBytes()) + if fnerr != nil { + panic(fnerr) + } +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) { + fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true)) + if fnerr != nil { + panic(fnerr) + } +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) TimeRtidIfBinc() uintptr { + if _, ok := f.d.hh.(*BincHandle); ok { + return timeTypId + } + return 0 +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) IsJSONHandle() bool { + return f.d.js +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) HasExtensions() bool { + return len(f.d.h.extHandle) != 0 +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecExt(v interface{}) (r bool) { + rt := reflect.TypeOf(v).Elem() + rtid := reflect.ValueOf(rt).Pointer() + if xfFn := f.d.h.getExt(rtid); xfFn != nil { + f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext) + return true + } + return false +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) { + return decInferLen(clen, maxlen, unit) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecSendContainerState(c containerState) { + if f.d.cr != nil { + f.d.cr.sendContainerState(c) + } +} + +{{/* + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncDriver() encDriver { + return f.e.e +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecDriver() decDriver { + return f.d.d +} + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncNil() { + f.e.e.EncodeNil() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncBytes(v []byte) { + f.e.e.EncodeStringBytes(c_RAW, v) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncArrayStart(length int) { + f.e.e.EncodeArrayStart(length) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncArrayEnd() { + f.e.e.EncodeArrayEnd() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncArrayEntrySeparator() { + f.e.e.EncodeArrayEntrySeparator() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncMapStart(length int) { + f.e.e.EncodeMapStart(length) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncMapEnd() { + f.e.e.EncodeMapEnd() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncMapEntrySeparator() { + f.e.e.EncodeMapEntrySeparator() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) EncMapKVSeparator() { + f.e.e.EncodeMapKVSeparator() +} + +// --------- + +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecBytes(v *[]byte) { + *v = f.d.d.DecodeBytes(*v) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecTryNil() bool { + return f.d.d.TryDecodeAsNil() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecContainerIsNil() (b bool) { + return f.d.d.IsContainerType(valueTypeNil) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecContainerIsMap() (b bool) { + return f.d.d.IsContainerType(valueTypeMap) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecContainerIsArray() (b bool) { + return f.d.d.IsContainerType(valueTypeArray) +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecCheckBreak() bool { + return f.d.d.CheckBreak() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecMapStart() int { + return f.d.d.ReadMapStart() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecArrayStart() int { + return f.d.d.ReadArrayStart() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecMapEnd() { + f.d.d.ReadMapEnd() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecArrayEnd() { + f.d.d.ReadArrayEnd() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecArrayEntrySeparator() { + f.d.d.ReadArrayEntrySeparator() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecMapEntrySeparator() { + f.d.d.ReadMapEntrySeparator() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) DecMapKVSeparator() { + f.d.d.ReadMapKVSeparator() +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) ReadStringAsBytes(bs []byte) []byte { + return f.d.d.DecodeStringAsBytes(bs) +} + + +// -- encode calls (primitives) +{{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) {{ .MethodNamePfx "Enc" true }}(v {{ .Primitive }}) { + ee := f.e.e + {{ encmd .Primitive "v" }} +} +{{ end }}{{ end }}{{ end }} + +// -- decode calls (primitives) +{{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) {{ .MethodNamePfx "Dec" true }}(vp *{{ .Primitive }}) { + dd := f.d.d + *vp = {{ decmd .Primitive }} +} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperDecoder) {{ .MethodNamePfx "Read" true }}() (v {{ .Primitive }}) { + dd := f.d.d + v = {{ decmd .Primitive }} + return +} +{{ end }}{{ end }}{{ end }} + + +// -- encode calls (slices/maps) +{{range .Values}}{{if not .Primitive }}{{if .Slice }} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v []{{ .Elem }}) { {{ else }} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v map[{{ .MapKey }}]{{ .Elem }}) { {{end}} + f.F.{{ .MethodNamePfx "Enc" false }}V(v, false, f.e) +} +{{ end }}{{ end }} + +// -- decode calls (slices/maps) +{{range .Values}}{{if not .Primitive }} +// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* +{{if .Slice }}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *[]{{ .Elem }}) { +{{else}}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *map[{{ .MapKey }}]{{ .Elem }}) { {{end}} + v, changed := f.F.{{ .MethodNamePfx "Dec" false }}V(*vp, false, true, f.d) + if changed { + *vp = v + } +} +{{ end }}{{ end }} +*/}} diff --git a/vendor/github.com/ugorji/go/codec/gen.generated.go b/vendor/github.com/ugorji/go/codec/gen.generated.go new file mode 100644 index 000000000..2ace97b78 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen.generated.go @@ -0,0 +1,175 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +// DO NOT EDIT. THIS FILE IS AUTO-GENERATED FROM gen-dec-(map|array).go.tmpl + +const genDecMapTmpl = ` +{{var "v"}} := *{{ .Varname }} +{{var "l"}} := r.ReadMapStart() +{{var "bh"}} := z.DecBasicHandle() +if {{var "v"}} == nil { + {{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }}) + {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}}) + *{{ .Varname }} = {{var "v"}} +} +var {{var "mk"}} {{ .KTyp }} +var {{var "mv"}} {{ .Typ }} +var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool +if {{var "bh"}}.MapValueReset { + {{if decElemKindPtr}}{{var "mg"}} = true + {{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true } + {{else if not decElemKindImmutable}}{{var "mg"}} = true + {{end}} } +if {{var "l"}} > 0 { +for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ { + z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) + {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} +{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { + {{var "mk"}} = string({{var "bv"}}) + }{{ end }}{{if decElemKindPtr}} + {{var "ms"}} = true{{end}} + if {{var "mg"}} { + {{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}] + if {{var "mok"}} { + {{var "ms"}} = false + } {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}} + } {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}} + z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) + {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} + if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil { + {{var "v"}}[{{var "mk"}}] = {{var "mv"}} + } +} +} else if {{var "l"}} < 0 { +for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { + z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) + {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} +{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { + {{var "mk"}} = string({{var "bv"}}) + }{{ end }}{{if decElemKindPtr}} + {{var "ms"}} = true {{ end }} + if {{var "mg"}} { + {{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}] + if {{var "mok"}} { + {{var "ms"}} = false + } {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}} + } {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}} + z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) + {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} + if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil { + {{var "v"}}[{{var "mk"}}] = {{var "mv"}} + } +} +} // else len==0: TODO: Should we clear map entries? +z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) +` + +const genDecListTmpl = ` +{{var "v"}} := {{if not isArray}}*{{end}}{{ .Varname }} +{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}{{if not isArray}} +var {{var "c"}} bool {{/* // changed */}} +_ = {{var "c"}}{{end}} +if {{var "l"}} == 0 { + {{if isSlice }}if {{var "v"}} == nil { + {{var "v"}} = []{{ .Typ }}{} + {{var "c"}} = true + } else if len({{var "v"}}) != 0 { + {{var "v"}} = {{var "v"}}[:0] + {{var "c"}} = true + } {{end}} {{if isChan }}if {{var "v"}} == nil { + {{var "v"}} = make({{ .CTyp }}, 0) + {{var "c"}} = true + } {{end}} +} else if {{var "l"}} > 0 { + {{if isChan }}if {{var "v"}} == nil { + {{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }}) + {{var "v"}} = make({{ .CTyp }}, {{var "rl"}}) + {{var "c"}} = true + } + for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ { + {{var "h"}}.ElemContainerState({{var "r"}}) + var {{var "t"}} {{ .Typ }} + {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} + {{var "v"}} <- {{var "t"}} + } + {{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}} + var {{var "rt"}} bool {{/* truncated */}} + _, _ = {{var "rl"}}, {{var "rt"}} + {{var "rr"}} = {{var "l"}} // len({{var "v"}}) + if {{var "l"}} > cap({{var "v"}}) { + {{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}}) + {{ else }}{{if not .Immutable }} + {{var "rg"}} := len({{var "v"}}) > 0 + {{var "v2"}} := {{var "v"}} {{end}} + {{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }}) + if {{var "rt"}} { + if {{var "rl"}} <= cap({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "rl"}}] + } else { + {{var "v"}} = make([]{{ .Typ }}, {{var "rl"}}) + } + } else { + {{var "v"}} = make([]{{ .Typ }}, {{var "rl"}}) + } + {{var "c"}} = true + {{var "rr"}} = len({{var "v"}}) {{if not .Immutable }} + if {{var "rg"}} { copy({{var "v"}}, {{var "v2"}}) } {{end}} {{end}}{{/* end not Immutable, isArray */}} + } {{if isSlice }} else if {{var "l"}} != len({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "l"}}] + {{var "c"}} = true + } {{end}} {{/* end isSlice:47 */}} + {{var "j"}} := 0 + for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ { + {{var "h"}}.ElemContainerState({{var "j"}}) + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } + {{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { + {{var "h"}}.ElemContainerState({{var "j"}}) + z.DecSwallow() + } + {{ else }}if {{var "rt"}} { + for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { + {{var "v"}} = append({{var "v"}}, {{ zero}}) + {{var "h"}}.ElemContainerState({{var "j"}}) + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } + } {{end}} {{/* end isArray:56 */}} + {{end}} {{/* end isChan:16 */}} +} else { {{/* len < 0 */}} + {{var "j"}} := 0 + for ; !r.CheckBreak(); {{var "j"}}++ { + {{if isChan }} + {{var "h"}}.ElemContainerState({{var "j"}}) + var {{var "t"}} {{ .Typ }} + {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} + {{var "v"}} <- {{var "t"}} + {{ else }} + if {{var "j"}} >= len({{var "v"}}) { + {{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1) + {{ else }}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }} + {{var "c"}} = true {{end}} + } + {{var "h"}}.ElemContainerState({{var "j"}}) + if {{var "j"}} < len({{var "v"}}) { + {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} + } else { + z.DecSwallow() + } + {{end}} + } + {{if isSlice }}if {{var "j"}} < len({{var "v"}}) { + {{var "v"}} = {{var "v"}}[:{{var "j"}}] + {{var "c"}} = true + } else if {{var "j"}} == 0 && {{var "v"}} == nil { + {{var "v"}} = []{{ .Typ }}{} + {{var "c"}} = true + }{{end}} +} +{{var "h"}}.End() +{{if not isArray }}if {{var "c"}} { + *{{ .Varname }} = {{var "v"}} +}{{end}} +` + diff --git a/vendor/github.com/ugorji/go/codec/gen.go b/vendor/github.com/ugorji/go/codec/gen.go new file mode 100644 index 000000000..d4dcbdcc0 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/gen.go @@ -0,0 +1,1989 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "bytes" + "encoding/base64" + "errors" + "fmt" + "go/format" + "io" + "io/ioutil" + "math/rand" + "os" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "sync" + "text/template" + "time" + "unicode" + "unicode/utf8" +) + +// --------------------------------------------------- +// codecgen supports the full cycle of reflection-based codec: +// - RawExt +// - Builtins +// - Extensions +// - (Binary|Text|JSON)(Unm|M)arshal +// - generic by-kind +// +// This means that, for dynamic things, we MUST use reflection to at least get the reflect.Type. +// In those areas, we try to only do reflection or interface-conversion when NECESSARY: +// - Extensions, only if Extensions are configured. +// +// However, codecgen doesn't support the following: +// - Canonical option. (codecgen IGNORES it currently) +// This is just because it has not been implemented. +// +// During encode/decode, Selfer takes precedence. +// A type implementing Selfer will know how to encode/decode itself statically. +// +// The following field types are supported: +// array: [n]T +// slice: []T +// map: map[K]V +// primitive: [u]int[n], float(32|64), bool, string +// struct +// +// --------------------------------------------------- +// Note that a Selfer cannot call (e|d).(En|De)code on itself, +// as this will cause a circular reference, as (En|De)code will call Selfer methods. +// Any type that implements Selfer must implement completely and not fallback to (En|De)code. +// +// In addition, code in this file manages the generation of fast-path implementations of +// encode/decode of slices/maps of primitive keys/values. +// +// Users MUST re-generate their implementations whenever the code shape changes. +// The generated code will panic if it was generated with a version older than the supporting library. +// --------------------------------------------------- +// +// codec framework is very feature rich. +// When encoding or decoding into an interface, it depends on the runtime type of the interface. +// The type of the interface may be a named type, an extension, etc. +// Consequently, we fallback to runtime codec for encoding/decoding interfaces. +// In addition, we fallback for any value which cannot be guaranteed at runtime. +// This allows us support ANY value, including any named types, specifically those which +// do not implement our interfaces (e.g. Selfer). +// +// This explains some slowness compared to other code generation codecs (e.g. msgp). +// This reduction in speed is only seen when your refers to interfaces, +// e.g. type T struct { A interface{}; B []interface{}; C map[string]interface{} } +// +// codecgen will panic if the file was generated with an old version of the library in use. +// +// Note: +// It was a concious decision to have gen.go always explicitly call EncodeNil or TryDecodeAsNil. +// This way, there isn't a function call overhead just to see that we should not enter a block of code. + +// GenVersion is the current version of codecgen. +// +// NOTE: Increment this value each time codecgen changes fundamentally. +// Fundamental changes are: +// - helper methods change (signature change, new ones added, some removed, etc) +// - codecgen command line changes +// +// v1: Initial Version +// v2: +// v3: Changes for Kubernetes: +// changes in signature of some unpublished helper methods and codecgen cmdline arguments. +// v4: Removed separator support from (en|de)cDriver, and refactored codec(gen) +// v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections. +const GenVersion = 5 + +const ( + genCodecPkg = "codec1978" + genTempVarPfx = "yy" + genTopLevelVarName = "x" + + // ignore canBeNil parameter, and always set to true. + // This is because nil can appear anywhere, so we should always check. + genAnythingCanBeNil = true + + // if genUseOneFunctionForDecStructMap, make a single codecDecodeSelferFromMap function; + // else make codecDecodeSelferFromMap{LenPrefix,CheckBreak} so that conditionals + // are not executed a lot. + // + // From testing, it didn't make much difference in runtime, so keep as true (one function only) + genUseOneFunctionForDecStructMap = true +) + +type genStructMapStyle uint8 + +const ( + genStructMapStyleConsolidated genStructMapStyle = iota + genStructMapStyleLenPrefix + genStructMapStyleCheckBreak +) + +var ( + genAllTypesSamePkgErr = errors.New("All types must be in the same package") + genExpectArrayOrMapErr = errors.New("unexpected type. Expecting array/map/slice") + genBase64enc = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789__") + genQNameRegex = regexp.MustCompile(`[A-Za-z_.]+`) +) + +// genRunner holds some state used during a Gen run. +type genRunner struct { + w io.Writer // output + c uint64 // counter used for generating varsfx + t []reflect.Type // list of types to run selfer on + + tc reflect.Type // currently running selfer on this type + te map[uintptr]bool // types for which the encoder has been created + td map[uintptr]bool // types for which the decoder has been created + cp string // codec import path + + im map[string]reflect.Type // imports to add + imn map[string]string // package names of imports to add + imc uint64 // counter for import numbers + + is map[reflect.Type]struct{} // types seen during import search + bp string // base PkgPath, for which we are generating for + + cpfx string // codec package prefix + unsafe bool // is unsafe to be used in generated code? + + tm map[reflect.Type]struct{} // types for which enc/dec must be generated + ts []reflect.Type // types for which enc/dec must be generated + + xs string // top level variable/constant suffix + hn string // fn helper type name + + ti *TypeInfos + // rr *rand.Rand // random generator for file-specific types +} + +// Gen will write a complete go file containing Selfer implementations for each +// type passed. All the types must be in the same package. +// +// Library users: *DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.* +func Gen(w io.Writer, buildTags, pkgName, uid string, useUnsafe bool, ti *TypeInfos, typ ...reflect.Type) { + if len(typ) == 0 { + return + } + x := genRunner{ + unsafe: useUnsafe, + w: w, + t: typ, + te: make(map[uintptr]bool), + td: make(map[uintptr]bool), + im: make(map[string]reflect.Type), + imn: make(map[string]string), + is: make(map[reflect.Type]struct{}), + tm: make(map[reflect.Type]struct{}), + ts: []reflect.Type{}, + bp: genImportPath(typ[0]), + xs: uid, + ti: ti, + } + if x.ti == nil { + x.ti = defTypeInfos + } + if x.xs == "" { + rr := rand.New(rand.NewSource(time.Now().UnixNano())) + x.xs = strconv.FormatInt(rr.Int63n(9999), 10) + } + + // gather imports first: + x.cp = genImportPath(reflect.TypeOf(x)) + x.imn[x.cp] = genCodecPkg + for _, t := range typ { + // fmt.Printf("###########: PkgPath: '%v', Name: '%s'\n", genImportPath(t), t.Name()) + if genImportPath(t) != x.bp { + panic(genAllTypesSamePkgErr) + } + x.genRefPkgs(t) + } + if buildTags != "" { + x.line("//+build " + buildTags) + x.line("") + } + x.line(` + +// ************************************************************ +// DO NOT EDIT. +// THIS FILE IS AUTO-GENERATED BY codecgen. +// ************************************************************ + +`) + x.line("package " + pkgName) + x.line("") + x.line("import (") + if x.cp != x.bp { + x.cpfx = genCodecPkg + "." + x.linef("%s \"%s\"", genCodecPkg, x.cp) + } + // use a sorted set of im keys, so that we can get consistent output + imKeys := make([]string, 0, len(x.im)) + for k, _ := range x.im { + imKeys = append(imKeys, k) + } + sort.Strings(imKeys) + for _, k := range imKeys { // for k, _ := range x.im { + x.linef("%s \"%s\"", x.imn[k], k) + } + // add required packages + for _, k := range [...]string{"reflect", "unsafe", "runtime", "fmt", "errors"} { + if _, ok := x.im[k]; !ok { + if k == "unsafe" && !x.unsafe { + continue + } + x.line("\"" + k + "\"") + } + } + x.line(")") + x.line("") + + x.line("const (") + x.linef("// ----- content types ----") + x.linef("codecSelferC_UTF8%s = %v", x.xs, int64(c_UTF8)) + x.linef("codecSelferC_RAW%s = %v", x.xs, int64(c_RAW)) + x.linef("// ----- value types used ----") + x.linef("codecSelferValueTypeArray%s = %v", x.xs, int64(valueTypeArray)) + x.linef("codecSelferValueTypeMap%s = %v", x.xs, int64(valueTypeMap)) + x.linef("// ----- containerStateValues ----") + x.linef("codecSelfer_containerMapKey%s = %v", x.xs, int64(containerMapKey)) + x.linef("codecSelfer_containerMapValue%s = %v", x.xs, int64(containerMapValue)) + x.linef("codecSelfer_containerMapEnd%s = %v", x.xs, int64(containerMapEnd)) + x.linef("codecSelfer_containerArrayElem%s = %v", x.xs, int64(containerArrayElem)) + x.linef("codecSelfer_containerArrayEnd%s = %v", x.xs, int64(containerArrayEnd)) + x.line(")") + x.line("var (") + x.line("codecSelferBitsize" + x.xs + " = uint8(reflect.TypeOf(uint(0)).Bits())") + x.line("codecSelferOnlyMapOrArrayEncodeToStructErr" + x.xs + " = errors.New(`only encoded map or array can be decoded into a struct`)") + x.line(")") + x.line("") + + if x.unsafe { + x.line("type codecSelferUnsafeString" + x.xs + " struct { Data uintptr; Len int}") + x.line("") + } + x.hn = "codecSelfer" + x.xs + x.line("type " + x.hn + " struct{}") + x.line("") + + x.line("func init() {") + x.linef("if %sGenVersion != %v {", x.cpfx, GenVersion) + x.line("_, file, _, _ := runtime.Caller(0)") + x.line(`err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v", `) + x.linef(`%v, %sGenVersion, file)`, GenVersion, x.cpfx) + x.line("panic(err)") + x.linef("}") + x.line("if false { // reference the types, but skip this branch at build/run time") + var n int + // for k, t := range x.im { + for _, k := range imKeys { + t := x.im[k] + x.linef("var v%v %s.%s", n, x.imn[k], t.Name()) + n++ + } + if x.unsafe { + x.linef("var v%v unsafe.Pointer", n) + n++ + } + if n > 0 { + x.out("_") + for i := 1; i < n; i++ { + x.out(", _") + } + x.out(" = v0") + for i := 1; i < n; i++ { + x.outf(", v%v", i) + } + } + x.line("} ") // close if false + x.line("}") // close init + x.line("") + + // generate rest of type info + for _, t := range typ { + x.tc = t + x.selfer(true) + x.selfer(false) + } + + for _, t := range x.ts { + rtid := reflect.ValueOf(t).Pointer() + // generate enc functions for all these slice/map types. + x.linef("func (x %s) enc%s(v %s%s, e *%sEncoder) {", x.hn, x.genMethodNameT(t), x.arr2str(t, "*"), x.genTypeName(t), x.cpfx) + x.genRequiredMethodVars(true) + switch t.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + x.encListFallback("v", t) + case reflect.Map: + x.encMapFallback("v", t) + default: + panic(genExpectArrayOrMapErr) + } + x.line("}") + x.line("") + + // generate dec functions for all these slice/map types. + x.linef("func (x %s) dec%s(v *%s, d *%sDecoder) {", x.hn, x.genMethodNameT(t), x.genTypeName(t), x.cpfx) + x.genRequiredMethodVars(false) + switch t.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + x.decListFallback("v", rtid, t) + case reflect.Map: + x.decMapFallback("v", rtid, t) + default: + panic(genExpectArrayOrMapErr) + } + x.line("}") + x.line("") + } + + x.line("") +} + +func (x *genRunner) checkForSelfer(t reflect.Type, varname string) bool { + // return varname != genTopLevelVarName && t != x.tc + // the only time we checkForSelfer is if we are not at the TOP of the generated code. + return varname != genTopLevelVarName +} + +func (x *genRunner) arr2str(t reflect.Type, s string) string { + if t.Kind() == reflect.Array { + return s + } + return "" +} + +func (x *genRunner) genRequiredMethodVars(encode bool) { + x.line("var h " + x.hn) + if encode { + x.line("z, r := " + x.cpfx + "GenHelperEncoder(e)") + } else { + x.line("z, r := " + x.cpfx + "GenHelperDecoder(d)") + } + x.line("_, _, _ = h, z, r") +} + +func (x *genRunner) genRefPkgs(t reflect.Type) { + if _, ok := x.is[t]; ok { + return + } + // fmt.Printf(">>>>>>: PkgPath: '%v', Name: '%s'\n", genImportPath(t), t.Name()) + x.is[t] = struct{}{} + tpkg, tname := genImportPath(t), t.Name() + if tpkg != "" && tpkg != x.bp && tpkg != x.cp && tname != "" && tname[0] >= 'A' && tname[0] <= 'Z' { + if _, ok := x.im[tpkg]; !ok { + x.im[tpkg] = t + if idx := strings.LastIndex(tpkg, "/"); idx < 0 { + x.imn[tpkg] = tpkg + } else { + x.imc++ + x.imn[tpkg] = "pkg" + strconv.FormatUint(x.imc, 10) + "_" + genGoIdentifier(tpkg[idx+1:], false) + } + } + } + switch t.Kind() { + case reflect.Array, reflect.Slice, reflect.Ptr, reflect.Chan: + x.genRefPkgs(t.Elem()) + case reflect.Map: + x.genRefPkgs(t.Elem()) + x.genRefPkgs(t.Key()) + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if fname := t.Field(i).Name; fname != "" && fname[0] >= 'A' && fname[0] <= 'Z' { + x.genRefPkgs(t.Field(i).Type) + } + } + } +} + +func (x *genRunner) line(s string) { + x.out(s) + if len(s) == 0 || s[len(s)-1] != '\n' { + x.out("\n") + } +} + +func (x *genRunner) varsfx() string { + x.c++ + return strconv.FormatUint(x.c, 10) +} + +func (x *genRunner) out(s string) { + if _, err := io.WriteString(x.w, s); err != nil { + panic(err) + } +} + +func (x *genRunner) linef(s string, params ...interface{}) { + x.line(fmt.Sprintf(s, params...)) +} + +func (x *genRunner) outf(s string, params ...interface{}) { + x.out(fmt.Sprintf(s, params...)) +} + +func (x *genRunner) genTypeName(t reflect.Type) (n string) { + // defer func() { fmt.Printf(">>>> ####: genTypeName: t: %v, name: '%s'\n", t, n) }() + + // if the type has a PkgPath, which doesn't match the current package, + // then include it. + // We cannot depend on t.String() because it includes current package, + // or t.PkgPath because it includes full import path, + // + var ptrPfx string + for t.Kind() == reflect.Ptr { + ptrPfx += "*" + t = t.Elem() + } + if tn := t.Name(); tn != "" { + return ptrPfx + x.genTypeNamePrim(t) + } + switch t.Kind() { + case reflect.Map: + return ptrPfx + "map[" + x.genTypeName(t.Key()) + "]" + x.genTypeName(t.Elem()) + case reflect.Slice: + return ptrPfx + "[]" + x.genTypeName(t.Elem()) + case reflect.Array: + return ptrPfx + "[" + strconv.FormatInt(int64(t.Len()), 10) + "]" + x.genTypeName(t.Elem()) + case reflect.Chan: + return ptrPfx + t.ChanDir().String() + " " + x.genTypeName(t.Elem()) + default: + if t == intfTyp { + return ptrPfx + "interface{}" + } else { + return ptrPfx + x.genTypeNamePrim(t) + } + } +} + +func (x *genRunner) genTypeNamePrim(t reflect.Type) (n string) { + if t.Name() == "" { + return t.String() + } else if genImportPath(t) == "" || genImportPath(t) == genImportPath(x.tc) { + return t.Name() + } else { + return x.imn[genImportPath(t)] + "." + t.Name() + // return t.String() // best way to get the package name inclusive + } +} + +func (x *genRunner) genZeroValueR(t reflect.Type) string { + // if t is a named type, w + switch t.Kind() { + case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func, + reflect.Slice, reflect.Map, reflect.Invalid: + return "nil" + case reflect.Bool: + return "false" + case reflect.String: + return `""` + case reflect.Struct, reflect.Array: + return x.genTypeName(t) + "{}" + default: // all numbers + return "0" + } +} + +func (x *genRunner) genMethodNameT(t reflect.Type) (s string) { + return genMethodNameT(t, x.tc) +} + +func (x *genRunner) selfer(encode bool) { + t := x.tc + t0 := t + // always make decode use a pointer receiver, + // and structs always use a ptr receiver (encode|decode) + isptr := !encode || t.Kind() == reflect.Struct + fnSigPfx := "func (x " + if isptr { + fnSigPfx += "*" + } + fnSigPfx += x.genTypeName(t) + + x.out(fnSigPfx) + if isptr { + t = reflect.PtrTo(t) + } + if encode { + x.line(") CodecEncodeSelf(e *" + x.cpfx + "Encoder) {") + x.genRequiredMethodVars(true) + // x.enc(genTopLevelVarName, t) + x.encVar(genTopLevelVarName, t) + } else { + x.line(") CodecDecodeSelf(d *" + x.cpfx + "Decoder) {") + x.genRequiredMethodVars(false) + // do not use decVar, as there is no need to check TryDecodeAsNil + // or way to elegantly handle that, and also setting it to a + // non-nil value doesn't affect the pointer passed. + // x.decVar(genTopLevelVarName, t, false) + x.dec(genTopLevelVarName, t0) + } + x.line("}") + x.line("") + + if encode || t0.Kind() != reflect.Struct { + return + } + + // write is containerMap + if genUseOneFunctionForDecStructMap { + x.out(fnSigPfx) + x.line(") codecDecodeSelfFromMap(l int, d *" + x.cpfx + "Decoder) {") + x.genRequiredMethodVars(false) + x.decStructMap(genTopLevelVarName, "l", reflect.ValueOf(t0).Pointer(), t0, genStructMapStyleConsolidated) + x.line("}") + x.line("") + } else { + x.out(fnSigPfx) + x.line(") codecDecodeSelfFromMapLenPrefix(l int, d *" + x.cpfx + "Decoder) {") + x.genRequiredMethodVars(false) + x.decStructMap(genTopLevelVarName, "l", reflect.ValueOf(t0).Pointer(), t0, genStructMapStyleLenPrefix) + x.line("}") + x.line("") + + x.out(fnSigPfx) + x.line(") codecDecodeSelfFromMapCheckBreak(l int, d *" + x.cpfx + "Decoder) {") + x.genRequiredMethodVars(false) + x.decStructMap(genTopLevelVarName, "l", reflect.ValueOf(t0).Pointer(), t0, genStructMapStyleCheckBreak) + x.line("}") + x.line("") + } + + // write containerArray + x.out(fnSigPfx) + x.line(") codecDecodeSelfFromArray(l int, d *" + x.cpfx + "Decoder) {") + x.genRequiredMethodVars(false) + x.decStructArray(genTopLevelVarName, "l", "return", reflect.ValueOf(t0).Pointer(), t0) + x.line("}") + x.line("") + +} + +// used for chan, array, slice, map +func (x *genRunner) xtraSM(varname string, encode bool, t reflect.Type) { + if encode { + x.linef("h.enc%s((%s%s)(%s), e)", x.genMethodNameT(t), x.arr2str(t, "*"), x.genTypeName(t), varname) + } else { + x.linef("h.dec%s((*%s)(%s), d)", x.genMethodNameT(t), x.genTypeName(t), varname) + } + x.registerXtraT(t) +} + +func (x *genRunner) registerXtraT(t reflect.Type) { + // recursively register the types + if _, ok := x.tm[t]; ok { + return + } + var tkey reflect.Type + switch t.Kind() { + case reflect.Chan, reflect.Slice, reflect.Array: + case reflect.Map: + tkey = t.Key() + default: + return + } + x.tm[t] = struct{}{} + x.ts = append(x.ts, t) + // check if this refers to any xtra types eg. a slice of array: add the array + x.registerXtraT(t.Elem()) + if tkey != nil { + x.registerXtraT(tkey) + } +} + +// encVar will encode a variable. +// The parameter, t, is the reflect.Type of the variable itself +func (x *genRunner) encVar(varname string, t reflect.Type) { + // fmt.Printf(">>>>>> varname: %s, t: %v\n", varname, t) + var checkNil bool + switch t.Kind() { + case reflect.Ptr, reflect.Interface, reflect.Slice, reflect.Map, reflect.Chan: + checkNil = true + } + if checkNil { + x.linef("if %s == nil { r.EncodeNil() } else { ", varname) + } + switch t.Kind() { + case reflect.Ptr: + switch t.Elem().Kind() { + case reflect.Struct, reflect.Array: + x.enc(varname, genNonPtr(t)) + default: + i := x.varsfx() + x.line(genTempVarPfx + i + " := *" + varname) + x.enc(genTempVarPfx+i, genNonPtr(t)) + } + case reflect.Struct, reflect.Array: + i := x.varsfx() + x.line(genTempVarPfx + i + " := &" + varname) + x.enc(genTempVarPfx+i, t) + default: + x.enc(varname, t) + } + + if checkNil { + x.line("}") + } + +} + +// enc will encode a variable (varname) of type t, +// except t is of kind reflect.Struct or reflect.Array, wherein varname is of type ptrTo(T) (to prevent copying) +func (x *genRunner) enc(varname string, t reflect.Type) { + rtid := reflect.ValueOf(t).Pointer() + // We call CodecEncodeSelf if one of the following are honored: + // - the type already implements Selfer, call that + // - the type has a Selfer implementation just created, use that + // - the type is in the list of the ones we will generate for, but it is not currently being generated + + mi := x.varsfx() + tptr := reflect.PtrTo(t) + tk := t.Kind() + if x.checkForSelfer(t, varname) { + if tk == reflect.Array || tk == reflect.Struct { // varname is of type *T + if tptr.Implements(selferTyp) || t.Implements(selferTyp) { + x.line(varname + ".CodecEncodeSelf(e)") + return + } + } else { // varname is of type T + if t.Implements(selferTyp) { + x.line(varname + ".CodecEncodeSelf(e)") + return + } else if tptr.Implements(selferTyp) { + x.linef("%ssf%s := &%s", genTempVarPfx, mi, varname) + x.linef("%ssf%s.CodecEncodeSelf(e)", genTempVarPfx, mi) + return + } + } + + if _, ok := x.te[rtid]; ok { + x.line(varname + ".CodecEncodeSelf(e)") + return + } + } + + inlist := false + for _, t0 := range x.t { + if t == t0 { + inlist = true + if x.checkForSelfer(t, varname) { + x.line(varname + ".CodecEncodeSelf(e)") + return + } + break + } + } + + var rtidAdded bool + if t == x.tc { + x.te[rtid] = true + rtidAdded = true + } + + // check if + // - type is RawExt + // - the type implements (Text|JSON|Binary)(Unm|M)arshal + x.linef("%sm%s := z.EncBinary()", genTempVarPfx, mi) + x.linef("_ = %sm%s", genTempVarPfx, mi) + x.line("if false {") //start if block + defer func() { x.line("}") }() //end if block + + if t == rawExtTyp { + x.linef("} else { r.EncodeRawExt(%v, e)", varname) + return + } + // HACK: Support for Builtins. + // Currently, only Binc supports builtins, and the only builtin type is time.Time. + // Have a method that returns the rtid for time.Time if Handle is Binc. + if t == timeTyp { + vrtid := genTempVarPfx + "m" + x.varsfx() + x.linef("} else if %s := z.TimeRtidIfBinc(); %s != 0 { ", vrtid, vrtid) + x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname) + } + // only check for extensions if the type is named, and has a packagePath. + if genImportPath(t) != "" && t.Name() != "" { + // first check if extensions are configued, before doing the interface conversion + x.linef("} else if z.HasExtensions() && z.EncExt(%s) {", varname) + } + if tk == reflect.Array || tk == reflect.Struct { // varname is of type *T + if t.Implements(binaryMarshalerTyp) || tptr.Implements(binaryMarshalerTyp) { + x.linef("} else if %sm%s { z.EncBinaryMarshal(%v) ", genTempVarPfx, mi, varname) + } + if t.Implements(jsonMarshalerTyp) || tptr.Implements(jsonMarshalerTyp) { + x.linef("} else if !%sm%s && z.IsJSONHandle() { z.EncJSONMarshal(%v) ", genTempVarPfx, mi, varname) + } else if t.Implements(textMarshalerTyp) || tptr.Implements(textMarshalerTyp) { + x.linef("} else if !%sm%s { z.EncTextMarshal(%v) ", genTempVarPfx, mi, varname) + } + } else { // varname is of type T + if t.Implements(binaryMarshalerTyp) { + x.linef("} else if %sm%s { z.EncBinaryMarshal(%v) ", genTempVarPfx, mi, varname) + } else if tptr.Implements(binaryMarshalerTyp) { + x.linef("} else if %sm%s { z.EncBinaryMarshal(&%v) ", genTempVarPfx, mi, varname) + } + if t.Implements(jsonMarshalerTyp) { + x.linef("} else if !%sm%s && z.IsJSONHandle() { z.EncJSONMarshal(%v) ", genTempVarPfx, mi, varname) + } else if tptr.Implements(jsonMarshalerTyp) { + x.linef("} else if !%sm%s && z.IsJSONHandle() { z.EncJSONMarshal(&%v) ", genTempVarPfx, mi, varname) + } else if t.Implements(textMarshalerTyp) { + x.linef("} else if !%sm%s { z.EncTextMarshal(%v) ", genTempVarPfx, mi, varname) + } else if tptr.Implements(textMarshalerTyp) { + x.linef("} else if !%sm%s { z.EncTextMarshal(&%v) ", genTempVarPfx, mi, varname) + } + } + x.line("} else {") + + switch t.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x.line("r.EncodeInt(int64(" + varname + "))") + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x.line("r.EncodeUint(uint64(" + varname + "))") + case reflect.Float32: + x.line("r.EncodeFloat32(float32(" + varname + "))") + case reflect.Float64: + x.line("r.EncodeFloat64(float64(" + varname + "))") + case reflect.Bool: + x.line("r.EncodeBool(bool(" + varname + "))") + case reflect.String: + x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + ", string(" + varname + "))") + case reflect.Chan: + x.xtraSM(varname, true, t) + // x.encListFallback(varname, rtid, t) + case reflect.Array: + x.xtraSM(varname, true, t) + case reflect.Slice: + // if nil, call dedicated function + // if a []uint8, call dedicated function + // if a known fastpath slice, call dedicated function + // else write encode function in-line. + // - if elements are primitives or Selfers, call dedicated function on each member. + // - else call Encoder.encode(XXX) on it. + if rtid == uint8SliceTypId { + x.line("r.EncodeStringBytes(codecSelferC_RAW" + x.xs + ", []byte(" + varname + "))") + } else if fastpathAV.index(rtid) != -1 { + g := x.newGenV(t) + x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)") + } else { + x.xtraSM(varname, true, t) + // x.encListFallback(varname, rtid, t) + } + case reflect.Map: + // if nil, call dedicated function + // if a known fastpath map, call dedicated function + // else write encode function in-line. + // - if elements are primitives or Selfers, call dedicated function on each member. + // - else call Encoder.encode(XXX) on it. + // x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ") + if fastpathAV.index(rtid) != -1 { + g := x.newGenV(t) + x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)") + } else { + x.xtraSM(varname, true, t) + // x.encMapFallback(varname, rtid, t) + } + case reflect.Struct: + if !inlist { + delete(x.te, rtid) + x.line("z.EncFallback(" + varname + ")") + break + } + x.encStruct(varname, rtid, t) + default: + if rtidAdded { + delete(x.te, rtid) + } + x.line("z.EncFallback(" + varname + ")") + } +} + +func (x *genRunner) encZero(t reflect.Type) { + switch t.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x.line("r.EncodeInt(0)") + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x.line("r.EncodeUint(0)") + case reflect.Float32: + x.line("r.EncodeFloat32(0)") + case reflect.Float64: + x.line("r.EncodeFloat64(0)") + case reflect.Bool: + x.line("r.EncodeBool(false)") + case reflect.String: + x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + `, "")`) + default: + x.line("r.EncodeNil()") + } +} + +func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) { + // Use knowledge from structfieldinfo (mbs, encodable fields. Ignore omitempty. ) + // replicate code in kStruct i.e. for each field, deref type to non-pointer, and call x.enc on it + + // if t === type currently running selfer on, do for all + ti := x.ti.get(rtid, t) + i := x.varsfx() + sepVarname := genTempVarPfx + "sep" + i + numfieldsvar := genTempVarPfx + "q" + i + ti2arrayvar := genTempVarPfx + "r" + i + struct2arrvar := genTempVarPfx + "2arr" + i + + x.line(sepVarname + " := !z.EncBinary()") + x.linef("%s := z.EncBasicHandle().StructToArray", struct2arrvar) + tisfi := ti.sfip // always use sequence from file. decStruct expects same thing. + // due to omitEmpty, we need to calculate the + // number of non-empty things we write out first. + // This is required as we need to pre-determine the size of the container, + // to support length-prefixing. + x.linef("var %s [%v]bool", numfieldsvar, len(tisfi)) + x.linef("_, _, _ = %s, %s, %s", sepVarname, numfieldsvar, struct2arrvar) + x.linef("const %s bool = %v", ti2arrayvar, ti.toArray) + nn := 0 + for j, si := range tisfi { + if !si.omitEmpty { + nn++ + continue + } + var t2 reflect.StructField + var omitline string + if si.i != -1 { + t2 = t.Field(int(si.i)) + } else { + t2typ := t + varname3 := varname + for _, ix := range si.is { + for t2typ.Kind() == reflect.Ptr { + t2typ = t2typ.Elem() + } + t2 = t2typ.Field(ix) + t2typ = t2.Type + varname3 = varname3 + "." + t2.Name + if t2typ.Kind() == reflect.Ptr { + omitline += varname3 + " != nil && " + } + } + } + // never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc. + // also, for maps/slices/arrays, check if len ! 0 (not if == zero value) + switch t2.Type.Kind() { + case reflect.Struct: + omitline += " true" + case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan: + omitline += "len(" + varname + "." + t2.Name + ") != 0" + default: + omitline += varname + "." + t2.Name + " != " + x.genZeroValueR(t2.Type) + } + x.linef("%s[%v] = %s", numfieldsvar, j, omitline) + } + x.linef("var %snn%s int", genTempVarPfx, i) + x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray { + x.line("r.EncodeArrayStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")") + x.linef("} else {") // if not ti.toArray + x.linef("%snn%s = %v", genTempVarPfx, i, nn) + x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i) + x.linef("r.EncodeMapStart(%snn%s)", genTempVarPfx, i) + x.linef("%snn%s = %v", genTempVarPfx, i, 0) + // x.line("r.EncodeMapStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")") + x.line("}") // close if not StructToArray + + for j, si := range tisfi { + i := x.varsfx() + isNilVarName := genTempVarPfx + "n" + i + var labelUsed bool + var t2 reflect.StructField + if si.i != -1 { + t2 = t.Field(int(si.i)) + } else { + t2typ := t + varname3 := varname + for _, ix := range si.is { + // fmt.Printf("%%%% %v, ix: %v\n", t2typ, ix) + for t2typ.Kind() == reflect.Ptr { + t2typ = t2typ.Elem() + } + t2 = t2typ.Field(ix) + t2typ = t2.Type + varname3 = varname3 + "." + t2.Name + if t2typ.Kind() == reflect.Ptr { + if !labelUsed { + x.line("var " + isNilVarName + " bool") + } + x.line("if " + varname3 + " == nil { " + isNilVarName + " = true ") + x.line("goto LABEL" + i) + x.line("}") + labelUsed = true + // "varname3 = new(" + x.genTypeName(t3.Elem()) + ") }") + } + } + // t2 = t.FieldByIndex(si.is) + } + if labelUsed { + x.line("LABEL" + i + ":") + } + // if the type of the field is a Selfer, or one of the ones + + x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray + if labelUsed { + x.line("if " + isNilVarName + " { r.EncodeNil() } else { ") + } + x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs) + if si.omitEmpty { + x.linef("if %s[%v] {", numfieldsvar, j) + } + x.encVar(varname+"."+t2.Name, t2.Type) + if si.omitEmpty { + x.linef("} else {") + x.encZero(t2.Type) + x.linef("}") + } + if labelUsed { + x.line("}") + } + + x.linef("} else {") // if not ti.toArray + + if si.omitEmpty { + x.linef("if %s[%v] {", numfieldsvar, j) + } + x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs) + x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + ", string(\"" + si.encName + "\"))") + x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs) + if labelUsed { + x.line("if " + isNilVarName + " { r.EncodeNil() } else { ") + x.encVar(varname+"."+t2.Name, t2.Type) + x.line("}") + } else { + x.encVar(varname+"."+t2.Name, t2.Type) + } + if si.omitEmpty { + x.line("}") + } + x.linef("} ") // end if/else ti.toArray + } + x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray { + x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs) + x.line("} else {") + x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs) + x.line("}") + +} + +func (x *genRunner) encListFallback(varname string, t reflect.Type) { + i := x.varsfx() + g := genTempVarPfx + x.line("r.EncodeArrayStart(len(" + varname + "))") + if t.Kind() == reflect.Chan { + x.linef("for %si%s, %si2%s := 0, len(%s); %si%s < %si2%s; %si%s++ {", g, i, g, i, varname, g, i, g, i, g, i) + x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs) + x.linef("%sv%s := <-%s", g, i, varname) + } else { + // x.linef("for %si%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname) + x.linef("for _, %sv%s := range %s {", genTempVarPfx, i, varname) + x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs) + } + x.encVar(genTempVarPfx+"v"+i, t.Elem()) + x.line("}") + x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs) +} + +func (x *genRunner) encMapFallback(varname string, t reflect.Type) { + // TODO: expand this to handle canonical. + i := x.varsfx() + x.line("r.EncodeMapStart(len(" + varname + "))") + x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname) + // x.line("for " + genTempVarPfx + "k" + i + ", " + genTempVarPfx + "v" + i + " := range " + varname + " {") + x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs) + x.encVar(genTempVarPfx+"k"+i, t.Key()) + x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs) + x.encVar(genTempVarPfx+"v"+i, t.Elem()) + x.line("}") + x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs) +} + +func (x *genRunner) decVar(varname string, t reflect.Type, canBeNil bool) { + // We only encode as nil if a nillable value. + // This removes some of the wasted checks for TryDecodeAsNil. + // We need to think about this more, to see what happens if omitempty, etc + // cause a nil value to be stored when something is expected. + // This could happen when decoding from a struct encoded as an array. + // For that, decVar should be called with canNil=true, to force true as its value. + i := x.varsfx() + if !canBeNil { + canBeNil = genAnythingCanBeNil || !genIsImmutable(t) + } + if canBeNil { + x.line("if r.TryDecodeAsNil() {") + if t.Kind() == reflect.Ptr { + x.line("if " + varname + " != nil { ") + + // if varname is a field of a struct (has a dot in it), + // then just set it to nil + if strings.IndexByte(varname, '.') != -1 { + x.line(varname + " = nil") + } else { + x.line("*" + varname + " = " + x.genZeroValueR(t.Elem())) + } + x.line("}") + } else { + x.line(varname + " = " + x.genZeroValueR(t)) + } + x.line("} else {") + } else { + x.line("// cannot be nil") + } + if t.Kind() != reflect.Ptr { + if x.decTryAssignPrimitive(varname, t) { + x.line(genTempVarPfx + "v" + i + " := &" + varname) + x.dec(genTempVarPfx+"v"+i, t) + } + } else { + x.linef("if %s == nil { %s = new(%s) }", varname, varname, x.genTypeName(t.Elem())) + // Ensure we set underlying ptr to a non-nil value (so we can deref to it later). + // There's a chance of a **T in here which is nil. + var ptrPfx string + for t = t.Elem(); t.Kind() == reflect.Ptr; t = t.Elem() { + ptrPfx += "*" + x.linef("if %s%s == nil { %s%s = new(%s)}", + ptrPfx, varname, ptrPfx, varname, x.genTypeName(t)) + } + // if varname has [ in it, then create temp variable for this ptr thingie + if strings.Index(varname, "[") >= 0 { + varname2 := genTempVarPfx + "w" + i + x.line(varname2 + " := " + varname) + varname = varname2 + } + + if ptrPfx == "" { + x.dec(varname, t) + } else { + x.line(genTempVarPfx + "z" + i + " := " + ptrPfx + varname) + x.dec(genTempVarPfx+"z"+i, t) + } + + } + + if canBeNil { + x.line("} ") + } +} + +// dec will decode a variable (varname) of type ptrTo(t). +// t is always a basetype (i.e. not of kind reflect.Ptr). +func (x *genRunner) dec(varname string, t reflect.Type) { + // assumptions: + // - the varname is to a pointer already. No need to take address of it + // - t is always a baseType T (not a *T, etc). + rtid := reflect.ValueOf(t).Pointer() + tptr := reflect.PtrTo(t) + if x.checkForSelfer(t, varname) { + if t.Implements(selferTyp) || tptr.Implements(selferTyp) { + x.line(varname + ".CodecDecodeSelf(d)") + return + } + if _, ok := x.td[rtid]; ok { + x.line(varname + ".CodecDecodeSelf(d)") + return + } + } + + inlist := false + for _, t0 := range x.t { + if t == t0 { + inlist = true + if x.checkForSelfer(t, varname) { + x.line(varname + ".CodecDecodeSelf(d)") + return + } + break + } + } + + var rtidAdded bool + if t == x.tc { + x.td[rtid] = true + rtidAdded = true + } + + // check if + // - type is RawExt + // - the type implements (Text|JSON|Binary)(Unm|M)arshal + mi := x.varsfx() + x.linef("%sm%s := z.DecBinary()", genTempVarPfx, mi) + x.linef("_ = %sm%s", genTempVarPfx, mi) + x.line("if false {") //start if block + defer func() { x.line("}") }() //end if block + + if t == rawExtTyp { + x.linef("} else { r.DecodeExt(%v, 0, nil)", varname) + return + } + + // HACK: Support for Builtins. + // Currently, only Binc supports builtins, and the only builtin type is time.Time. + // Have a method that returns the rtid for time.Time if Handle is Binc. + if t == timeTyp { + vrtid := genTempVarPfx + "m" + x.varsfx() + x.linef("} else if %s := z.TimeRtidIfBinc(); %s != 0 { ", vrtid, vrtid) + x.linef("r.DecodeBuiltin(%s, %s)", vrtid, varname) + } + // only check for extensions if the type is named, and has a packagePath. + if genImportPath(t) != "" && t.Name() != "" { + // first check if extensions are configued, before doing the interface conversion + x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname) + } + + if t.Implements(binaryUnmarshalerTyp) || tptr.Implements(binaryUnmarshalerTyp) { + x.linef("} else if %sm%s { z.DecBinaryUnmarshal(%v) ", genTempVarPfx, mi, varname) + } + if t.Implements(jsonUnmarshalerTyp) || tptr.Implements(jsonUnmarshalerTyp) { + x.linef("} else if !%sm%s && z.IsJSONHandle() { z.DecJSONUnmarshal(%v)", genTempVarPfx, mi, varname) + } else if t.Implements(textUnmarshalerTyp) || tptr.Implements(textUnmarshalerTyp) { + x.linef("} else if !%sm%s { z.DecTextUnmarshal(%v)", genTempVarPfx, mi, varname) + } + + x.line("} else {") + + // Since these are pointers, we cannot share, and have to use them one by one + switch t.Kind() { + case reflect.Int: + x.line("*((*int)(" + varname + ")) = int(r.DecodeInt(codecSelferBitsize" + x.xs + "))") + // x.line("z.DecInt((*int)(" + varname + "))") + case reflect.Int8: + x.line("*((*int8)(" + varname + ")) = int8(r.DecodeInt(8))") + // x.line("z.DecInt8((*int8)(" + varname + "))") + case reflect.Int16: + x.line("*((*int16)(" + varname + ")) = int16(r.DecodeInt(16))") + // x.line("z.DecInt16((*int16)(" + varname + "))") + case reflect.Int32: + x.line("*((*int32)(" + varname + ")) = int32(r.DecodeInt(32))") + // x.line("z.DecInt32((*int32)(" + varname + "))") + case reflect.Int64: + x.line("*((*int64)(" + varname + ")) = int64(r.DecodeInt(64))") + // x.line("z.DecInt64((*int64)(" + varname + "))") + + case reflect.Uint: + x.line("*((*uint)(" + varname + ")) = uint(r.DecodeUint(codecSelferBitsize" + x.xs + "))") + // x.line("z.DecUint((*uint)(" + varname + "))") + case reflect.Uint8: + x.line("*((*uint8)(" + varname + ")) = uint8(r.DecodeUint(8))") + // x.line("z.DecUint8((*uint8)(" + varname + "))") + case reflect.Uint16: + x.line("*((*uint16)(" + varname + ")) = uint16(r.DecodeUint(16))") + //x.line("z.DecUint16((*uint16)(" + varname + "))") + case reflect.Uint32: + x.line("*((*uint32)(" + varname + ")) = uint32(r.DecodeUint(32))") + //x.line("z.DecUint32((*uint32)(" + varname + "))") + case reflect.Uint64: + x.line("*((*uint64)(" + varname + ")) = uint64(r.DecodeUint(64))") + //x.line("z.DecUint64((*uint64)(" + varname + "))") + case reflect.Uintptr: + x.line("*((*uintptr)(" + varname + ")) = uintptr(r.DecodeUint(codecSelferBitsize" + x.xs + "))") + + case reflect.Float32: + x.line("*((*float32)(" + varname + ")) = float32(r.DecodeFloat(true))") + //x.line("z.DecFloat32((*float32)(" + varname + "))") + case reflect.Float64: + x.line("*((*float64)(" + varname + ")) = float64(r.DecodeFloat(false))") + // x.line("z.DecFloat64((*float64)(" + varname + "))") + + case reflect.Bool: + x.line("*((*bool)(" + varname + ")) = r.DecodeBool()") + // x.line("z.DecBool((*bool)(" + varname + "))") + case reflect.String: + x.line("*((*string)(" + varname + ")) = r.DecodeString()") + // x.line("z.DecString((*string)(" + varname + "))") + case reflect.Array, reflect.Chan: + x.xtraSM(varname, false, t) + // x.decListFallback(varname, rtid, true, t) + case reflect.Slice: + // if a []uint8, call dedicated function + // if a known fastpath slice, call dedicated function + // else write encode function in-line. + // - if elements are primitives or Selfers, call dedicated function on each member. + // - else call Encoder.encode(XXX) on it. + if rtid == uint8SliceTypId { + x.line("*" + varname + " = r.DecodeBytes(*(*[]byte)(" + varname + "), false, false)") + } else if fastpathAV.index(rtid) != -1 { + g := x.newGenV(t) + x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)") + } else { + x.xtraSM(varname, false, t) + // x.decListFallback(varname, rtid, false, t) + } + case reflect.Map: + // if a known fastpath map, call dedicated function + // else write encode function in-line. + // - if elements are primitives or Selfers, call dedicated function on each member. + // - else call Encoder.encode(XXX) on it. + if fastpathAV.index(rtid) != -1 { + g := x.newGenV(t) + x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)") + } else { + x.xtraSM(varname, false, t) + // x.decMapFallback(varname, rtid, t) + } + case reflect.Struct: + if inlist { + x.decStruct(varname, rtid, t) + } else { + // delete(x.td, rtid) + x.line("z.DecFallback(" + varname + ", false)") + } + default: + if rtidAdded { + delete(x.te, rtid) + } + x.line("z.DecFallback(" + varname + ", true)") + } +} + +func (x *genRunner) decTryAssignPrimitive(varname string, t reflect.Type) (tryAsPtr bool) { + // We have to use the actual type name when doing a direct assignment. + // We don't have the luxury of casting the pointer to the underlying type. + // + // Consequently, in the situation of a + // type Message int32 + // var x Message + // var i int32 = 32 + // x = i // this will bomb + // x = Message(i) // this will work + // *((*int32)(&x)) = i // this will work + // + // Consequently, we replace: + // case reflect.Uint32: x.line(varname + " = uint32(r.DecodeUint(32))") + // with: + // case reflect.Uint32: x.line(varname + " = " + genTypeNamePrim(t, x.tc) + "(r.DecodeUint(32))") + + xfn := func(t reflect.Type) string { + return x.genTypeNamePrim(t) + } + switch t.Kind() { + case reflect.Int: + x.linef("%s = %s(r.DecodeInt(codecSelferBitsize%s))", varname, xfn(t), x.xs) + case reflect.Int8: + x.linef("%s = %s(r.DecodeInt(8))", varname, xfn(t)) + case reflect.Int16: + x.linef("%s = %s(r.DecodeInt(16))", varname, xfn(t)) + case reflect.Int32: + x.linef("%s = %s(r.DecodeInt(32))", varname, xfn(t)) + case reflect.Int64: + x.linef("%s = %s(r.DecodeInt(64))", varname, xfn(t)) + + case reflect.Uint: + x.linef("%s = %s(r.DecodeUint(codecSelferBitsize%s))", varname, xfn(t), x.xs) + case reflect.Uint8: + x.linef("%s = %s(r.DecodeUint(8))", varname, xfn(t)) + case reflect.Uint16: + x.linef("%s = %s(r.DecodeUint(16))", varname, xfn(t)) + case reflect.Uint32: + x.linef("%s = %s(r.DecodeUint(32))", varname, xfn(t)) + case reflect.Uint64: + x.linef("%s = %s(r.DecodeUint(64))", varname, xfn(t)) + case reflect.Uintptr: + x.linef("%s = %s(r.DecodeUint(codecSelferBitsize%s))", varname, xfn(t), x.xs) + + case reflect.Float32: + x.linef("%s = %s(r.DecodeFloat(true))", varname, xfn(t)) + case reflect.Float64: + x.linef("%s = %s(r.DecodeFloat(false))", varname, xfn(t)) + + case reflect.Bool: + x.linef("%s = %s(r.DecodeBool())", varname, xfn(t)) + case reflect.String: + x.linef("%s = %s(r.DecodeString())", varname, xfn(t)) + default: + tryAsPtr = true + } + return +} + +func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type) { + type tstruc struct { + TempVar string + Rand string + Varname string + CTyp string + Typ string + Immutable bool + Size int + } + telem := t.Elem() + ts := tstruc{genTempVarPfx, x.varsfx(), varname, x.genTypeName(t), x.genTypeName(telem), genIsImmutable(telem), int(telem.Size())} + + funcs := make(template.FuncMap) + + funcs["decLineVar"] = func(varname string) string { + x.decVar(varname, telem, false) + return "" + } + funcs["decLine"] = func(pfx string) string { + x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false) + return "" + } + funcs["var"] = func(s string) string { + return ts.TempVar + s + ts.Rand + } + funcs["zero"] = func() string { + return x.genZeroValueR(telem) + } + funcs["isArray"] = func() bool { + return t.Kind() == reflect.Array + } + funcs["isSlice"] = func() bool { + return t.Kind() == reflect.Slice + } + funcs["isChan"] = func() bool { + return t.Kind() == reflect.Chan + } + tm, err := template.New("").Funcs(funcs).Parse(genDecListTmpl) + if err != nil { + panic(err) + } + if err = tm.Execute(x.w, &ts); err != nil { + panic(err) + } +} + +func (x *genRunner) decMapFallback(varname string, rtid uintptr, t reflect.Type) { + type tstruc struct { + TempVar string + Sfx string + Rand string + Varname string + KTyp string + Typ string + Size int + } + telem := t.Elem() + tkey := t.Key() + ts := tstruc{ + genTempVarPfx, x.xs, x.varsfx(), varname, x.genTypeName(tkey), + x.genTypeName(telem), int(telem.Size() + tkey.Size()), + } + + funcs := make(template.FuncMap) + funcs["decElemZero"] = func() string { + return x.genZeroValueR(telem) + } + funcs["decElemKindImmutable"] = func() bool { + return genIsImmutable(telem) + } + funcs["decElemKindPtr"] = func() bool { + return telem.Kind() == reflect.Ptr + } + funcs["decElemKindIntf"] = func() bool { + return telem.Kind() == reflect.Interface + } + funcs["decLineVarK"] = func(varname string) string { + x.decVar(varname, tkey, false) + return "" + } + funcs["decLineVar"] = func(varname string) string { + x.decVar(varname, telem, false) + return "" + } + funcs["decLineK"] = func(pfx string) string { + x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(tkey), false) + return "" + } + funcs["decLine"] = func(pfx string) string { + x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false) + return "" + } + funcs["var"] = func(s string) string { + return ts.TempVar + s + ts.Rand + } + + tm, err := template.New("").Funcs(funcs).Parse(genDecMapTmpl) + if err != nil { + panic(err) + } + if err = tm.Execute(x.w, &ts); err != nil { + panic(err) + } +} + +func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintptr, t reflect.Type) { + ti := x.ti.get(rtid, t) + tisfi := ti.sfip // always use sequence from file. decStruct expects same thing. + x.line("switch (" + kName + ") {") + for _, si := range tisfi { + x.line("case \"" + si.encName + "\":") + var t2 reflect.StructField + if si.i != -1 { + t2 = t.Field(int(si.i)) + } else { + //we must accomodate anonymous fields, where the embedded field is a nil pointer in the value. + // t2 = t.FieldByIndex(si.is) + t2typ := t + varname3 := varname + for _, ix := range si.is { + for t2typ.Kind() == reflect.Ptr { + t2typ = t2typ.Elem() + } + t2 = t2typ.Field(ix) + t2typ = t2.Type + varname3 = varname3 + "." + t2.Name + if t2typ.Kind() == reflect.Ptr { + x.linef("if %s == nil { %s = new(%s) }", varname3, varname3, x.genTypeName(t2typ.Elem())) + } + } + } + x.decVar(varname+"."+t2.Name, t2.Type, false) + } + x.line("default:") + // pass the slice here, so that the string will not escape, and maybe save allocation + x.line("z.DecStructFieldNotFound(-1, " + kName + ")") + x.line("} // end switch " + kName) +} + +func (x *genRunner) decStructMap(varname, lenvarname string, rtid uintptr, t reflect.Type, style genStructMapStyle) { + tpfx := genTempVarPfx + i := x.varsfx() + kName := tpfx + "s" + i + + // We thought to use ReadStringAsBytes, as go compiler might optimize the copy out. + // However, using that was more expensive, as it seems that the switch expression + // is evaluated each time. + // + // We could depend on decodeString using a temporary/shared buffer internally. + // However, this model of creating a byte array, and using explicitly is faster, + // and allows optional use of unsafe []byte->string conversion without alloc. + + // Also, ensure that the slice array doesn't escape. + // That will help escape analysis prevent allocation when it gets better. + + // x.line("var " + kName + "Arr = [32]byte{} // default string to decode into") + // x.line("var " + kName + "Slc = " + kName + "Arr[:] // default slice to decode into") + // use the scratch buffer to avoid allocation (most field names are < 32). + + x.line("var " + kName + "Slc = z.DecScratchBuffer() // default slice to decode into") + + x.line("_ = " + kName + "Slc") + switch style { + case genStructMapStyleLenPrefix: + x.linef("for %sj%s := 0; %sj%s < %s; %sj%s++ {", tpfx, i, tpfx, i, lenvarname, tpfx, i) + case genStructMapStyleCheckBreak: + x.linef("for %sj%s := 0; !r.CheckBreak(); %sj%s++ {", tpfx, i, tpfx, i) + default: // 0, otherwise. + x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length + x.linef("for %sj%s := 0; ; %sj%s++ {", tpfx, i, tpfx, i) + x.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname) + x.line("} else { if r.CheckBreak() { break }; }") + } + x.linef("z.DecSendContainerState(codecSelfer_containerMapKey%s)", x.xs) + x.line(kName + "Slc = r.DecodeBytes(" + kName + "Slc, true, true)") + // let string be scoped to this loop alone, so it doesn't escape. + if x.unsafe { + x.line(kName + "SlcHdr := codecSelferUnsafeString" + x.xs + "{uintptr(unsafe.Pointer(&" + + kName + "Slc[0])), len(" + kName + "Slc)}") + x.line(kName + " := *(*string)(unsafe.Pointer(&" + kName + "SlcHdr))") + } else { + x.line(kName + " := string(" + kName + "Slc)") + } + x.linef("z.DecSendContainerState(codecSelfer_containerMapValue%s)", x.xs) + x.decStructMapSwitch(kName, varname, rtid, t) + + x.line("} // end for " + tpfx + "j" + i) + x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs) +} + +func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) { + tpfx := genTempVarPfx + i := x.varsfx() + ti := x.ti.get(rtid, t) + tisfi := ti.sfip // always use sequence from file. decStruct expects same thing. + x.linef("var %sj%s int", tpfx, i) + x.linef("var %sb%s bool", tpfx, i) // break + x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length + for _, si := range tisfi { + var t2 reflect.StructField + if si.i != -1 { + t2 = t.Field(int(si.i)) + } else { + //we must accomodate anonymous fields, where the embedded field is a nil pointer in the value. + // t2 = t.FieldByIndex(si.is) + t2typ := t + varname3 := varname + for _, ix := range si.is { + for t2typ.Kind() == reflect.Ptr { + t2typ = t2typ.Elem() + } + t2 = t2typ.Field(ix) + t2typ = t2.Type + varname3 = varname3 + "." + t2.Name + if t2typ.Kind() == reflect.Ptr { + x.linef("if %s == nil { %s = new(%s) }", varname3, varname3, x.genTypeName(t2typ.Elem())) + } + } + } + + x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }", + tpfx, i, tpfx, i, tpfx, i, + tpfx, i, lenvarname, tpfx, i) + x.linef("if %sb%s { z.DecSendContainerState(codecSelfer_containerArrayEnd%s); %s }", + tpfx, i, x.xs, breakString) + x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs) + x.decVar(varname+"."+t2.Name, t2.Type, true) + } + // read remaining values and throw away. + x.line("for {") + x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }", + tpfx, i, tpfx, i, tpfx, i, + tpfx, i, lenvarname, tpfx, i) + x.linef("if %sb%s { break }", tpfx, i) + x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs) + x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i) + x.line("}") + x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs) +} + +func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) { + // if container is map + i := x.varsfx() + x.linef("%sct%s := r.ContainerType()", genTempVarPfx, i) + x.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs) + x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()") + x.linef("if %sl%s == 0 {", genTempVarPfx, i) + x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs) + if genUseOneFunctionForDecStructMap { + x.line("} else { ") + x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i) + } else { + x.line("} else if " + genTempVarPfx + "l" + i + " > 0 { ") + x.line("x.codecDecodeSelfFromMapLenPrefix(" + genTempVarPfx + "l" + i + ", d)") + x.line("} else {") + x.line("x.codecDecodeSelfFromMapCheckBreak(" + genTempVarPfx + "l" + i + ", d)") + } + x.line("}") + + // else if container is array + x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs) + x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()") + x.linef("if %sl%s == 0 {", genTempVarPfx, i) + x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs) + x.line("} else { ") + x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i) + x.line("}") + // else panic + x.line("} else { ") + x.line("panic(codecSelferOnlyMapOrArrayEncodeToStructErr" + x.xs + ")") + x.line("} ") +} + +// -------- + +type genV struct { + // genV is either a primitive (Primitive != "") or a map (MapKey != "") or a slice + MapKey string + Elem string + Primitive string + Size int +} + +func (x *genRunner) newGenV(t reflect.Type) (v genV) { + switch t.Kind() { + case reflect.Slice, reflect.Array: + te := t.Elem() + v.Elem = x.genTypeName(te) + v.Size = int(te.Size()) + case reflect.Map: + te, tk := t.Elem(), t.Key() + v.Elem = x.genTypeName(te) + v.MapKey = x.genTypeName(tk) + v.Size = int(te.Size() + tk.Size()) + default: + panic("unexpected type for newGenV. Requires map or slice type") + } + return +} + +func (x *genV) MethodNamePfx(prefix string, prim bool) string { + var name []byte + if prefix != "" { + name = append(name, prefix...) + } + if prim { + name = append(name, genTitleCaseName(x.Primitive)...) + } else { + if x.MapKey == "" { + name = append(name, "Slice"...) + } else { + name = append(name, "Map"...) + name = append(name, genTitleCaseName(x.MapKey)...) + } + name = append(name, genTitleCaseName(x.Elem)...) + } + return string(name) + +} + +var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") == "1" + +// genImportPath returns import path of a non-predeclared named typed, or an empty string otherwise. +// +// This handles the misbehaviour that occurs when 1.5-style vendoring is enabled, +// where PkgPath returns the full path, including the vendoring pre-fix that should have been stripped. +// We strip it here. +func genImportPath(t reflect.Type) (s string) { + s = t.PkgPath() + if genCheckVendor { + // HACK: Misbehaviour occurs in go 1.5. May have to re-visit this later. + // if s contains /vendor/ OR startsWith vendor/, then return everything after it. + const vendorStart = "vendor/" + const vendorInline = "/vendor/" + if i := strings.LastIndex(s, vendorInline); i >= 0 { + s = s[i+len(vendorInline):] + } else if strings.HasPrefix(s, vendorStart) { + s = s[len(vendorStart):] + } + } + return +} + +// A go identifier is (letter|_)[letter|number|_]* +func genGoIdentifier(s string, checkFirstChar bool) string { + b := make([]byte, 0, len(s)) + t := make([]byte, 4) + var n int + for i, r := range s { + if checkFirstChar && i == 0 && !unicode.IsLetter(r) { + b = append(b, '_') + } + // r must be unicode_letter, unicode_digit or _ + if unicode.IsLetter(r) || unicode.IsDigit(r) { + n = utf8.EncodeRune(t, r) + b = append(b, t[:n]...) + } else { + b = append(b, '_') + } + } + return string(b) +} + +func genNonPtr(t reflect.Type) reflect.Type { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t +} + +func genTitleCaseName(s string) string { + switch s { + case "interface{}": + return "Intf" + default: + return strings.ToUpper(s[0:1]) + s[1:] + } +} + +func genMethodNameT(t reflect.Type, tRef reflect.Type) (n string) { + var ptrPfx string + for t.Kind() == reflect.Ptr { + ptrPfx += "Ptrto" + t = t.Elem() + } + tstr := t.String() + if tn := t.Name(); tn != "" { + if tRef != nil && genImportPath(t) == genImportPath(tRef) { + return ptrPfx + tn + } else { + if genQNameRegex.MatchString(tstr) { + return ptrPfx + strings.Replace(tstr, ".", "_", 1000) + } else { + return ptrPfx + genCustomTypeName(tstr) + } + } + } + switch t.Kind() { + case reflect.Map: + return ptrPfx + "Map" + genMethodNameT(t.Key(), tRef) + genMethodNameT(t.Elem(), tRef) + case reflect.Slice: + return ptrPfx + "Slice" + genMethodNameT(t.Elem(), tRef) + case reflect.Array: + return ptrPfx + "Array" + strconv.FormatInt(int64(t.Len()), 10) + genMethodNameT(t.Elem(), tRef) + case reflect.Chan: + var cx string + switch t.ChanDir() { + case reflect.SendDir: + cx = "ChanSend" + case reflect.RecvDir: + cx = "ChanRecv" + default: + cx = "Chan" + } + return ptrPfx + cx + genMethodNameT(t.Elem(), tRef) + default: + if t == intfTyp { + return ptrPfx + "Interface" + } else { + if tRef != nil && genImportPath(t) == genImportPath(tRef) { + if t.Name() != "" { + return ptrPfx + t.Name() + } else { + return ptrPfx + genCustomTypeName(tstr) + } + } else { + // best way to get the package name inclusive + // return ptrPfx + strings.Replace(tstr, ".", "_", 1000) + // return ptrPfx + genBase64enc.EncodeToString([]byte(tstr)) + if t.Name() != "" && genQNameRegex.MatchString(tstr) { + return ptrPfx + strings.Replace(tstr, ".", "_", 1000) + } else { + return ptrPfx + genCustomTypeName(tstr) + } + } + } + } +} + +// genCustomNameForType base64encodes the t.String() value in such a way +// that it can be used within a function name. +func genCustomTypeName(tstr string) string { + len2 := genBase64enc.EncodedLen(len(tstr)) + bufx := make([]byte, len2) + genBase64enc.Encode(bufx, []byte(tstr)) + for i := len2 - 1; i >= 0; i-- { + if bufx[i] == '=' { + len2-- + } else { + break + } + } + return string(bufx[:len2]) +} + +func genIsImmutable(t reflect.Type) (v bool) { + return isImmutableKind(t.Kind()) +} + +type genInternal struct { + Values []genV + Unsafe bool +} + +func (x genInternal) FastpathLen() (l int) { + for _, v := range x.Values { + if v.Primitive == "" { + l++ + } + } + return +} + +func genInternalZeroValue(s string) string { + switch s { + case "interface{}": + return "nil" + case "bool": + return "false" + case "string": + return `""` + default: + return "0" + } +} + +func genInternalEncCommandAsString(s string, vname string) string { + switch s { + case "uint", "uint8", "uint16", "uint32", "uint64": + return "ee.EncodeUint(uint64(" + vname + "))" + case "int", "int8", "int16", "int32", "int64": + return "ee.EncodeInt(int64(" + vname + "))" + case "string": + return "ee.EncodeString(c_UTF8, " + vname + ")" + case "float32": + return "ee.EncodeFloat32(" + vname + ")" + case "float64": + return "ee.EncodeFloat64(" + vname + ")" + case "bool": + return "ee.EncodeBool(" + vname + ")" + case "symbol": + return "ee.EncodeSymbol(" + vname + ")" + default: + return "e.encode(" + vname + ")" + } +} + +func genInternalDecCommandAsString(s string) string { + switch s { + case "uint": + return "uint(dd.DecodeUint(uintBitsize))" + case "uint8": + return "uint8(dd.DecodeUint(8))" + case "uint16": + return "uint16(dd.DecodeUint(16))" + case "uint32": + return "uint32(dd.DecodeUint(32))" + case "uint64": + return "dd.DecodeUint(64)" + case "uintptr": + return "uintptr(dd.DecodeUint(uintBitsize))" + case "int": + return "int(dd.DecodeInt(intBitsize))" + case "int8": + return "int8(dd.DecodeInt(8))" + case "int16": + return "int16(dd.DecodeInt(16))" + case "int32": + return "int32(dd.DecodeInt(32))" + case "int64": + return "dd.DecodeInt(64)" + + case "string": + return "dd.DecodeString()" + case "float32": + return "float32(dd.DecodeFloat(true))" + case "float64": + return "dd.DecodeFloat(false)" + case "bool": + return "dd.DecodeBool()" + default: + panic(errors.New("gen internal: unknown type for decode: " + s)) + } +} + +func genInternalSortType(s string, elem bool) string { + for _, v := range [...]string{"int", "uint", "float", "bool", "string"} { + if strings.HasPrefix(s, v) { + if elem { + if v == "int" || v == "uint" || v == "float" { + return v + "64" + } else { + return v + } + } + return v + "Slice" + } + } + panic("sorttype: unexpected type: " + s) +} + +// var genInternalMu sync.Mutex +var genInternalV genInternal +var genInternalTmplFuncs template.FuncMap +var genInternalOnce sync.Once + +func genInternalInit() { + types := [...]string{ + "interface{}", + "string", + "float32", + "float64", + "uint", + "uint8", + "uint16", + "uint32", + "uint64", + "uintptr", + "int", + "int8", + "int16", + "int32", + "int64", + "bool", + } + // keep as slice, so it is in specific iteration order. + // Initial order was uint64, string, interface{}, int, int64 + mapvaltypes := [...]string{ + "interface{}", + "string", + "uint", + "uint8", + "uint16", + "uint32", + "uint64", + "uintptr", + "int", + "int8", + "int16", + "int32", + "int64", + "float32", + "float64", + "bool", + } + wordSizeBytes := int(intBitsize) / 8 + + mapvaltypes2 := map[string]int{ + "interface{}": 2 * wordSizeBytes, + "string": 2 * wordSizeBytes, + "uint": 1 * wordSizeBytes, + "uint8": 1, + "uint16": 2, + "uint32": 4, + "uint64": 8, + "uintptr": 1 * wordSizeBytes, + "int": 1 * wordSizeBytes, + "int8": 1, + "int16": 2, + "int32": 4, + "int64": 8, + "float32": 4, + "float64": 8, + "bool": 1, + } + var gt genInternal + + // For each slice or map type, there must be a (symetrical) Encode and Decode fast-path function + for _, s := range types { + gt.Values = append(gt.Values, genV{Primitive: s, Size: mapvaltypes2[s]}) + if s != "uint8" { // do not generate fast path for slice of bytes. Treat specially already. + gt.Values = append(gt.Values, genV{Elem: s, Size: mapvaltypes2[s]}) + } + if _, ok := mapvaltypes2[s]; !ok { + gt.Values = append(gt.Values, genV{MapKey: s, Elem: s, Size: 2 * mapvaltypes2[s]}) + } + for _, ms := range mapvaltypes { + gt.Values = append(gt.Values, genV{MapKey: s, Elem: ms, Size: mapvaltypes2[s] + mapvaltypes2[ms]}) + } + } + + funcs := make(template.FuncMap) + // funcs["haspfx"] = strings.HasPrefix + funcs["encmd"] = genInternalEncCommandAsString + funcs["decmd"] = genInternalDecCommandAsString + funcs["zerocmd"] = genInternalZeroValue + funcs["hasprefix"] = strings.HasPrefix + funcs["sorttype"] = genInternalSortType + + genInternalV = gt + genInternalTmplFuncs = funcs +} + +// genInternalGoFile is used to generate source files from templates. +// It is run by the program author alone. +// Unfortunately, it has to be exported so that it can be called from a command line tool. +// *** DO NOT USE *** +func genInternalGoFile(r io.Reader, w io.Writer, safe bool) (err error) { + genInternalOnce.Do(genInternalInit) + + gt := genInternalV + gt.Unsafe = !safe + + t := template.New("").Funcs(genInternalTmplFuncs) + + tmplstr, err := ioutil.ReadAll(r) + if err != nil { + return + } + + if t, err = t.Parse(string(tmplstr)); err != nil { + return + } + + var out bytes.Buffer + err = t.Execute(&out, gt) + if err != nil { + return + } + + bout, err := format.Source(out.Bytes()) + if err != nil { + w.Write(out.Bytes()) // write out if error, so we can still see. + // w.Write(bout) // write out if error, as much as possible, so we can still see. + return + } + w.Write(bout) + return +} diff --git a/vendor/github.com/ugorji/go/codec/helper.go b/vendor/github.com/ugorji/go/codec/helper.go new file mode 100644 index 000000000..40065a01c --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/helper.go @@ -0,0 +1,1271 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +// Contains code shared by both encode and decode. + +// Some shared ideas around encoding/decoding +// ------------------------------------------ +// +// If an interface{} is passed, we first do a type assertion to see if it is +// a primitive type or a map/slice of primitive types, and use a fastpath to handle it. +// +// If we start with a reflect.Value, we are already in reflect.Value land and +// will try to grab the function for the underlying Type and directly call that function. +// This is more performant than calling reflect.Value.Interface(). +// +// This still helps us bypass many layers of reflection, and give best performance. +// +// Containers +// ------------ +// Containers in the stream are either associative arrays (key-value pairs) or +// regular arrays (indexed by incrementing integers). +// +// Some streams support indefinite-length containers, and use a breaking +// byte-sequence to denote that the container has come to an end. +// +// Some streams also are text-based, and use explicit separators to denote the +// end/beginning of different values. +// +// During encode, we use a high-level condition to determine how to iterate through +// the container. That decision is based on whether the container is text-based (with +// separators) or binary (without separators). If binary, we do not even call the +// encoding of separators. +// +// During decode, we use a different high-level condition to determine how to iterate +// through the containers. That decision is based on whether the stream contained +// a length prefix, or if it used explicit breaks. If length-prefixed, we assume that +// it has to be binary, and we do not even try to read separators. +// +// The only codec that may suffer (slightly) is cbor, and only when decoding indefinite-length. +// It may suffer because we treat it like a text-based codec, and read separators. +// However, this read is a no-op and the cost is insignificant. +// +// Philosophy +// ------------ +// On decode, this codec will update containers appropriately: +// - If struct, update fields from stream into fields of struct. +// If field in stream not found in struct, handle appropriately (based on option). +// If a struct field has no corresponding value in the stream, leave it AS IS. +// If nil in stream, set value to nil/zero value. +// - If map, update map from stream. +// If the stream value is NIL, set the map to nil. +// - if slice, try to update up to length of array in stream. +// if container len is less than stream array length, +// and container cannot be expanded, handled (based on option). +// This means you can decode 4-element stream array into 1-element array. +// +// ------------------------------------ +// On encode, user can specify omitEmpty. This means that the value will be omitted +// if the zero value. The problem may occur during decode, where omitted values do not affect +// the value being decoded into. This means that if decoding into a struct with an +// int field with current value=5, and the field is omitted in the stream, then after +// decoding, the value will still be 5 (not 0). +// omitEmpty only works if you guarantee that you always decode into zero-values. +// +// ------------------------------------ +// We could have truncated a map to remove keys not available in the stream, +// or set values in the struct which are not in the stream to their zero values. +// We decided against it because there is no efficient way to do it. +// We may introduce it as an option later. +// However, that will require enabling it for both runtime and code generation modes. +// +// To support truncate, we need to do 2 passes over the container: +// map +// - first collect all keys (e.g. in k1) +// - for each key in stream, mark k1 that the key should not be removed +// - after updating map, do second pass and call delete for all keys in k1 which are not marked +// struct: +// - for each field, track the *typeInfo s1 +// - iterate through all s1, and for each one not marked, set value to zero +// - this involves checking the possible anonymous fields which are nil ptrs. +// too much work. +// +// ------------------------------------------ +// Error Handling is done within the library using panic. +// +// This way, the code doesn't have to keep checking if an error has happened, +// and we don't have to keep sending the error value along with each call +// or storing it in the En|Decoder and checking it constantly along the way. +// +// The disadvantage is that small functions which use panics cannot be inlined. +// The code accounts for that by only using panics behind an interface; +// since interface calls cannot be inlined, this is irrelevant. +// +// We considered storing the error is En|Decoder. +// - once it has its err field set, it cannot be used again. +// - panicing will be optional, controlled by const flag. +// - code should always check error first and return early. +// We eventually decided against it as it makes the code clumsier to always +// check for these error conditions. + +import ( + "bytes" + "encoding" + "encoding/binary" + "errors" + "fmt" + "math" + "reflect" + "sort" + "strings" + "sync" + "time" +) + +const ( + scratchByteArrayLen = 32 + initCollectionCap = 32 // 32 is defensive. 16 is preferred. + + // Support encoding.(Binary|Text)(Unm|M)arshaler. + // This constant flag will enable or disable it. + supportMarshalInterfaces = true + + // Each Encoder or Decoder uses a cache of functions based on conditionals, + // so that the conditionals are not run every time. + // + // Either a map or a slice is used to keep track of the functions. + // The map is more natural, but has a higher cost than a slice/array. + // This flag (useMapForCodecCache) controls which is used. + // + // From benchmarks, slices with linear search perform better with < 32 entries. + // We have typically seen a high threshold of about 24 entries. + useMapForCodecCache = false + + // for debugging, set this to false, to catch panic traces. + // Note that this will always cause rpc tests to fail, since they need io.EOF sent via panic. + recoverPanicToErr = true + + // Fast path functions try to create a fast path encode or decode implementation + // for common maps and slices, by by-passing reflection altogether. + fastpathEnabled = true + + // if checkStructForEmptyValue, check structs fields to see if an empty value. + // This could be an expensive call, so possibly disable it. + checkStructForEmptyValue = false + + // if derefForIsEmptyValue, deref pointers and interfaces when checking isEmptyValue + derefForIsEmptyValue = false + + // if resetSliceElemToZeroValue, then on decoding a slice, reset the element to a zero value first. + // Only concern is that, if the slice already contained some garbage, we will decode into that garbage. + // The chances of this are slim, so leave this "optimization". + // TODO: should this be true, to ensure that we always decode into a "zero" "empty" value? + resetSliceElemToZeroValue bool = false +) + +var ( + oneByteArr = [1]byte{0} + zeroByteSlice = oneByteArr[:0:0] +) + +type charEncoding uint8 + +const ( + c_RAW charEncoding = iota + c_UTF8 + c_UTF16LE + c_UTF16BE + c_UTF32LE + c_UTF32BE +) + +// valueType is the stream type +type valueType uint8 + +const ( + valueTypeUnset valueType = iota + valueTypeNil + valueTypeInt + valueTypeUint + valueTypeFloat + valueTypeBool + valueTypeString + valueTypeSymbol + valueTypeBytes + valueTypeMap + valueTypeArray + valueTypeTimestamp + valueTypeExt + + // valueTypeInvalid = 0xff +) + +type seqType uint8 + +const ( + _ seqType = iota + seqTypeArray + seqTypeSlice + seqTypeChan +) + +// note that containerMapStart and containerArraySend are not sent. +// This is because the ReadXXXStart and EncodeXXXStart already does these. +type containerState uint8 + +const ( + _ containerState = iota + + containerMapStart // slot left open, since Driver method already covers it + containerMapKey + containerMapValue + containerMapEnd + containerArrayStart // slot left open, since Driver methods already cover it + containerArrayElem + containerArrayEnd +) + +type rgetPoolT struct { + encNames [8]string + fNames [8]string + etypes [8]uintptr + sfis [8]*structFieldInfo +} + +var rgetPool = sync.Pool{ + New: func() interface{} { return new(rgetPoolT) }, +} + +type rgetT struct { + fNames []string + encNames []string + etypes []uintptr + sfis []*structFieldInfo +} + +type containerStateRecv interface { + sendContainerState(containerState) +} + +// mirror json.Marshaler and json.Unmarshaler here, +// so we don't import the encoding/json package +type jsonMarshaler interface { + MarshalJSON() ([]byte, error) +} +type jsonUnmarshaler interface { + UnmarshalJSON([]byte) error +} + +var ( + bigen = binary.BigEndian + structInfoFieldName = "_struct" + + mapStrIntfTyp = reflect.TypeOf(map[string]interface{}(nil)) + mapIntfIntfTyp = reflect.TypeOf(map[interface{}]interface{}(nil)) + intfSliceTyp = reflect.TypeOf([]interface{}(nil)) + intfTyp = intfSliceTyp.Elem() + + stringTyp = reflect.TypeOf("") + timeTyp = reflect.TypeOf(time.Time{}) + rawExtTyp = reflect.TypeOf(RawExt{}) + uint8SliceTyp = reflect.TypeOf([]uint8(nil)) + + mapBySliceTyp = reflect.TypeOf((*MapBySlice)(nil)).Elem() + + binaryMarshalerTyp = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem() + binaryUnmarshalerTyp = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem() + + textMarshalerTyp = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + textUnmarshalerTyp = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + + jsonMarshalerTyp = reflect.TypeOf((*jsonMarshaler)(nil)).Elem() + jsonUnmarshalerTyp = reflect.TypeOf((*jsonUnmarshaler)(nil)).Elem() + + selferTyp = reflect.TypeOf((*Selfer)(nil)).Elem() + + uint8SliceTypId = reflect.ValueOf(uint8SliceTyp).Pointer() + rawExtTypId = reflect.ValueOf(rawExtTyp).Pointer() + intfTypId = reflect.ValueOf(intfTyp).Pointer() + timeTypId = reflect.ValueOf(timeTyp).Pointer() + stringTypId = reflect.ValueOf(stringTyp).Pointer() + + mapStrIntfTypId = reflect.ValueOf(mapStrIntfTyp).Pointer() + mapIntfIntfTypId = reflect.ValueOf(mapIntfIntfTyp).Pointer() + intfSliceTypId = reflect.ValueOf(intfSliceTyp).Pointer() + // mapBySliceTypId = reflect.ValueOf(mapBySliceTyp).Pointer() + + intBitsize uint8 = uint8(reflect.TypeOf(int(0)).Bits()) + uintBitsize uint8 = uint8(reflect.TypeOf(uint(0)).Bits()) + + bsAll0x00 = []byte{0, 0, 0, 0, 0, 0, 0, 0} + bsAll0xff = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + + chkOvf checkOverflow + + noFieldNameToStructFieldInfoErr = errors.New("no field name passed to parseStructFieldInfo") +) + +var defTypeInfos = NewTypeInfos([]string{"codec", "json"}) + +// Selfer defines methods by which a value can encode or decode itself. +// +// Any type which implements Selfer will be able to encode or decode itself. +// Consequently, during (en|de)code, this takes precedence over +// (text|binary)(M|Unm)arshal or extension support. +type Selfer interface { + CodecEncodeSelf(*Encoder) + CodecDecodeSelf(*Decoder) +} + +// MapBySlice represents a slice which should be encoded as a map in the stream. +// The slice contains a sequence of key-value pairs. +// This affords storing a map in a specific sequence in the stream. +// +// The support of MapBySlice affords the following: +// - A slice type which implements MapBySlice will be encoded as a map +// - A slice can be decoded from a map in the stream +type MapBySlice interface { + MapBySlice() +} + +// WARNING: DO NOT USE DIRECTLY. EXPORTED FOR GODOC BENEFIT. WILL BE REMOVED. +// +// BasicHandle encapsulates the common options and extension functions. +type BasicHandle struct { + // TypeInfos is used to get the type info for any type. + // + // If not configured, the default TypeInfos is used, which uses struct tag keys: codec, json + TypeInfos *TypeInfos + + extHandle + EncodeOptions + DecodeOptions +} + +func (x *BasicHandle) getBasicHandle() *BasicHandle { + return x +} + +func (x *BasicHandle) getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) { + if x.TypeInfos != nil { + return x.TypeInfos.get(rtid, rt) + } + return defTypeInfos.get(rtid, rt) +} + +// Handle is the interface for a specific encoding format. +// +// Typically, a Handle is pre-configured before first time use, +// and not modified while in use. Such a pre-configured Handle +// is safe for concurrent access. +type Handle interface { + getBasicHandle() *BasicHandle + newEncDriver(w *Encoder) encDriver + newDecDriver(r *Decoder) decDriver + isBinary() bool +} + +// RawExt represents raw unprocessed extension data. +// Some codecs will decode extension data as a *RawExt if there is no registered extension for the tag. +// +// Only one of Data or Value is nil. If Data is nil, then the content of the RawExt is in the Value. +type RawExt struct { + Tag uint64 + // Data is the []byte which represents the raw ext. If Data is nil, ext is exposed in Value. + // Data is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types + Data []byte + // Value represents the extension, if Data is nil. + // Value is used by codecs (e.g. cbor) which use the format to do custom serialization of the types. + Value interface{} +} + +// BytesExt handles custom (de)serialization of types to/from []byte. +// It is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types. +type BytesExt interface { + // WriteExt converts a value to a []byte. + // + // Note: v *may* be a pointer to the extension type, if the extension type was a struct or array. + WriteExt(v interface{}) []byte + + // ReadExt updates a value from a []byte. + ReadExt(dst interface{}, src []byte) +} + +// InterfaceExt handles custom (de)serialization of types to/from another interface{} value. +// The Encoder or Decoder will then handle the further (de)serialization of that known type. +// +// It is used by codecs (e.g. cbor, json) which use the format to do custom serialization of the types. +type InterfaceExt interface { + // ConvertExt converts a value into a simpler interface for easy encoding e.g. convert time.Time to int64. + // + // Note: v *may* be a pointer to the extension type, if the extension type was a struct or array. + ConvertExt(v interface{}) interface{} + + // UpdateExt updates a value from a simpler interface for easy decoding e.g. convert int64 to time.Time. + UpdateExt(dst interface{}, src interface{}) +} + +// Ext handles custom (de)serialization of custom types / extensions. +type Ext interface { + BytesExt + InterfaceExt +} + +// addExtWrapper is a wrapper implementation to support former AddExt exported method. +type addExtWrapper struct { + encFn func(reflect.Value) ([]byte, error) + decFn func(reflect.Value, []byte) error +} + +func (x addExtWrapper) WriteExt(v interface{}) []byte { + bs, err := x.encFn(reflect.ValueOf(v)) + if err != nil { + panic(err) + } + return bs +} + +func (x addExtWrapper) ReadExt(v interface{}, bs []byte) { + if err := x.decFn(reflect.ValueOf(v), bs); err != nil { + panic(err) + } +} + +func (x addExtWrapper) ConvertExt(v interface{}) interface{} { + return x.WriteExt(v) +} + +func (x addExtWrapper) UpdateExt(dest interface{}, v interface{}) { + x.ReadExt(dest, v.([]byte)) +} + +type setExtWrapper struct { + b BytesExt + i InterfaceExt +} + +func (x *setExtWrapper) WriteExt(v interface{}) []byte { + if x.b == nil { + panic("BytesExt.WriteExt is not supported") + } + return x.b.WriteExt(v) +} + +func (x *setExtWrapper) ReadExt(v interface{}, bs []byte) { + if x.b == nil { + panic("BytesExt.WriteExt is not supported") + + } + x.b.ReadExt(v, bs) +} + +func (x *setExtWrapper) ConvertExt(v interface{}) interface{} { + if x.i == nil { + panic("InterfaceExt.ConvertExt is not supported") + + } + return x.i.ConvertExt(v) +} + +func (x *setExtWrapper) UpdateExt(dest interface{}, v interface{}) { + if x.i == nil { + panic("InterfaceExxt.UpdateExt is not supported") + + } + x.i.UpdateExt(dest, v) +} + +// type errorString string +// func (x errorString) Error() string { return string(x) } + +type binaryEncodingType struct{} + +func (_ binaryEncodingType) isBinary() bool { return true } + +type textEncodingType struct{} + +func (_ textEncodingType) isBinary() bool { return false } + +// noBuiltInTypes is embedded into many types which do not support builtins +// e.g. msgpack, simple, cbor. +type noBuiltInTypes struct{} + +func (_ noBuiltInTypes) IsBuiltinType(rt uintptr) bool { return false } +func (_ noBuiltInTypes) EncodeBuiltin(rt uintptr, v interface{}) {} +func (_ noBuiltInTypes) DecodeBuiltin(rt uintptr, v interface{}) {} + +type noStreamingCodec struct{} + +func (_ noStreamingCodec) CheckBreak() bool { return false } + +// bigenHelper. +// Users must already slice the x completely, because we will not reslice. +type bigenHelper struct { + x []byte // must be correctly sliced to appropriate len. slicing is a cost. + w encWriter +} + +func (z bigenHelper) writeUint16(v uint16) { + bigen.PutUint16(z.x, v) + z.w.writeb(z.x) +} + +func (z bigenHelper) writeUint32(v uint32) { + bigen.PutUint32(z.x, v) + z.w.writeb(z.x) +} + +func (z bigenHelper) writeUint64(v uint64) { + bigen.PutUint64(z.x, v) + z.w.writeb(z.x) +} + +type extTypeTagFn struct { + rtid uintptr + rt reflect.Type + tag uint64 + ext Ext +} + +type extHandle []extTypeTagFn + +// DEPRECATED: Use SetBytesExt or SetInterfaceExt on the Handle instead. +// +// AddExt registes an encode and decode function for a reflect.Type. +// AddExt internally calls SetExt. +// To deregister an Ext, call AddExt with nil encfn and/or nil decfn. +func (o *extHandle) AddExt( + rt reflect.Type, tag byte, + encfn func(reflect.Value) ([]byte, error), decfn func(reflect.Value, []byte) error, +) (err error) { + if encfn == nil || decfn == nil { + return o.SetExt(rt, uint64(tag), nil) + } + return o.SetExt(rt, uint64(tag), addExtWrapper{encfn, decfn}) +} + +// DEPRECATED: Use SetBytesExt or SetInterfaceExt on the Handle instead. +// +// Note that the type must be a named type, and specifically not +// a pointer or Interface. An error is returned if that is not honored. +// +// To Deregister an ext, call SetExt with nil Ext +func (o *extHandle) SetExt(rt reflect.Type, tag uint64, ext Ext) (err error) { + // o is a pointer, because we may need to initialize it + if rt.PkgPath() == "" || rt.Kind() == reflect.Interface { + err = fmt.Errorf("codec.Handle.AddExt: Takes named type, especially not a pointer or interface: %T", + reflect.Zero(rt).Interface()) + return + } + + rtid := reflect.ValueOf(rt).Pointer() + for _, v := range *o { + if v.rtid == rtid { + v.tag, v.ext = tag, ext + return + } + } + + if *o == nil { + *o = make([]extTypeTagFn, 0, 4) + } + *o = append(*o, extTypeTagFn{rtid, rt, tag, ext}) + return +} + +func (o extHandle) getExt(rtid uintptr) *extTypeTagFn { + var v *extTypeTagFn + for i := range o { + v = &o[i] + if v.rtid == rtid { + return v + } + } + return nil +} + +func (o extHandle) getExtForTag(tag uint64) *extTypeTagFn { + var v *extTypeTagFn + for i := range o { + v = &o[i] + if v.tag == tag { + return v + } + } + return nil +} + +type structFieldInfo struct { + encName string // encode name + + // only one of 'i' or 'is' can be set. If 'i' is -1, then 'is' has been set. + + is []int // (recursive/embedded) field index in struct + i int16 // field index in struct + omitEmpty bool + toArray bool // if field is _struct, is the toArray set? +} + +// func (si *structFieldInfo) isZero() bool { +// return si.encName == "" && len(si.is) == 0 && si.i == 0 && !si.omitEmpty && !si.toArray +// } + +// rv returns the field of the struct. +// If anonymous, it returns an Invalid +func (si *structFieldInfo) field(v reflect.Value, update bool) (rv2 reflect.Value) { + if si.i != -1 { + v = v.Field(int(si.i)) + return v + } + // replicate FieldByIndex + for _, x := range si.is { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + if !update { + return + } + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + v = v.Field(x) + } + return v +} + +func (si *structFieldInfo) setToZeroValue(v reflect.Value) { + if si.i != -1 { + v = v.Field(int(si.i)) + v.Set(reflect.Zero(v.Type())) + // v.Set(reflect.New(v.Type()).Elem()) + // v.Set(reflect.New(v.Type())) + } else { + // replicate FieldByIndex + for _, x := range si.is { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + return + } + v = v.Elem() + } + v = v.Field(x) + } + v.Set(reflect.Zero(v.Type())) + } +} + +func parseStructFieldInfo(fname string, stag string) *structFieldInfo { + // if fname == "" { + // panic(noFieldNameToStructFieldInfoErr) + // } + si := structFieldInfo{ + encName: fname, + } + + if stag != "" { + for i, s := range strings.Split(stag, ",") { + if i == 0 { + if s != "" { + si.encName = s + } + } else { + if s == "omitempty" { + si.omitEmpty = true + } else if s == "toarray" { + si.toArray = true + } + } + } + } + // si.encNameBs = []byte(si.encName) + return &si +} + +type sfiSortedByEncName []*structFieldInfo + +func (p sfiSortedByEncName) Len() int { + return len(p) +} + +func (p sfiSortedByEncName) Less(i, j int) bool { + return p[i].encName < p[j].encName +} + +func (p sfiSortedByEncName) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +// typeInfo keeps information about each type referenced in the encode/decode sequence. +// +// During an encode/decode sequence, we work as below: +// - If base is a built in type, en/decode base value +// - If base is registered as an extension, en/decode base value +// - If type is binary(M/Unm)arshaler, call Binary(M/Unm)arshal method +// - If type is text(M/Unm)arshaler, call Text(M/Unm)arshal method +// - Else decode appropriately based on the reflect.Kind +type typeInfo struct { + sfi []*structFieldInfo // sorted. Used when enc/dec struct to map. + sfip []*structFieldInfo // unsorted. Used when enc/dec struct to array. + + rt reflect.Type + rtid uintptr + + numMeth uint16 // number of methods + + // baseId gives pointer to the base reflect.Type, after deferencing + // the pointers. E.g. base type of ***time.Time is time.Time. + base reflect.Type + baseId uintptr + baseIndir int8 // number of indirections to get to base + + mbs bool // base type (T or *T) is a MapBySlice + + bm bool // base type (T or *T) is a binaryMarshaler + bunm bool // base type (T or *T) is a binaryUnmarshaler + bmIndir int8 // number of indirections to get to binaryMarshaler type + bunmIndir int8 // number of indirections to get to binaryUnmarshaler type + + tm bool // base type (T or *T) is a textMarshaler + tunm bool // base type (T or *T) is a textUnmarshaler + tmIndir int8 // number of indirections to get to textMarshaler type + tunmIndir int8 // number of indirections to get to textUnmarshaler type + + jm bool // base type (T or *T) is a jsonMarshaler + junm bool // base type (T or *T) is a jsonUnmarshaler + jmIndir int8 // number of indirections to get to jsonMarshaler type + junmIndir int8 // number of indirections to get to jsonUnmarshaler type + + cs bool // base type (T or *T) is a Selfer + csIndir int8 // number of indirections to get to Selfer type + + toArray bool // whether this (struct) type should be encoded as an array +} + +func (ti *typeInfo) indexForEncName(name string) int { + //tisfi := ti.sfi + const binarySearchThreshold = 16 + if sfilen := len(ti.sfi); sfilen < binarySearchThreshold { + // linear search. faster than binary search in my testing up to 16-field structs. + for i, si := range ti.sfi { + if si.encName == name { + return i + } + } + } else { + // binary search. adapted from sort/search.go. + h, i, j := 0, 0, sfilen + for i < j { + h = i + (j-i)/2 + if ti.sfi[h].encName < name { + i = h + 1 + } else { + j = h + } + } + if i < sfilen && ti.sfi[i].encName == name { + return i + } + } + return -1 +} + +// TypeInfos caches typeInfo for each type on first inspection. +// +// It is configured with a set of tag keys, which are used to get +// configuration for the type. +type TypeInfos struct { + infos map[uintptr]*typeInfo + mu sync.RWMutex + tags []string +} + +// NewTypeInfos creates a TypeInfos given a set of struct tags keys. +// +// This allows users customize the struct tag keys which contain configuration +// of their types. +func NewTypeInfos(tags []string) *TypeInfos { + return &TypeInfos{tags: tags, infos: make(map[uintptr]*typeInfo, 64)} +} + +func (x *TypeInfos) structTag(t reflect.StructTag) (s string) { + // check for tags: codec, json, in that order. + // this allows seamless support for many configured structs. + for _, x := range x.tags { + s = t.Get(x) + if s != "" { + return s + } + } + return +} + +func (x *TypeInfos) get(rtid uintptr, rt reflect.Type) (pti *typeInfo) { + var ok bool + x.mu.RLock() + pti, ok = x.infos[rtid] + x.mu.RUnlock() + if ok { + return + } + + // do not hold lock while computing this. + // it may lead to duplication, but that's ok. + ti := typeInfo{rt: rt, rtid: rtid} + ti.numMeth = uint16(rt.NumMethod()) + + var indir int8 + if ok, indir = implementsIntf(rt, binaryMarshalerTyp); ok { + ti.bm, ti.bmIndir = true, indir + } + if ok, indir = implementsIntf(rt, binaryUnmarshalerTyp); ok { + ti.bunm, ti.bunmIndir = true, indir + } + if ok, indir = implementsIntf(rt, textMarshalerTyp); ok { + ti.tm, ti.tmIndir = true, indir + } + if ok, indir = implementsIntf(rt, textUnmarshalerTyp); ok { + ti.tunm, ti.tunmIndir = true, indir + } + if ok, indir = implementsIntf(rt, jsonMarshalerTyp); ok { + ti.jm, ti.jmIndir = true, indir + } + if ok, indir = implementsIntf(rt, jsonUnmarshalerTyp); ok { + ti.junm, ti.junmIndir = true, indir + } + if ok, indir = implementsIntf(rt, selferTyp); ok { + ti.cs, ti.csIndir = true, indir + } + if ok, _ = implementsIntf(rt, mapBySliceTyp); ok { + ti.mbs = true + } + + pt := rt + var ptIndir int8 + // for ; pt.Kind() == reflect.Ptr; pt, ptIndir = pt.Elem(), ptIndir+1 { } + for pt.Kind() == reflect.Ptr { + pt = pt.Elem() + ptIndir++ + } + if ptIndir == 0 { + ti.base = rt + ti.baseId = rtid + } else { + ti.base = pt + ti.baseId = reflect.ValueOf(pt).Pointer() + ti.baseIndir = ptIndir + } + + if rt.Kind() == reflect.Struct { + var siInfo *structFieldInfo + if f, ok := rt.FieldByName(structInfoFieldName); ok { + siInfo = parseStructFieldInfo(structInfoFieldName, x.structTag(f.Tag)) + ti.toArray = siInfo.toArray + } + pi := rgetPool.Get() + pv := pi.(*rgetPoolT) + pv.etypes[0] = ti.baseId + vv := rgetT{pv.fNames[:0], pv.encNames[:0], pv.etypes[:1], pv.sfis[:0]} + x.rget(rt, rtid, nil, &vv, siInfo) + ti.sfip = make([]*structFieldInfo, len(vv.sfis)) + ti.sfi = make([]*structFieldInfo, len(vv.sfis)) + copy(ti.sfip, vv.sfis) + sort.Sort(sfiSortedByEncName(vv.sfis)) + copy(ti.sfi, vv.sfis) + rgetPool.Put(pi) + } + // sfi = sfip + + x.mu.Lock() + if pti, ok = x.infos[rtid]; !ok { + pti = &ti + x.infos[rtid] = pti + } + x.mu.Unlock() + return +} + +func (x *TypeInfos) rget(rt reflect.Type, rtid uintptr, + indexstack []int, pv *rgetT, siInfo *structFieldInfo, +) { + // This will read up the fields and store how to access the value. + // It uses the go language's rules for embedding, as below: + // - if a field has been seen while traversing, skip it + // - if an encName has been seen while traversing, skip it + // - if an embedded type has been seen, skip it + // + // Also, per Go's rules, embedded fields must be analyzed AFTER all top-level fields. + // + // Note: we consciously use slices, not a map, to simulate a set. + // Typically, types have < 16 fields, and iteration using equals is faster than maps there + + type anonField struct { + ft reflect.Type + idx int + } + + var anonFields []anonField + +LOOP: + for j, jlen := 0, rt.NumField(); j < jlen; j++ { + f := rt.Field(j) + fkind := f.Type.Kind() + // skip if a func type, or is unexported, or structTag value == "-" + switch fkind { + case reflect.Func, reflect.Complex64, reflect.Complex128, reflect.UnsafePointer: + continue LOOP + } + + // if r1, _ := utf8.DecodeRuneInString(f.Name); r1 == utf8.RuneError || !unicode.IsUpper(r1) { + if f.PkgPath != "" && !f.Anonymous { // unexported, not embedded + continue + } + stag := x.structTag(f.Tag) + if stag == "-" { + continue + } + var si *structFieldInfo + // if anonymous and no struct tag (or it's blank), and a struct (or pointer to struct), inline it. + if f.Anonymous && fkind != reflect.Interface { + doInline := stag == "" + if !doInline { + si = parseStructFieldInfo("", stag) + doInline = si.encName == "" + // doInline = si.isZero() + } + if doInline { + ft := f.Type + for ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + if ft.Kind() == reflect.Struct { + // handle anonymous fields after handling all the non-anon fields + anonFields = append(anonFields, anonField{ft, j}) + continue + } + } + } + + // after the anonymous dance: if an unexported field, skip + if f.PkgPath != "" { // unexported + continue + } + + if f.Name == "" { + panic(noFieldNameToStructFieldInfoErr) + } + + for _, k := range pv.fNames { + if k == f.Name { + continue LOOP + } + } + pv.fNames = append(pv.fNames, f.Name) + + if si == nil { + si = parseStructFieldInfo(f.Name, stag) + } else if si.encName == "" { + si.encName = f.Name + } + + for _, k := range pv.encNames { + if k == si.encName { + continue LOOP + } + } + pv.encNames = append(pv.encNames, si.encName) + + // si.ikind = int(f.Type.Kind()) + if len(indexstack) == 0 { + si.i = int16(j) + } else { + si.i = -1 + si.is = make([]int, len(indexstack)+1) + copy(si.is, indexstack) + si.is[len(indexstack)] = j + // si.is = append(append(make([]int, 0, len(indexstack)+4), indexstack...), j) + } + + if siInfo != nil { + if siInfo.omitEmpty { + si.omitEmpty = true + } + } + pv.sfis = append(pv.sfis, si) + } + + // now handle anonymous fields +LOOP2: + for _, af := range anonFields { + // if etypes contains this, then do not call rget again (as the fields are already seen here) + ftid := reflect.ValueOf(af.ft).Pointer() + for _, k := range pv.etypes { + if k == ftid { + continue LOOP2 + } + } + pv.etypes = append(pv.etypes, ftid) + + indexstack2 := make([]int, len(indexstack)+1) + copy(indexstack2, indexstack) + indexstack2[len(indexstack)] = af.idx + // indexstack2 := append(append(make([]int, 0, len(indexstack)+4), indexstack...), j) + x.rget(af.ft, ftid, indexstack2, pv, siInfo) + } +} + +func panicToErr(err *error) { + if recoverPanicToErr { + if x := recover(); x != nil { + //debug.PrintStack() + panicValToErr(x, err) + } + } +} + +// func doPanic(tag string, format string, params ...interface{}) { +// params2 := make([]interface{}, len(params)+1) +// params2[0] = tag +// copy(params2[1:], params) +// panic(fmt.Errorf("%s: "+format, params2...)) +// } + +func isImmutableKind(k reflect.Kind) (v bool) { + return false || + k == reflect.Int || + k == reflect.Int8 || + k == reflect.Int16 || + k == reflect.Int32 || + k == reflect.Int64 || + k == reflect.Uint || + k == reflect.Uint8 || + k == reflect.Uint16 || + k == reflect.Uint32 || + k == reflect.Uint64 || + k == reflect.Uintptr || + k == reflect.Float32 || + k == reflect.Float64 || + k == reflect.Bool || + k == reflect.String +} + +// these functions must be inlinable, and not call anybody +type checkOverflow struct{} + +func (_ checkOverflow) Float32(f float64) (overflow bool) { + if f < 0 { + f = -f + } + return math.MaxFloat32 < f && f <= math.MaxFloat64 +} + +func (_ checkOverflow) Uint(v uint64, bitsize uint8) (overflow bool) { + if bitsize == 0 || bitsize >= 64 || v == 0 { + return + } + if trunc := (v << (64 - bitsize)) >> (64 - bitsize); v != trunc { + overflow = true + } + return +} + +func (_ checkOverflow) Int(v int64, bitsize uint8) (overflow bool) { + if bitsize == 0 || bitsize >= 64 || v == 0 { + return + } + if trunc := (v << (64 - bitsize)) >> (64 - bitsize); v != trunc { + overflow = true + } + return +} + +func (_ checkOverflow) SignedInt(v uint64) (i int64, overflow bool) { + //e.g. -127 to 128 for int8 + pos := (v >> 63) == 0 + ui2 := v & 0x7fffffffffffffff + if pos { + if ui2 > math.MaxInt64 { + overflow = true + return + } + } else { + if ui2 > math.MaxInt64-1 { + overflow = true + return + } + } + i = int64(v) + return +} + +// ------------------ SORT ----------------- + +func isNaN(f float64) bool { return f != f } + +// ----------------------- + +type intSlice []int64 +type uintSlice []uint64 +type floatSlice []float64 +type boolSlice []bool +type stringSlice []string +type bytesSlice [][]byte + +func (p intSlice) Len() int { return len(p) } +func (p intSlice) Less(i, j int) bool { return p[i] < p[j] } +func (p intSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p uintSlice) Len() int { return len(p) } +func (p uintSlice) Less(i, j int) bool { return p[i] < p[j] } +func (p uintSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p floatSlice) Len() int { return len(p) } +func (p floatSlice) Less(i, j int) bool { + return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) +} +func (p floatSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p stringSlice) Len() int { return len(p) } +func (p stringSlice) Less(i, j int) bool { return p[i] < p[j] } +func (p stringSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p bytesSlice) Len() int { return len(p) } +func (p bytesSlice) Less(i, j int) bool { return bytes.Compare(p[i], p[j]) == -1 } +func (p bytesSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p boolSlice) Len() int { return len(p) } +func (p boolSlice) Less(i, j int) bool { return !p[i] && p[j] } +func (p boolSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// --------------------- + +type intRv struct { + v int64 + r reflect.Value +} +type intRvSlice []intRv +type uintRv struct { + v uint64 + r reflect.Value +} +type uintRvSlice []uintRv +type floatRv struct { + v float64 + r reflect.Value +} +type floatRvSlice []floatRv +type boolRv struct { + v bool + r reflect.Value +} +type boolRvSlice []boolRv +type stringRv struct { + v string + r reflect.Value +} +type stringRvSlice []stringRv +type bytesRv struct { + v []byte + r reflect.Value +} +type bytesRvSlice []bytesRv + +func (p intRvSlice) Len() int { return len(p) } +func (p intRvSlice) Less(i, j int) bool { return p[i].v < p[j].v } +func (p intRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p uintRvSlice) Len() int { return len(p) } +func (p uintRvSlice) Less(i, j int) bool { return p[i].v < p[j].v } +func (p uintRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p floatRvSlice) Len() int { return len(p) } +func (p floatRvSlice) Less(i, j int) bool { + return p[i].v < p[j].v || isNaN(p[i].v) && !isNaN(p[j].v) +} +func (p floatRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p stringRvSlice) Len() int { return len(p) } +func (p stringRvSlice) Less(i, j int) bool { return p[i].v < p[j].v } +func (p stringRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p bytesRvSlice) Len() int { return len(p) } +func (p bytesRvSlice) Less(i, j int) bool { return bytes.Compare(p[i].v, p[j].v) == -1 } +func (p bytesRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p boolRvSlice) Len() int { return len(p) } +func (p boolRvSlice) Less(i, j int) bool { return !p[i].v && p[j].v } +func (p boolRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// ----------------- + +type bytesI struct { + v []byte + i interface{} +} + +type bytesISlice []bytesI + +func (p bytesISlice) Len() int { return len(p) } +func (p bytesISlice) Less(i, j int) bool { return bytes.Compare(p[i].v, p[j].v) == -1 } +func (p bytesISlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// ----------------- + +type set []uintptr + +func (s *set) add(v uintptr) (exists bool) { + // e.ci is always nil, or len >= 1 + // defer func() { fmt.Printf("$$$$$$$$$$$ cirRef Add: %v, exists: %v\n", v, exists) }() + x := *s + if x == nil { + x = make([]uintptr, 1, 8) + x[0] = v + *s = x + return + } + // typically, length will be 1. make this perform. + if len(x) == 1 { + if j := x[0]; j == 0 { + x[0] = v + } else if j == v { + exists = true + } else { + x = append(x, v) + *s = x + } + return + } + // check if it exists + for _, j := range x { + if j == v { + exists = true + return + } + } + // try to replace a "deleted" slot + for i, j := range x { + if j == 0 { + x[i] = v + return + } + } + // if unable to replace deleted slot, just append it. + x = append(x, v) + *s = x + return +} + +func (s *set) remove(v uintptr) (exists bool) { + // defer func() { fmt.Printf("$$$$$$$$$$$ cirRef Rm: %v, exists: %v\n", v, exists) }() + x := *s + if len(x) == 0 { + return + } + if len(x) == 1 { + if x[0] == v { + x[0] = 0 + } + return + } + for i, j := range x { + if j == v { + exists = true + x[i] = 0 // set it to 0, as way to delete it. + // copy(x[i:], x[i+1:]) + // x = x[:len(x)-1] + return + } + } + return +} diff --git a/vendor/github.com/ugorji/go/codec/helper_internal.go b/vendor/github.com/ugorji/go/codec/helper_internal.go new file mode 100644 index 000000000..dea981fbb --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/helper_internal.go @@ -0,0 +1,242 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +// All non-std package dependencies live in this file, +// so porting to different environment is easy (just update functions). + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +func panicValToErr(panicVal interface{}, err *error) { + if panicVal == nil { + return + } + // case nil + switch xerr := panicVal.(type) { + case error: + *err = xerr + case string: + *err = errors.New(xerr) + default: + *err = fmt.Errorf("%v", panicVal) + } + return +} + +func hIsEmptyValue(v reflect.Value, deref, checkStruct bool) bool { + switch v.Kind() { + case reflect.Invalid: + return true + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + if deref { + if v.IsNil() { + return true + } + return hIsEmptyValue(v.Elem(), deref, checkStruct) + } else { + return v.IsNil() + } + case reflect.Struct: + if !checkStruct { + return false + } + // return true if all fields are empty. else return false. + // we cannot use equality check, because some fields may be maps/slices/etc + // and consequently the structs are not comparable. + // return v.Interface() == reflect.Zero(v.Type()).Interface() + for i, n := 0, v.NumField(); i < n; i++ { + if !hIsEmptyValue(v.Field(i), deref, checkStruct) { + return false + } + } + return true + } + return false +} + +func isEmptyValue(v reflect.Value) bool { + return hIsEmptyValue(v, derefForIsEmptyValue, checkStructForEmptyValue) +} + +func pruneSignExt(v []byte, pos bool) (n int) { + if len(v) < 2 { + } else if pos && v[0] == 0 { + for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ { + } + } else if !pos && v[0] == 0xff { + for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ { + } + } + return +} + +func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) { + if typ == nil { + return + } + rt := typ + // The type might be a pointer and we need to keep + // dereferencing to the base type until we find an implementation. + for { + if rt.Implements(iTyp) { + return true, indir + } + if p := rt; p.Kind() == reflect.Ptr { + indir++ + if indir >= math.MaxInt8 { // insane number of indirections + return false, 0 + } + rt = p.Elem() + continue + } + break + } + // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. + if typ.Kind() != reflect.Ptr { + // Not a pointer, but does the pointer work? + if reflect.PtrTo(typ).Implements(iTyp) { + return true, -1 + } + } + return false, 0 +} + +// validate that this function is correct ... +// culled from OGRE (Object-Oriented Graphics Rendering Engine) +// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html) +func halfFloatToFloatBits(yy uint16) (d uint32) { + y := uint32(yy) + s := (y >> 15) & 0x01 + e := (y >> 10) & 0x1f + m := y & 0x03ff + + if e == 0 { + if m == 0 { // plu or minus 0 + return s << 31 + } else { // Denormalized number -- renormalize it + for (m & 0x00000400) == 0 { + m <<= 1 + e -= 1 + } + e += 1 + const zz uint32 = 0x0400 + m &= ^zz + } + } else if e == 31 { + if m == 0 { // Inf + return (s << 31) | 0x7f800000 + } else { // NaN + return (s << 31) | 0x7f800000 | (m << 13) + } + } + e = e + (127 - 15) + m = m << 13 + return (s << 31) | (e << 23) | m +} + +// GrowCap will return a new capacity for a slice, given the following: +// - oldCap: current capacity +// - unit: in-memory size of an element +// - num: number of elements to add +func growCap(oldCap, unit, num int) (newCap int) { + // appendslice logic (if cap < 1024, *2, else *1.25): + // leads to many copy calls, especially when copying bytes. + // bytes.Buffer model (2*cap + n): much better for bytes. + // smarter way is to take the byte-size of the appended element(type) into account + + // maintain 3 thresholds: + // t1: if cap <= t1, newcap = 2x + // t2: if cap <= t2, newcap = 1.75x + // t3: if cap <= t3, newcap = 1.5x + // else newcap = 1.25x + // + // t1, t2, t3 >= 1024 always. + // i.e. if unit size >= 16, then always do 2x or 1.25x (ie t1, t2, t3 are all same) + // + // With this, appending for bytes increase by: + // 100% up to 4K + // 75% up to 8K + // 50% up to 16K + // 25% beyond that + + // unit can be 0 e.g. for struct{}{}; handle that appropriately + var t1, t2, t3 int // thresholds + if unit <= 1 { + t1, t2, t3 = 4*1024, 8*1024, 16*1024 + } else if unit < 16 { + t3 = 16 / unit * 1024 + t1 = t3 * 1 / 4 + t2 = t3 * 2 / 4 + } else { + t1, t2, t3 = 1024, 1024, 1024 + } + + var x int // temporary variable + + // x is multiplier here: one of 5, 6, 7 or 8; incr of 25%, 50%, 75% or 100% respectively + if oldCap <= t1 { // [0,t1] + x = 8 + } else if oldCap > t3 { // (t3,infinity] + x = 5 + } else if oldCap <= t2 { // (t1,t2] + x = 7 + } else { // (t2,t3] + x = 6 + } + newCap = x * oldCap / 4 + + if num > 0 { + newCap += num + } + + // ensure newCap is a multiple of 64 (if it is > 64) or 16. + if newCap > 64 { + if x = newCap % 64; x != 0 { + x = newCap / 64 + newCap = 64 * (x + 1) + } + } else { + if x = newCap % 16; x != 0 { + x = newCap / 16 + newCap = 16 * (x + 1) + } + } + return +} + +func expandSliceValue(s reflect.Value, num int) reflect.Value { + if num <= 0 { + return s + } + l0 := s.Len() + l1 := l0 + num // new slice length + if l1 < l0 { + panic("ExpandSlice: slice overflow") + } + c0 := s.Cap() + if l1 <= c0 { + return s.Slice(0, l1) + } + st := s.Type() + c1 := growCap(c0, int(st.Elem().Size()), num) + s2 := reflect.MakeSlice(st, l1, c1) + // println("expandslicevalue: cap-old: ", c0, ", cap-new: ", c1, ", len-new: ", l1) + reflect.Copy(s2, s) + return s2 +} diff --git a/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go b/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go new file mode 100644 index 000000000..7c2ffc0fd --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go @@ -0,0 +1,20 @@ +//+build !unsafe + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +// stringView returns a view of the []byte as a string. +// In unsafe mode, it doesn't incur allocation and copying caused by conversion. +// In regular safe mode, it is an allocation and copy. +func stringView(v []byte) string { + return string(v) +} + +// bytesView returns a view of the string as a []byte. +// In unsafe mode, it doesn't incur allocation and copying caused by conversion. +// In regular safe mode, it is an allocation and copy. +func bytesView(v string) []byte { + return []byte(v) +} diff --git a/vendor/github.com/ugorji/go/codec/helper_unsafe.go b/vendor/github.com/ugorji/go/codec/helper_unsafe.go new file mode 100644 index 000000000..373b2b102 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/helper_unsafe.go @@ -0,0 +1,45 @@ +//+build unsafe + +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "unsafe" +) + +// This file has unsafe variants of some helper methods. + +type unsafeString struct { + Data uintptr + Len int +} + +type unsafeBytes struct { + Data uintptr + Len int + Cap int +} + +// stringView returns a view of the []byte as a string. +// In unsafe mode, it doesn't incur allocation and copying caused by conversion. +// In regular safe mode, it is an allocation and copy. +func stringView(v []byte) string { + if len(v) == 0 { + return "" + } + x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)} + return *(*string)(unsafe.Pointer(&x)) +} + +// bytesView returns a view of the string as a []byte. +// In unsafe mode, it doesn't incur allocation and copying caused by conversion. +// In regular safe mode, it is an allocation and copy. +func bytesView(v string) []byte { + if len(v) == 0 { + return zeroByteSlice + } + x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)} + return *(*[]byte)(unsafe.Pointer(&x)) +} diff --git a/vendor/github.com/ugorji/go/codec/json.go b/vendor/github.com/ugorji/go/codec/json.go new file mode 100644 index 000000000..a04dfcb9d --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/json.go @@ -0,0 +1,1213 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +// By default, this json support uses base64 encoding for bytes, because you cannot +// store and read any arbitrary string in json (only unicode). +// However, the user can configre how to encode/decode bytes. +// +// This library specifically supports UTF-8 for encoding and decoding only. +// +// Note that the library will happily encode/decode things which are not valid +// json e.g. a map[int64]string. We do it for consistency. With valid json, +// we will encode and decode appropriately. +// Users can specify their map type if necessary to force it. +// +// Note: +// - we cannot use strconv.Quote and strconv.Unquote because json quotes/unquotes differently. +// We implement it here. +// - Also, strconv.ParseXXX for floats and integers +// - only works on strings resulting in unnecessary allocation and []byte-string conversion. +// - it does a lot of redundant checks, because json numbers are simpler that what it supports. +// - We parse numbers (floats and integers) directly here. +// We only delegate parsing floats if it is a hairy float which could cause a loss of precision. +// In that case, we delegate to strconv.ParseFloat. +// +// Note: +// - encode does not beautify. There is no whitespace when encoding. +// - rpc calls which take single integer arguments or write single numeric arguments will need care. + +// Top-level methods of json(End|Dec)Driver (which are implementations of (en|de)cDriver +// MUST not call one-another. + +import ( + "bytes" + "encoding/base64" + "fmt" + "reflect" + "strconv" + "unicode/utf16" + "unicode/utf8" +) + +//-------------------------------- + +var ( + jsonLiterals = [...]byte{'t', 'r', 'u', 'e', 'f', 'a', 'l', 's', 'e', 'n', 'u', 'l', 'l'} + + jsonFloat64Pow10 = [...]float64{ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, + } + + jsonUint64Pow10 = [...]uint64{ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + } + + // jsonTabs and jsonSpaces are used as caches for indents + jsonTabs, jsonSpaces string +) + +const ( + // jsonUnreadAfterDecNum controls whether we unread after decoding a number. + // + // instead of unreading, just update d.tok (iff it's not a whitespace char) + // However, doing this means that we may HOLD onto some data which belongs to another stream. + // Thus, it is safest to unread the data when done. + // keep behind a constant flag for now. + jsonUnreadAfterDecNum = true + + // If !jsonValidateSymbols, decoding will be faster, by skipping some checks: + // - If we see first character of null, false or true, + // do not validate subsequent characters. + // - e.g. if we see a n, assume null and skip next 3 characters, + // and do not validate they are ull. + // P.S. Do not expect a significant decoding boost from this. + jsonValidateSymbols = true + + // if jsonTruncateMantissa, truncate mantissa if trailing 0's. + // This is important because it could allow some floats to be decoded without + // deferring to strconv.ParseFloat. + jsonTruncateMantissa = true + + // if mantissa >= jsonNumUintCutoff before multiplying by 10, this is an overflow + jsonNumUintCutoff = (1<<64-1)/uint64(10) + 1 // cutoff64(base) + + // if mantissa >= jsonNumUintMaxVal, this is an overflow + jsonNumUintMaxVal = 1< 1<<53 || v < -(1<<53)) { + e.w.writen1('"') + e.w.writeb(strconv.AppendInt(e.b[:0], v, 10)) + e.w.writen1('"') + return + } + e.w.writeb(strconv.AppendInt(e.b[:0], v, 10)) +} + +func (e *jsonEncDriver) EncodeUint(v uint64) { + if x := e.h.IntegerAsString; x == 'A' || x == 'L' && v > 1<<53 { + e.w.writen1('"') + e.w.writeb(strconv.AppendUint(e.b[:0], v, 10)) + e.w.writen1('"') + return + } + e.w.writeb(strconv.AppendUint(e.b[:0], v, 10)) +} + +func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) { + if v := ext.ConvertExt(rv); v == nil { + e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil() + } else { + en.encode(v) + } +} + +func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) { + // only encodes re.Value (never re.Data) + if re.Value == nil { + e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil() + } else { + en.encode(re.Value) + } +} + +func (e *jsonEncDriver) EncodeArrayStart(length int) { + if e.d { + e.dl++ + } + e.w.writen1('[') + e.c = containerArrayStart +} + +func (e *jsonEncDriver) EncodeMapStart(length int) { + if e.d { + e.dl++ + } + e.w.writen1('{') + e.c = containerMapStart +} + +func (e *jsonEncDriver) EncodeString(c charEncoding, v string) { + // e.w.writestr(strconv.Quote(v)) + e.quoteStr(v) +} + +func (e *jsonEncDriver) EncodeSymbol(v string) { + // e.EncodeString(c_UTF8, v) + e.quoteStr(v) +} + +func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) { + // if encoding raw bytes and RawBytesExt is configured, use it to encode + if c == c_RAW && e.se.i != nil { + e.EncodeExt(v, 0, &e.se, e.e) + return + } + if c == c_RAW { + slen := base64.StdEncoding.EncodedLen(len(v)) + if cap(e.bs) >= slen { + e.bs = e.bs[:slen] + } else { + e.bs = make([]byte, slen) + } + base64.StdEncoding.Encode(e.bs, v) + e.w.writen1('"') + e.w.writeb(e.bs) + e.w.writen1('"') + } else { + // e.EncodeString(c, string(v)) + e.quoteStr(stringView(v)) + } +} + +func (e *jsonEncDriver) EncodeAsis(v []byte) { + e.w.writeb(v) +} + +func (e *jsonEncDriver) quoteStr(s string) { + // adapted from std pkg encoding/json + const hex = "0123456789abcdef" + w := e.w + w.writen1('"') + start := 0 + for i := 0; i < len(s); { + if b := s[i]; b < utf8.RuneSelf { + if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { + i++ + continue + } + if start < i { + w.writestr(s[start:i]) + } + switch b { + case '\\', '"': + w.writen2('\\', b) + case '\n': + w.writen2('\\', 'n') + case '\r': + w.writen2('\\', 'r') + case '\b': + w.writen2('\\', 'b') + case '\f': + w.writen2('\\', 'f') + case '\t': + w.writen2('\\', 't') + default: + // encode all bytes < 0x20 (except \r, \n). + // also encode < > & to prevent security holes when served to some browsers. + w.writestr(`\u00`) + w.writen2(hex[b>>4], hex[b&0xF]) + } + i++ + start = i + continue + } + c, size := utf8.DecodeRuneInString(s[i:]) + if c == utf8.RuneError && size == 1 { + if start < i { + w.writestr(s[start:i]) + } + w.writestr(`\ufffd`) + i += size + start = i + continue + } + // U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR. + // Both technically valid JSON, but bomb on JSONP, so fix here. + if c == '\u2028' || c == '\u2029' { + if start < i { + w.writestr(s[start:i]) + } + w.writestr(`\u202`) + w.writen1(hex[c&0xF]) + i += size + start = i + continue + } + i += size + } + if start < len(s) { + w.writestr(s[start:]) + } + w.writen1('"') +} + +//-------------------------------- + +type jsonNum struct { + // bytes []byte // may have [+-.eE0-9] + mantissa uint64 // where mantissa ends, and maybe dot begins. + exponent int16 // exponent value. + manOverflow bool + neg bool // started with -. No initial sign in the bytes above. + dot bool // has dot + explicitExponent bool // explicit exponent +} + +func (x *jsonNum) reset() { + x.manOverflow = false + x.neg = false + x.dot = false + x.explicitExponent = false + x.mantissa = 0 + x.exponent = 0 +} + +// uintExp is called only if exponent > 0. +func (x *jsonNum) uintExp() (n uint64, overflow bool) { + n = x.mantissa + e := x.exponent + if e >= int16(len(jsonUint64Pow10)) { + overflow = true + return + } + n *= jsonUint64Pow10[e] + if n < x.mantissa || n > jsonNumUintMaxVal { + overflow = true + return + } + return + // for i := int16(0); i < e; i++ { + // if n >= jsonNumUintCutoff { + // overflow = true + // return + // } + // n *= 10 + // } + // return +} + +// these constants are only used withn floatVal. +// They are brought out, so that floatVal can be inlined. +const ( + jsonUint64MantissaBits = 52 + jsonMaxExponent = int16(len(jsonFloat64Pow10)) - 1 +) + +func (x *jsonNum) floatVal() (f float64, parseUsingStrConv bool) { + // We do not want to lose precision. + // Consequently, we will delegate to strconv.ParseFloat if any of the following happen: + // - There are more digits than in math.MaxUint64: 18446744073709551615 (20 digits) + // We expect up to 99.... (19 digits) + // - The mantissa cannot fit into a 52 bits of uint64 + // - The exponent is beyond our scope ie beyong 22. + parseUsingStrConv = x.manOverflow || + x.exponent > jsonMaxExponent || + (x.exponent < 0 && -(x.exponent) > jsonMaxExponent) || + x.mantissa>>jsonUint64MantissaBits != 0 + + if parseUsingStrConv { + return + } + + // all good. so handle parse here. + f = float64(x.mantissa) + // fmt.Printf(".Float: uint64 value: %v, float: %v\n", m, f) + if x.neg { + f = -f + } + if x.exponent > 0 { + f *= jsonFloat64Pow10[x.exponent] + } else if x.exponent < 0 { + f /= jsonFloat64Pow10[-x.exponent] + } + return +} + +type jsonDecDriver struct { + noBuiltInTypes + d *Decoder + h *JsonHandle + r decReader + + c containerState + // tok is used to store the token read right after skipWhiteSpace. + tok uint8 + + bstr [8]byte // scratch used for string \UXXX parsing + b [64]byte // scratch, used for parsing strings or numbers + b2 [64]byte // scratch, used only for decodeBytes (after base64) + bs []byte // scratch. Initialized from b. Used for parsing strings or numbers. + + se setExtWrapper + + n jsonNum +} + +func jsonIsWS(b byte) bool { + return b == ' ' || b == '\t' || b == '\r' || b == '\n' +} + +// // This will skip whitespace characters and return the next byte to read. +// // The next byte determines what the value will be one of. +// func (d *jsonDecDriver) skipWhitespace() { +// // fast-path: do not enter loop. Just check first (in case no whitespace). +// b := d.r.readn1() +// if jsonIsWS(b) { +// r := d.r +// for b = r.readn1(); jsonIsWS(b); b = r.readn1() { +// } +// } +// d.tok = b +// } + +func (d *jsonDecDriver) uncacheRead() { + if d.tok != 0 { + d.r.unreadn1() + d.tok = 0 + } +} + +func (d *jsonDecDriver) sendContainerState(c containerState) { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + var xc uint8 // char expected + if c == containerMapKey { + if d.c != containerMapStart { + xc = ',' + } + } else if c == containerMapValue { + xc = ':' + } else if c == containerMapEnd { + xc = '}' + } else if c == containerArrayElem { + if d.c != containerArrayStart { + xc = ',' + } + } else if c == containerArrayEnd { + xc = ']' + } + if xc != 0 { + if d.tok != xc { + d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok) + } + d.tok = 0 + } + d.c = c +} + +func (d *jsonDecDriver) CheckBreak() bool { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok == '}' || d.tok == ']' { + // d.tok = 0 // only checking, not consuming + return true + } + return false +} + +func (d *jsonDecDriver) readStrIdx(fromIdx, toIdx uint8) { + bs := d.r.readx(int(toIdx - fromIdx)) + d.tok = 0 + if jsonValidateSymbols { + if !bytes.Equal(bs, jsonLiterals[fromIdx:toIdx]) { + d.d.errorf("json: expecting %s: got %s", jsonLiterals[fromIdx:toIdx], bs) + return + } + } +} + +func (d *jsonDecDriver) TryDecodeAsNil() bool { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok == 'n' { + d.readStrIdx(10, 13) // ull + return true + } + return false +} + +func (d *jsonDecDriver) DecodeBool() bool { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok == 'f' { + d.readStrIdx(5, 9) // alse + return false + } + if d.tok == 't' { + d.readStrIdx(1, 4) // rue + return true + } + d.d.errorf("json: decode bool: got first char %c", d.tok) + return false // "unreachable" +} + +func (d *jsonDecDriver) ReadMapStart() int { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok != '{' { + d.d.errorf("json: expect char '%c' but got char '%c'", '{', d.tok) + } + d.tok = 0 + d.c = containerMapStart + return -1 +} + +func (d *jsonDecDriver) ReadArrayStart() int { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok != '[' { + d.d.errorf("json: expect char '%c' but got char '%c'", '[', d.tok) + } + d.tok = 0 + d.c = containerArrayStart + return -1 +} + +func (d *jsonDecDriver) ContainerType() (vt valueType) { + // check container type by checking the first char + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if b := d.tok; b == '{' { + return valueTypeMap + } else if b == '[' { + return valueTypeArray + } else if b == 'n' { + return valueTypeNil + } else if b == '"' { + return valueTypeString + } + return valueTypeUnset + // d.d.errorf("isContainerType: unsupported parameter: %v", vt) + // return false // "unreachable" +} + +func (d *jsonDecDriver) decNum(storeBytes bool) { + // If it is has a . or an e|E, decode as a float; else decode as an int. + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + b := d.tok + var str bool + if b == '"' { + str = true + b = d.r.readn1() + } + if !(b == '+' || b == '-' || b == '.' || (b >= '0' && b <= '9')) { + d.d.errorf("json: decNum: got first char '%c'", b) + return + } + d.tok = 0 + + const cutoff = (1<<64-1)/uint64(10) + 1 // cutoff64(base) + const jsonNumUintMaxVal = 1<= jsonNumUintCutoff { + n.manOverflow = true + break + } + v := uint64(b - '0') + n.mantissa *= 10 + if v != 0 { + n1 := n.mantissa + v + if n1 < n.mantissa || n1 > jsonNumUintMaxVal { + n.manOverflow = true // n+v overflows + break + } + n.mantissa = n1 + } + case 6: + state = 7 + fallthrough + case 7: + if !(b == '0' && e == 0) { + e = e*10 + int16(b-'0') + } + default: + break LOOP + } + case '"': + if str { + if storeBytes { + d.bs = append(d.bs, '"') + } + b, eof = r.readn1eof() + } + break LOOP + default: + break LOOP + } + if storeBytes { + d.bs = append(d.bs, b) + } + b, eof = r.readn1eof() + } + + if jsonTruncateMantissa && n.mantissa != 0 { + for n.mantissa%10 == 0 { + n.mantissa /= 10 + n.exponent++ + } + } + + if e != 0 { + if eNeg { + n.exponent -= e + } else { + n.exponent += e + } + } + + // d.n = n + + if !eof { + if jsonUnreadAfterDecNum { + r.unreadn1() + } else { + if !jsonIsWS(b) { + d.tok = b + } + } + } + // fmt.Printf("1: n: bytes: %s, neg: %v, dot: %v, exponent: %v, mantissaEndIndex: %v\n", + // n.bytes, n.neg, n.dot, n.exponent, n.mantissaEndIndex) + return +} + +func (d *jsonDecDriver) DecodeInt(bitsize uint8) (i int64) { + d.decNum(false) + n := &d.n + if n.manOverflow { + d.d.errorf("json: overflow integer after: %v", n.mantissa) + return + } + var u uint64 + if n.exponent == 0 { + u = n.mantissa + } else if n.exponent < 0 { + d.d.errorf("json: fractional integer") + return + } else if n.exponent > 0 { + var overflow bool + if u, overflow = n.uintExp(); overflow { + d.d.errorf("json: overflow integer") + return + } + } + i = int64(u) + if n.neg { + i = -i + } + if chkOvf.Int(i, bitsize) { + d.d.errorf("json: overflow %v bits: %s", bitsize, d.bs) + return + } + // fmt.Printf("DecodeInt: %v\n", i) + return +} + +// floatVal MUST only be called after a decNum, as d.bs now contains the bytes of the number +func (d *jsonDecDriver) floatVal() (f float64) { + f, useStrConv := d.n.floatVal() + if useStrConv { + var err error + if f, err = strconv.ParseFloat(stringView(d.bs), 64); err != nil { + panic(fmt.Errorf("parse float: %s, %v", d.bs, err)) + } + if d.n.neg { + f = -f + } + } + return +} + +func (d *jsonDecDriver) DecodeUint(bitsize uint8) (u uint64) { + d.decNum(false) + n := &d.n + if n.neg { + d.d.errorf("json: unsigned integer cannot be negative") + return + } + if n.manOverflow { + d.d.errorf("json: overflow integer after: %v", n.mantissa) + return + } + if n.exponent == 0 { + u = n.mantissa + } else if n.exponent < 0 { + d.d.errorf("json: fractional integer") + return + } else if n.exponent > 0 { + var overflow bool + if u, overflow = n.uintExp(); overflow { + d.d.errorf("json: overflow integer") + return + } + } + if chkOvf.Uint(u, bitsize) { + d.d.errorf("json: overflow %v bits: %s", bitsize, d.bs) + return + } + // fmt.Printf("DecodeUint: %v\n", u) + return +} + +func (d *jsonDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) { + d.decNum(true) + f = d.floatVal() + if chkOverflow32 && chkOvf.Float32(f) { + d.d.errorf("json: overflow float32: %v, %s", f, d.bs) + return + } + return +} + +func (d *jsonDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { + if ext == nil { + re := rv.(*RawExt) + re.Tag = xtag + d.d.decode(&re.Value) + } else { + var v interface{} + d.d.decode(&v) + ext.UpdateExt(rv, v) + } + return +} + +func (d *jsonDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) { + // if decoding into raw bytes, and the RawBytesExt is configured, use it to decode. + if !isstring && d.se.i != nil { + bsOut = bs + d.DecodeExt(&bsOut, 0, &d.se) + return + } + d.appendStringAsBytes() + // if isstring, then just return the bytes, even if it is using the scratch buffer. + // the bytes will be converted to a string as needed. + if isstring { + return d.bs + } + bs0 := d.bs + slen := base64.StdEncoding.DecodedLen(len(bs0)) + if slen <= cap(bs) { + bsOut = bs[:slen] + } else if zerocopy && slen <= cap(d.b2) { + bsOut = d.b2[:slen] + } else { + bsOut = make([]byte, slen) + } + slen2, err := base64.StdEncoding.Decode(bsOut, bs0) + if err != nil { + d.d.errorf("json: error decoding base64 binary '%s': %v", bs0, err) + return nil + } + if slen != slen2 { + bsOut = bsOut[:slen2] + } + return +} + +func (d *jsonDecDriver) DecodeString() (s string) { + d.appendStringAsBytes() + // if x := d.s.sc; x != nil && x.so && x.st == '}' { // map key + if d.c == containerMapKey { + return d.d.string(d.bs) + } + return string(d.bs) +} + +func (d *jsonDecDriver) appendStringAsBytes() { + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + if d.tok != '"' { + d.d.errorf("json: expect char '%c' but got char '%c'", '"', d.tok) + } + d.tok = 0 + + v := d.bs[:0] + var c uint8 + r := d.r + for { + c = r.readn1() + if c == '"' { + break + } else if c == '\\' { + c = r.readn1() + switch c { + case '"', '\\', '/', '\'': + v = append(v, c) + case 'b': + v = append(v, '\b') + case 'f': + v = append(v, '\f') + case 'n': + v = append(v, '\n') + case 'r': + v = append(v, '\r') + case 't': + v = append(v, '\t') + case 'u': + rr := d.jsonU4(false) + // fmt.Printf("$$$$$$$$$: is surrogate: %v\n", utf16.IsSurrogate(rr)) + if utf16.IsSurrogate(rr) { + rr = utf16.DecodeRune(rr, d.jsonU4(true)) + } + w2 := utf8.EncodeRune(d.bstr[:], rr) + v = append(v, d.bstr[:w2]...) + default: + d.d.errorf("json: unsupported escaped value: %c", c) + } + } else { + v = append(v, c) + } + } + d.bs = v +} + +func (d *jsonDecDriver) jsonU4(checkSlashU bool) rune { + r := d.r + if checkSlashU && !(r.readn1() == '\\' && r.readn1() == 'u') { + d.d.errorf(`json: unquoteStr: invalid unicode sequence. Expecting \u`) + return 0 + } + // u, _ := strconv.ParseUint(string(d.bstr[:4]), 16, 64) + var u uint32 + for i := 0; i < 4; i++ { + v := r.readn1() + if '0' <= v && v <= '9' { + v = v - '0' + } else if 'a' <= v && v <= 'z' { + v = v - 'a' + 10 + } else if 'A' <= v && v <= 'Z' { + v = v - 'A' + 10 + } else { + d.d.errorf(`json: unquoteStr: invalid hex char in \u unicode sequence: %q`, v) + return 0 + } + u = u*16 + uint32(v) + } + return rune(u) +} + +func (d *jsonDecDriver) DecodeNaked() { + z := &d.d.n + // var decodeFurther bool + + if d.tok == 0 { + var b byte + r := d.r + for b = r.readn1(); jsonIsWS(b); b = r.readn1() { + } + d.tok = b + } + switch d.tok { + case 'n': + d.readStrIdx(10, 13) // ull + z.v = valueTypeNil + case 'f': + d.readStrIdx(5, 9) // alse + z.v = valueTypeBool + z.b = false + case 't': + d.readStrIdx(1, 4) // rue + z.v = valueTypeBool + z.b = true + case '{': + z.v = valueTypeMap + // d.tok = 0 // don't consume. kInterfaceNaked will call ReadMapStart + // decodeFurther = true + case '[': + z.v = valueTypeArray + // d.tok = 0 // don't consume. kInterfaceNaked will call ReadArrayStart + // decodeFurther = true + case '"': + z.v = valueTypeString + z.s = d.DecodeString() + default: // number + d.decNum(true) + n := &d.n + // if the string had a any of [.eE], then decode as float. + switch { + case n.explicitExponent, n.dot, n.exponent < 0, n.manOverflow: + z.v = valueTypeFloat + z.f = d.floatVal() + case n.exponent == 0: + u := n.mantissa + switch { + case n.neg: + z.v = valueTypeInt + z.i = -int64(u) + case d.h.SignedInteger: + z.v = valueTypeInt + z.i = int64(u) + default: + z.v = valueTypeUint + z.u = u + } + default: + u, overflow := n.uintExp() + switch { + case overflow: + z.v = valueTypeFloat + z.f = d.floatVal() + case n.neg: + z.v = valueTypeInt + z.i = -int64(u) + case d.h.SignedInteger: + z.v = valueTypeInt + z.i = int64(u) + default: + z.v = valueTypeUint + z.u = u + } + } + // fmt.Printf("DecodeNaked: Number: %T, %v\n", v, v) + } + // if decodeFurther { + // d.s.sc.retryRead() + // } + return +} + +//---------------------- + +// JsonHandle is a handle for JSON encoding format. +// +// Json is comprehensively supported: +// - decodes numbers into interface{} as int, uint or float64 +// - configurable way to encode/decode []byte . +// by default, encodes and decodes []byte using base64 Std Encoding +// - UTF-8 support for encoding and decoding +// +// It has better performance than the json library in the standard library, +// by leveraging the performance improvements of the codec library and +// minimizing allocations. +// +// In addition, it doesn't read more bytes than necessary during a decode, which allows +// reading multiple values from a stream containing json and non-json content. +// For example, a user can read a json value, then a cbor value, then a msgpack value, +// all from the same stream in sequence. +type JsonHandle struct { + textEncodingType + BasicHandle + // RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way. + // If not configured, raw bytes are encoded to/from base64 text. + RawBytesExt InterfaceExt + + // Indent indicates how a value is encoded. + // - If positive, indent by that number of spaces. + // - If negative, indent by that number of tabs. + Indent int8 + + // IntegerAsString controls how integers (signed and unsigned) are encoded. + // + // Per the JSON Spec, JSON numbers are 64-bit floating point numbers. + // Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision. + // This can be mitigated by configuring how to encode integers. + // + // IntegerAsString interpretes the following values: + // - if 'L', then encode integers > 2^53 as a json string. + // - if 'A', then encode all integers as a json string + // containing the exact integer representation as a decimal. + // - else encode all integers as a json number (default) + IntegerAsString uint8 +} + +func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) { + return h.SetExt(rt, tag, &setExtWrapper{i: ext}) +} + +func (h *JsonHandle) newEncDriver(e *Encoder) encDriver { + hd := jsonEncDriver{e: e, h: h} + hd.bs = hd.b[:0] + + hd.reset() + + return &hd +} + +func (h *JsonHandle) newDecDriver(d *Decoder) decDriver { + // d := jsonDecDriver{r: r.(*bytesDecReader), h: h} + hd := jsonDecDriver{d: d, h: h} + hd.bs = hd.b[:0] + hd.reset() + return &hd +} + +func (e *jsonEncDriver) reset() { + e.w = e.e.w + e.se.i = e.h.RawBytesExt + if e.bs != nil { + e.bs = e.bs[:0] + } + e.d, e.dt, e.dl, e.ds = false, false, 0, "" + e.c = 0 + if e.h.Indent > 0 { + e.d = true + e.ds = jsonSpaces[:e.h.Indent] + } else if e.h.Indent < 0 { + e.d = true + e.dt = true + e.ds = jsonTabs[:-(e.h.Indent)] + } +} + +func (d *jsonDecDriver) reset() { + d.r = d.d.r + d.se.i = d.h.RawBytesExt + if d.bs != nil { + d.bs = d.bs[:0] + } + d.c, d.tok = 0, 0 + d.n.reset() +} + +var jsonEncodeTerminate = []byte{' '} + +func (h *JsonHandle) rpcEncodeTerminate() []byte { + return jsonEncodeTerminate +} + +var _ decDriver = (*jsonDecDriver)(nil) +var _ encDriver = (*jsonEncDriver)(nil) diff --git a/vendor/github.com/ugorji/go/codec/msgpack.go b/vendor/github.com/ugorji/go/codec/msgpack.go new file mode 100644 index 000000000..f9f872362 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/msgpack.go @@ -0,0 +1,845 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +/* +MSGPACK + +Msgpack-c implementation powers the c, c++, python, ruby, etc libraries. +We need to maintain compatibility with it and how it encodes integer values +without caring about the type. + +For compatibility with behaviour of msgpack-c reference implementation: + - Go intX (>0) and uintX + IS ENCODED AS + msgpack +ve fixnum, unsigned + - Go intX (<0) + IS ENCODED AS + msgpack -ve fixnum, signed + +*/ +package codec + +import ( + "fmt" + "io" + "math" + "net/rpc" + "reflect" +) + +const ( + mpPosFixNumMin byte = 0x00 + mpPosFixNumMax = 0x7f + mpFixMapMin = 0x80 + mpFixMapMax = 0x8f + mpFixArrayMin = 0x90 + mpFixArrayMax = 0x9f + mpFixStrMin = 0xa0 + mpFixStrMax = 0xbf + mpNil = 0xc0 + _ = 0xc1 + mpFalse = 0xc2 + mpTrue = 0xc3 + mpFloat = 0xca + mpDouble = 0xcb + mpUint8 = 0xcc + mpUint16 = 0xcd + mpUint32 = 0xce + mpUint64 = 0xcf + mpInt8 = 0xd0 + mpInt16 = 0xd1 + mpInt32 = 0xd2 + mpInt64 = 0xd3 + + // extensions below + mpBin8 = 0xc4 + mpBin16 = 0xc5 + mpBin32 = 0xc6 + mpExt8 = 0xc7 + mpExt16 = 0xc8 + mpExt32 = 0xc9 + mpFixExt1 = 0xd4 + mpFixExt2 = 0xd5 + mpFixExt4 = 0xd6 + mpFixExt8 = 0xd7 + mpFixExt16 = 0xd8 + + mpStr8 = 0xd9 // new + mpStr16 = 0xda + mpStr32 = 0xdb + + mpArray16 = 0xdc + mpArray32 = 0xdd + + mpMap16 = 0xde + mpMap32 = 0xdf + + mpNegFixNumMin = 0xe0 + mpNegFixNumMax = 0xff +) + +// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec +// that the backend RPC service takes multiple arguments, which have been arranged +// in sequence in the slice. +// +// The Codec then passes it AS-IS to the rpc service (without wrapping it in an +// array of 1 element). +type MsgpackSpecRpcMultiArgs []interface{} + +// A MsgpackContainer type specifies the different types of msgpackContainers. +type msgpackContainerType struct { + fixCutoff int + bFixMin, b8, b16, b32 byte + hasFixMin, has8, has8Always bool +} + +var ( + msgpackContainerStr = msgpackContainerType{32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false} + msgpackContainerBin = msgpackContainerType{0, 0, mpBin8, mpBin16, mpBin32, false, true, true} + msgpackContainerList = msgpackContainerType{16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false} + msgpackContainerMap = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false} +) + +//--------------------------------------------- + +type msgpackEncDriver struct { + noBuiltInTypes + encNoSeparator + e *Encoder + w encWriter + h *MsgpackHandle + x [8]byte +} + +func (e *msgpackEncDriver) EncodeNil() { + e.w.writen1(mpNil) +} + +func (e *msgpackEncDriver) EncodeInt(i int64) { + if i >= 0 { + e.EncodeUint(uint64(i)) + } else if i >= -32 { + e.w.writen1(byte(i)) + } else if i >= math.MinInt8 { + e.w.writen2(mpInt8, byte(i)) + } else if i >= math.MinInt16 { + e.w.writen1(mpInt16) + bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i)) + } else if i >= math.MinInt32 { + e.w.writen1(mpInt32) + bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i)) + } else { + e.w.writen1(mpInt64) + bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i)) + } +} + +func (e *msgpackEncDriver) EncodeUint(i uint64) { + if i <= math.MaxInt8 { + e.w.writen1(byte(i)) + } else if i <= math.MaxUint8 { + e.w.writen2(mpUint8, byte(i)) + } else if i <= math.MaxUint16 { + e.w.writen1(mpUint16) + bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i)) + } else if i <= math.MaxUint32 { + e.w.writen1(mpUint32) + bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i)) + } else { + e.w.writen1(mpUint64) + bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i)) + } +} + +func (e *msgpackEncDriver) EncodeBool(b bool) { + if b { + e.w.writen1(mpTrue) + } else { + e.w.writen1(mpFalse) + } +} + +func (e *msgpackEncDriver) EncodeFloat32(f float32) { + e.w.writen1(mpFloat) + bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f)) +} + +func (e *msgpackEncDriver) EncodeFloat64(f float64) { + e.w.writen1(mpDouble) + bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f)) +} + +func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) { + bs := ext.WriteExt(v) + if bs == nil { + e.EncodeNil() + return + } + if e.h.WriteExt { + e.encodeExtPreamble(uint8(xtag), len(bs)) + e.w.writeb(bs) + } else { + e.EncodeStringBytes(c_RAW, bs) + } +} + +func (e *msgpackEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) { + e.encodeExtPreamble(uint8(re.Tag), len(re.Data)) + e.w.writeb(re.Data) +} + +func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) { + if l == 1 { + e.w.writen2(mpFixExt1, xtag) + } else if l == 2 { + e.w.writen2(mpFixExt2, xtag) + } else if l == 4 { + e.w.writen2(mpFixExt4, xtag) + } else if l == 8 { + e.w.writen2(mpFixExt8, xtag) + } else if l == 16 { + e.w.writen2(mpFixExt16, xtag) + } else if l < 256 { + e.w.writen2(mpExt8, byte(l)) + e.w.writen1(xtag) + } else if l < 65536 { + e.w.writen1(mpExt16) + bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l)) + e.w.writen1(xtag) + } else { + e.w.writen1(mpExt32) + bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l)) + e.w.writen1(xtag) + } +} + +func (e *msgpackEncDriver) EncodeArrayStart(length int) { + e.writeContainerLen(msgpackContainerList, length) +} + +func (e *msgpackEncDriver) EncodeMapStart(length int) { + e.writeContainerLen(msgpackContainerMap, length) +} + +func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) { + if c == c_RAW && e.h.WriteExt { + e.writeContainerLen(msgpackContainerBin, len(s)) + } else { + e.writeContainerLen(msgpackContainerStr, len(s)) + } + if len(s) > 0 { + e.w.writestr(s) + } +} + +func (e *msgpackEncDriver) EncodeSymbol(v string) { + e.EncodeString(c_UTF8, v) +} + +func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) { + if c == c_RAW && e.h.WriteExt { + e.writeContainerLen(msgpackContainerBin, len(bs)) + } else { + e.writeContainerLen(msgpackContainerStr, len(bs)) + } + if len(bs) > 0 { + e.w.writeb(bs) + } +} + +func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) { + if ct.hasFixMin && l < ct.fixCutoff { + e.w.writen1(ct.bFixMin | byte(l)) + } else if ct.has8 && l < 256 && (ct.has8Always || e.h.WriteExt) { + e.w.writen2(ct.b8, uint8(l)) + } else if l < 65536 { + e.w.writen1(ct.b16) + bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l)) + } else { + e.w.writen1(ct.b32) + bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l)) + } +} + +//--------------------------------------------- + +type msgpackDecDriver struct { + d *Decoder + r decReader // *Decoder decReader decReaderT + h *MsgpackHandle + b [scratchByteArrayLen]byte + bd byte + bdRead bool + br bool // bytes reader + noBuiltInTypes + noStreamingCodec + decNoSeparator +} + +// Note: This returns either a primitive (int, bool, etc) for non-containers, +// or a containerType, or a specific type denoting nil or extension. +// It is called when a nil interface{} is passed, leaving it up to the DecDriver +// to introspect the stream and decide how best to decode. +// It deciphers the value by looking at the stream first. +func (d *msgpackDecDriver) DecodeNaked() { + if !d.bdRead { + d.readNextBd() + } + bd := d.bd + n := &d.d.n + var decodeFurther bool + + switch bd { + case mpNil: + n.v = valueTypeNil + d.bdRead = false + case mpFalse: + n.v = valueTypeBool + n.b = false + case mpTrue: + n.v = valueTypeBool + n.b = true + + case mpFloat: + n.v = valueTypeFloat + n.f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4)))) + case mpDouble: + n.v = valueTypeFloat + n.f = math.Float64frombits(bigen.Uint64(d.r.readx(8))) + + case mpUint8: + n.v = valueTypeUint + n.u = uint64(d.r.readn1()) + case mpUint16: + n.v = valueTypeUint + n.u = uint64(bigen.Uint16(d.r.readx(2))) + case mpUint32: + n.v = valueTypeUint + n.u = uint64(bigen.Uint32(d.r.readx(4))) + case mpUint64: + n.v = valueTypeUint + n.u = uint64(bigen.Uint64(d.r.readx(8))) + + case mpInt8: + n.v = valueTypeInt + n.i = int64(int8(d.r.readn1())) + case mpInt16: + n.v = valueTypeInt + n.i = int64(int16(bigen.Uint16(d.r.readx(2)))) + case mpInt32: + n.v = valueTypeInt + n.i = int64(int32(bigen.Uint32(d.r.readx(4)))) + case mpInt64: + n.v = valueTypeInt + n.i = int64(int64(bigen.Uint64(d.r.readx(8)))) + + default: + switch { + case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax: + // positive fixnum (always signed) + n.v = valueTypeInt + n.i = int64(int8(bd)) + case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax: + // negative fixnum + n.v = valueTypeInt + n.i = int64(int8(bd)) + case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax: + if d.h.RawToString { + n.v = valueTypeString + n.s = d.DecodeString() + } else { + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + } + case bd == mpBin8, bd == mpBin16, bd == mpBin32: + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax: + n.v = valueTypeArray + decodeFurther = true + case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax: + n.v = valueTypeMap + decodeFurther = true + case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32: + n.v = valueTypeExt + clen := d.readExtLen() + n.u = uint64(d.r.readn1()) + n.l = d.r.readx(clen) + default: + d.d.errorf("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) + } + } + if !decodeFurther { + d.bdRead = false + } + if n.v == valueTypeUint && d.h.SignedInteger { + n.v = valueTypeInt + n.i = int64(n.u) + } + return +} + +// int can be decoded from msgpack type: intXXX or uintXXX +func (d *msgpackDecDriver) DecodeInt(bitsize uint8) (i int64) { + if !d.bdRead { + d.readNextBd() + } + switch d.bd { + case mpUint8: + i = int64(uint64(d.r.readn1())) + case mpUint16: + i = int64(uint64(bigen.Uint16(d.r.readx(2)))) + case mpUint32: + i = int64(uint64(bigen.Uint32(d.r.readx(4)))) + case mpUint64: + i = int64(bigen.Uint64(d.r.readx(8))) + case mpInt8: + i = int64(int8(d.r.readn1())) + case mpInt16: + i = int64(int16(bigen.Uint16(d.r.readx(2)))) + case mpInt32: + i = int64(int32(bigen.Uint32(d.r.readx(4)))) + case mpInt64: + i = int64(bigen.Uint64(d.r.readx(8))) + default: + switch { + case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax: + i = int64(int8(d.bd)) + case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax: + i = int64(int8(d.bd)) + default: + d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd) + return + } + } + // check overflow (logic adapted from std pkg reflect/value.go OverflowUint() + if bitsize > 0 { + if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc { + d.d.errorf("Overflow int value: %v", i) + return + } + } + d.bdRead = false + return +} + +// uint can be decoded from msgpack type: intXXX or uintXXX +func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) { + if !d.bdRead { + d.readNextBd() + } + switch d.bd { + case mpUint8: + ui = uint64(d.r.readn1()) + case mpUint16: + ui = uint64(bigen.Uint16(d.r.readx(2))) + case mpUint32: + ui = uint64(bigen.Uint32(d.r.readx(4))) + case mpUint64: + ui = bigen.Uint64(d.r.readx(8)) + case mpInt8: + if i := int64(int8(d.r.readn1())); i >= 0 { + ui = uint64(i) + } else { + d.d.errorf("Assigning negative signed value: %v, to unsigned type", i) + return + } + case mpInt16: + if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 { + ui = uint64(i) + } else { + d.d.errorf("Assigning negative signed value: %v, to unsigned type", i) + return + } + case mpInt32: + if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 { + ui = uint64(i) + } else { + d.d.errorf("Assigning negative signed value: %v, to unsigned type", i) + return + } + case mpInt64: + if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 { + ui = uint64(i) + } else { + d.d.errorf("Assigning negative signed value: %v, to unsigned type", i) + return + } + default: + switch { + case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax: + ui = uint64(d.bd) + case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax: + d.d.errorf("Assigning negative signed value: %v, to unsigned type", int(d.bd)) + return + default: + d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd) + return + } + } + // check overflow (logic adapted from std pkg reflect/value.go OverflowUint() + if bitsize > 0 { + if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc { + d.d.errorf("Overflow uint value: %v", ui) + return + } + } + d.bdRead = false + return +} + +// float can either be decoded from msgpack type: float, double or intX +func (d *msgpackDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == mpFloat { + f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4)))) + } else if d.bd == mpDouble { + f = math.Float64frombits(bigen.Uint64(d.r.readx(8))) + } else { + f = float64(d.DecodeInt(0)) + } + if chkOverflow32 && chkOvf.Float32(f) { + d.d.errorf("msgpack: float32 overflow: %v", f) + return + } + d.bdRead = false + return +} + +// bool can be decoded from bool, fixnum 0 or 1. +func (d *msgpackDecDriver) DecodeBool() (b bool) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == mpFalse || d.bd == 0 { + // b = false + } else if d.bd == mpTrue || d.bd == 1 { + b = true + } else { + d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + return + } + d.bdRead = false + return +} + +func (d *msgpackDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) { + if !d.bdRead { + d.readNextBd() + } + var clen int + // ignore isstring. Expect that the bytes may be found from msgpackContainerStr or msgpackContainerBin + if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 { + clen = d.readContainerLen(msgpackContainerBin) + } else { + clen = d.readContainerLen(msgpackContainerStr) + } + // println("DecodeBytes: clen: ", clen) + d.bdRead = false + // bytes may be nil, so handle it. if nil, clen=-1. + if clen < 0 { + return nil + } + if zerocopy { + if d.br { + return d.r.readx(clen) + } else if len(bs) == 0 { + bs = d.b[:] + } + } + return decByteSlice(d.r, clen, bs) +} + +func (d *msgpackDecDriver) DecodeString() (s string) { + return string(d.DecodeBytes(d.b[:], true, true)) +} + +func (d *msgpackDecDriver) readNextBd() { + d.bd = d.r.readn1() + d.bdRead = true +} + +func (d *msgpackDecDriver) ContainerType() (vt valueType) { + bd := d.bd + if bd == mpNil { + return valueTypeNil + } else if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 || + (!d.h.RawToString && + (bd == mpStr8 || bd == mpStr16 || bd == mpStr32 || (bd >= mpFixStrMin && bd <= mpFixStrMax))) { + return valueTypeBytes + } else if d.h.RawToString && + (bd == mpStr8 || bd == mpStr16 || bd == mpStr32 || (bd >= mpFixStrMin && bd <= mpFixStrMax)) { + return valueTypeString + } else if bd == mpArray16 || bd == mpArray32 || (bd >= mpFixArrayMin && bd <= mpFixArrayMax) { + return valueTypeArray + } else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) { + return valueTypeMap + } else { + // d.d.errorf("isContainerType: unsupported parameter: %v", vt) + } + return valueTypeUnset +} + +func (d *msgpackDecDriver) TryDecodeAsNil() (v bool) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == mpNil { + d.bdRead = false + v = true + } + return +} + +func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int) { + bd := d.bd + if bd == mpNil { + clen = -1 // to represent nil + } else if bd == ct.b8 { + clen = int(d.r.readn1()) + } else if bd == ct.b16 { + clen = int(bigen.Uint16(d.r.readx(2))) + } else if bd == ct.b32 { + clen = int(bigen.Uint32(d.r.readx(4))) + } else if (ct.bFixMin & bd) == ct.bFixMin { + clen = int(ct.bFixMin ^ bd) + } else { + d.d.errorf("readContainerLen: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd) + return + } + d.bdRead = false + return +} + +func (d *msgpackDecDriver) ReadMapStart() int { + return d.readContainerLen(msgpackContainerMap) +} + +func (d *msgpackDecDriver) ReadArrayStart() int { + return d.readContainerLen(msgpackContainerList) +} + +func (d *msgpackDecDriver) readExtLen() (clen int) { + switch d.bd { + case mpNil: + clen = -1 // to represent nil + case mpFixExt1: + clen = 1 + case mpFixExt2: + clen = 2 + case mpFixExt4: + clen = 4 + case mpFixExt8: + clen = 8 + case mpFixExt16: + clen = 16 + case mpExt8: + clen = int(d.r.readn1()) + case mpExt16: + clen = int(bigen.Uint16(d.r.readx(2))) + case mpExt32: + clen = int(bigen.Uint32(d.r.readx(4))) + default: + d.d.errorf("decoding ext bytes: found unexpected byte: %x", d.bd) + return + } + return +} + +func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { + if xtag > 0xff { + d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag) + return + } + realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag)) + realxtag = uint64(realxtag1) + if ext == nil { + re := rv.(*RawExt) + re.Tag = realxtag + re.Data = detachZeroCopyBytes(d.br, re.Data, xbs) + } else { + ext.ReadExt(rv, xbs) + } + return +} + +func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + if !d.bdRead { + d.readNextBd() + } + xbd := d.bd + if xbd == mpBin8 || xbd == mpBin16 || xbd == mpBin32 { + xbs = d.DecodeBytes(nil, false, true) + } else if xbd == mpStr8 || xbd == mpStr16 || xbd == mpStr32 || + (xbd >= mpFixStrMin && xbd <= mpFixStrMax) { + xbs = d.DecodeBytes(nil, true, true) + } else { + clen := d.readExtLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + return + } + xbs = d.r.readx(clen) + } + d.bdRead = false + return +} + +//-------------------------------------------------- + +//MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format. +type MsgpackHandle struct { + BasicHandle + + // RawToString controls how raw bytes are decoded into a nil interface{}. + RawToString bool + + // WriteExt flag supports encoding configured extensions with extension tags. + // It also controls whether other elements of the new spec are encoded (ie Str8). + // + // With WriteExt=false, configured extensions are serialized as raw bytes + // and Str8 is not encoded. + // + // A stream can still be decoded into a typed value, provided an appropriate value + // is provided, but the type cannot be inferred from the stream. If no appropriate + // type is provided (e.g. decoding into a nil interface{}), you get back + // a []byte or string based on the setting of RawToString. + WriteExt bool + binaryEncodingType +} + +func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) { + return h.SetExt(rt, tag, &setExtWrapper{b: ext}) +} + +func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver { + return &msgpackEncDriver{e: e, w: e.w, h: h} +} + +func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver { + return &msgpackDecDriver{d: d, r: d.r, h: h, br: d.bytes} +} + +func (e *msgpackEncDriver) reset() { + e.w = e.e.w +} + +func (d *msgpackDecDriver) reset() { + d.r = d.d.r + d.bd, d.bdRead = 0, false +} + +//-------------------------------------------------- + +type msgpackSpecRpcCodec struct { + rpcCodec +} + +// /////////////// Spec RPC Codec /////////////////// +func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { + // WriteRequest can write to both a Go service, and other services that do + // not abide by the 1 argument rule of a Go service. + // We discriminate based on if the body is a MsgpackSpecRpcMultiArgs + var bodyArr []interface{} + if m, ok := body.(MsgpackSpecRpcMultiArgs); ok { + bodyArr = ([]interface{})(m) + } else { + bodyArr = []interface{}{body} + } + r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr} + return c.write(r2, nil, false, true) +} + +func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { + var moe interface{} + if r.Error != "" { + moe = r.Error + } + if moe != nil && body != nil { + body = nil + } + r2 := []interface{}{1, uint32(r.Seq), moe, body} + return c.write(r2, nil, false, true) +} + +func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error { + return c.parseCustomHeader(1, &r.Seq, &r.Error) +} + +func (c *msgpackSpecRpcCodec) ReadRequestHeader(r *rpc.Request) error { + return c.parseCustomHeader(0, &r.Seq, &r.ServiceMethod) +} + +func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error { + if body == nil { // read and discard + return c.read(nil) + } + bodyArr := []interface{}{body} + return c.read(&bodyArr) +} + +func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) { + + if c.isClosed() { + return io.EOF + } + + // We read the response header by hand + // so that the body can be decoded on its own from the stream at a later time. + + const fia byte = 0x94 //four item array descriptor value + // Not sure why the panic of EOF is swallowed above. + // if bs1 := c.dec.r.readn1(); bs1 != fia { + // err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1) + // return + // } + var b byte + b, err = c.br.ReadByte() + if err != nil { + return + } + if b != fia { + err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b) + return + } + + if err = c.read(&b); err != nil { + return + } + if b != expectTypeByte { + err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b) + return + } + if err = c.read(msgid); err != nil { + return + } + if err = c.read(methodOrError); err != nil { + return + } + return +} + +//-------------------------------------------------- + +// msgpackSpecRpc is the implementation of Rpc that uses custom communication protocol +// as defined in the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md +type msgpackSpecRpc struct{} + +// MsgpackSpecRpc implements Rpc using the communication protocol defined in +// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md . +// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered. +var MsgpackSpecRpc msgpackSpecRpc + +func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec { + return &msgpackSpecRpcCodec{newRPCCodec(conn, h)} +} + +func (x msgpackSpecRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec { + return &msgpackSpecRpcCodec{newRPCCodec(conn, h)} +} + +var _ decDriver = (*msgpackDecDriver)(nil) +var _ encDriver = (*msgpackEncDriver)(nil) diff --git a/vendor/github.com/ugorji/go/codec/noop.go b/vendor/github.com/ugorji/go/codec/noop.go new file mode 100644 index 000000000..cfee3d084 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/noop.go @@ -0,0 +1,213 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "math/rand" + "time" +) + +// NoopHandle returns a no-op handle. It basically does nothing. +// It is only useful for benchmarking, as it gives an idea of the +// overhead from the codec framework. +// +// LIBRARY USERS: *** DO NOT USE *** +func NoopHandle(slen int) *noopHandle { + h := noopHandle{} + h.rand = rand.New(rand.NewSource(time.Now().UnixNano())) + h.B = make([][]byte, slen) + h.S = make([]string, slen) + for i := 0; i < len(h.S); i++ { + b := make([]byte, i+1) + for j := 0; j < len(b); j++ { + b[j] = 'a' + byte(i) + } + h.B[i] = b + h.S[i] = string(b) + } + return &h +} + +// noopHandle does nothing. +// It is used to simulate the overhead of the codec framework. +type noopHandle struct { + BasicHandle + binaryEncodingType + noopDrv // noopDrv is unexported here, so we can get a copy of it when needed. +} + +type noopDrv struct { + d *Decoder + e *Encoder + i int + S []string + B [][]byte + mks []bool // stack. if map (true), else if array (false) + mk bool // top of stack. what container are we on? map or array? + ct valueType // last response for IsContainerType. + cb int // counter for ContainerType + rand *rand.Rand +} + +func (h *noopDrv) r(v int) int { return h.rand.Intn(v) } +func (h *noopDrv) m(v int) int { h.i++; return h.i % v } + +func (h *noopDrv) newEncDriver(e *Encoder) encDriver { h.e = e; return h } +func (h *noopDrv) newDecDriver(d *Decoder) decDriver { h.d = d; return h } + +func (h *noopDrv) reset() {} +func (h *noopDrv) uncacheRead() {} + +// --- encDriver + +// stack functions (for map and array) +func (h *noopDrv) start(b bool) { + // println("start", len(h.mks)+1) + h.mks = append(h.mks, b) + h.mk = b +} +func (h *noopDrv) end() { + // println("end: ", len(h.mks)-1) + h.mks = h.mks[:len(h.mks)-1] + if len(h.mks) > 0 { + h.mk = h.mks[len(h.mks)-1] + } else { + h.mk = false + } +} + +func (h *noopDrv) EncodeBuiltin(rt uintptr, v interface{}) {} +func (h *noopDrv) EncodeNil() {} +func (h *noopDrv) EncodeInt(i int64) {} +func (h *noopDrv) EncodeUint(i uint64) {} +func (h *noopDrv) EncodeBool(b bool) {} +func (h *noopDrv) EncodeFloat32(f float32) {} +func (h *noopDrv) EncodeFloat64(f float64) {} +func (h *noopDrv) EncodeRawExt(re *RawExt, e *Encoder) {} +func (h *noopDrv) EncodeArrayStart(length int) { h.start(true) } +func (h *noopDrv) EncodeMapStart(length int) { h.start(false) } +func (h *noopDrv) EncodeEnd() { h.end() } + +func (h *noopDrv) EncodeString(c charEncoding, v string) {} +func (h *noopDrv) EncodeSymbol(v string) {} +func (h *noopDrv) EncodeStringBytes(c charEncoding, v []byte) {} + +func (h *noopDrv) EncodeExt(rv interface{}, xtag uint64, ext Ext, e *Encoder) {} + +// ---- decDriver +func (h *noopDrv) initReadNext() {} +func (h *noopDrv) CheckBreak() bool { return false } +func (h *noopDrv) IsBuiltinType(rt uintptr) bool { return false } +func (h *noopDrv) DecodeBuiltin(rt uintptr, v interface{}) {} +func (h *noopDrv) DecodeInt(bitsize uint8) (i int64) { return int64(h.m(15)) } +func (h *noopDrv) DecodeUint(bitsize uint8) (ui uint64) { return uint64(h.m(35)) } +func (h *noopDrv) DecodeFloat(chkOverflow32 bool) (f float64) { return float64(h.m(95)) } +func (h *noopDrv) DecodeBool() (b bool) { return h.m(2) == 0 } +func (h *noopDrv) DecodeString() (s string) { return h.S[h.m(8)] } + +// func (h *noopDrv) DecodeStringAsBytes(bs []byte) []byte { return h.DecodeBytes(bs) } + +func (h *noopDrv) DecodeBytes(bs []byte, isstring, zerocopy bool) []byte { return h.B[h.m(len(h.B))] } + +func (h *noopDrv) ReadEnd() { h.end() } + +// toggle map/slice +func (h *noopDrv) ReadMapStart() int { h.start(true); return h.m(10) } +func (h *noopDrv) ReadArrayStart() int { h.start(false); return h.m(10) } + +func (h *noopDrv) ContainerType() (vt valueType) { + // return h.m(2) == 0 + // handle kStruct, which will bomb is it calls this and doesn't get back a map or array. + // consequently, if the return value is not map or array, reset it to one of them based on h.m(7) % 2 + // for kstruct: at least one out of every 2 times, return one of valueTypeMap or Array (else kstruct bombs) + // however, every 10th time it is called, we just return something else. + var vals = [...]valueType{valueTypeArray, valueTypeMap} + // ------------ TAKE ------------ + // if h.cb%2 == 0 { + // if h.ct == valueTypeMap || h.ct == valueTypeArray { + // } else { + // h.ct = vals[h.m(2)] + // } + // } else if h.cb%5 == 0 { + // h.ct = valueType(h.m(8)) + // } else { + // h.ct = vals[h.m(2)] + // } + // ------------ TAKE ------------ + // if h.cb%16 == 0 { + // h.ct = valueType(h.cb % 8) + // } else { + // h.ct = vals[h.cb%2] + // } + h.ct = vals[h.cb%2] + h.cb++ + return h.ct + + // if h.ct == valueTypeNil || h.ct == valueTypeString || h.ct == valueTypeBytes { + // return h.ct + // } + // return valueTypeUnset + // TODO: may need to tweak this so it works. + // if h.ct == valueTypeMap && vt == valueTypeArray || h.ct == valueTypeArray && vt == valueTypeMap { + // h.cb = !h.cb + // h.ct = vt + // return h.cb + // } + // // go in a loop and check it. + // h.ct = vt + // h.cb = h.m(7) == 0 + // return h.cb +} +func (h *noopDrv) TryDecodeAsNil() bool { + if h.mk { + return false + } else { + return h.m(8) == 0 + } +} +func (h *noopDrv) DecodeExt(rv interface{}, xtag uint64, ext Ext) uint64 { + return 0 +} + +func (h *noopDrv) DecodeNaked() { + // use h.r (random) not h.m() because h.m() could cause the same value to be given. + var sk int + if h.mk { + // if mapkey, do not support values of nil OR bytes, array, map or rawext + sk = h.r(7) + 1 + } else { + sk = h.r(12) + } + n := &h.d.n + switch sk { + case 0: + n.v = valueTypeNil + case 1: + n.v, n.b = valueTypeBool, false + case 2: + n.v, n.b = valueTypeBool, true + case 3: + n.v, n.i = valueTypeInt, h.DecodeInt(64) + case 4: + n.v, n.u = valueTypeUint, h.DecodeUint(64) + case 5: + n.v, n.f = valueTypeFloat, h.DecodeFloat(true) + case 6: + n.v, n.f = valueTypeFloat, h.DecodeFloat(false) + case 7: + n.v, n.s = valueTypeString, h.DecodeString() + case 8: + n.v, n.l = valueTypeBytes, h.B[h.m(len(h.B))] + case 9: + n.v = valueTypeArray + case 10: + n.v = valueTypeMap + default: + n.v = valueTypeExt + n.u = h.DecodeUint(64) + n.l = h.B[h.m(len(h.B))] + } + h.ct = n.v + return +} diff --git a/vendor/github.com/ugorji/go/codec/prebuild.go b/vendor/github.com/ugorji/go/codec/prebuild.go new file mode 100644 index 000000000..2353263e8 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/prebuild.go @@ -0,0 +1,3 @@ +package codec + +//go:generate bash prebuild.sh diff --git a/vendor/github.com/ugorji/go/codec/prebuild.sh b/vendor/github.com/ugorji/go/codec/prebuild.sh new file mode 100644 index 000000000..909f4bb0f --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/prebuild.sh @@ -0,0 +1,199 @@ +#!/bin/bash + +# _needgen is a helper function to tell if we need to generate files for msgp, codecgen. +_needgen() { + local a="$1" + zneedgen=0 + if [[ ! -e "$a" ]] + then + zneedgen=1 + echo 1 + return 0 + fi + for i in `ls -1 *.go.tmpl gen.go values_test.go` + do + if [[ "$a" -ot "$i" ]] + then + zneedgen=1 + echo 1 + return 0 + fi + done + echo 0 +} + +# _build generates fast-path.go and gen-helper.go. +# +# It is needed because there is some dependency between the generated code +# and the other classes. Consequently, we have to totally remove the +# generated files and put stubs in place, before calling "go run" again +# to recreate them. +_build() { + if ! [[ "${zforce}" == "1" || + "1" == $( _needgen "fast-path.generated.go" ) || + "1" == $( _needgen "gen-helper.generated.go" ) || + "1" == $( _needgen "gen.generated.go" ) || + 1 == 0 ]] + then + return 0 + fi + + # echo "Running prebuild" + if [ "${zbak}" == "1" ] + then + # echo "Backing up old generated files" + _zts=`date '+%m%d%Y_%H%M%S'` + _gg=".generated.go" + [ -e "gen-helper${_gg}" ] && mv gen-helper${_gg} gen-helper${_gg}__${_zts}.bak + [ -e "fast-path${_gg}" ] && mv fast-path${_gg} fast-path${_gg}__${_zts}.bak + # [ -e "safe${_gg}" ] && mv safe${_gg} safe${_gg}__${_zts}.bak + # [ -e "unsafe${_gg}" ] && mv unsafe${_gg} unsafe${_gg}__${_zts}.bak + else + rm -f fast-path.generated.go gen.generated.go gen-helper.generated.go \ + *safe.generated.go *_generated_test.go *.generated_ffjson_expose.go + fi + + cat > gen.generated.go <> gen.generated.go < gen-dec-map.go.tmpl + + cat >> gen.generated.go <> gen.generated.go < gen-dec-array.go.tmpl + + cat >> gen.generated.go < gen-from-tmpl.codec.generated.go < gen-from-tmpl.generated.go < math.MaxInt64 { + // d.d.errorf("decIntAny: Integer out of range for signed int64: %v", ui) + // return + // } + return +} + +func (d *simpleDecDriver) DecodeInt(bitsize uint8) (i int64) { + ui, neg := d.decCheckInteger() + i, overflow := chkOvf.SignedInt(ui) + if overflow { + d.d.errorf("simple: overflow converting %v to signed integer", ui) + return + } + if neg { + i = -i + } + if chkOvf.Int(i, bitsize) { + d.d.errorf("simple: overflow integer: %v", i) + return + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) DecodeUint(bitsize uint8) (ui uint64) { + ui, neg := d.decCheckInteger() + if neg { + d.d.errorf("Assigning negative signed value to unsigned type") + return + } + if chkOvf.Uint(ui, bitsize) { + d.d.errorf("simple: overflow integer: %v", ui) + return + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == simpleVdFloat32 { + f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4)))) + } else if d.bd == simpleVdFloat64 { + f = math.Float64frombits(bigen.Uint64(d.r.readx(8))) + } else { + if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 { + f = float64(d.DecodeInt(64)) + } else { + d.d.errorf("Float only valid from float32/64: Invalid descriptor: %v", d.bd) + return + } + } + if chkOverflow32 && chkOvf.Float32(f) { + d.d.errorf("msgpack: float32 overflow: %v", f) + return + } + d.bdRead = false + return +} + +// bool can be decoded from bool only (single byte). +func (d *simpleDecDriver) DecodeBool() (b bool) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == simpleVdTrue { + b = true + } else if d.bd == simpleVdFalse { + } else { + d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + return + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) ReadMapStart() (length int) { + d.bdRead = false + return d.decLen() +} + +func (d *simpleDecDriver) ReadArrayStart() (length int) { + d.bdRead = false + return d.decLen() +} + +func (d *simpleDecDriver) decLen() int { + switch d.bd % 8 { + case 0: + return 0 + case 1: + return int(d.r.readn1()) + case 2: + return int(bigen.Uint16(d.r.readx(2))) + case 3: + ui := uint64(bigen.Uint32(d.r.readx(4))) + if chkOvf.Uint(ui, intBitsize) { + d.d.errorf("simple: overflow integer: %v", ui) + return 0 + } + return int(ui) + case 4: + ui := bigen.Uint64(d.r.readx(8)) + if chkOvf.Uint(ui, intBitsize) { + d.d.errorf("simple: overflow integer: %v", ui) + return 0 + } + return int(ui) + } + d.d.errorf("decLen: Cannot read length: bd%8 must be in range 0..4. Got: %d", d.bd%8) + return -1 +} + +func (d *simpleDecDriver) DecodeString() (s string) { + return string(d.DecodeBytes(d.b[:], true, true)) +} + +func (d *simpleDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) { + if !d.bdRead { + d.readNextBd() + } + if d.bd == simpleVdNil { + d.bdRead = false + return + } + clen := d.decLen() + d.bdRead = false + if zerocopy { + if d.br { + return d.r.readx(clen) + } else if len(bs) == 0 { + bs = d.b[:] + } + } + return decByteSlice(d.r, clen, bs) +} + +func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) { + if xtag > 0xff { + d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag) + return + } + realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag)) + realxtag = uint64(realxtag1) + if ext == nil { + re := rv.(*RawExt) + re.Tag = realxtag + re.Data = detachZeroCopyBytes(d.br, re.Data, xbs) + } else { + ext.ReadExt(rv, xbs) + } + return +} + +func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + if !d.bdRead { + d.readNextBd() + } + switch d.bd { + case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4: + l := d.decLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + return + } + xbs = d.r.readx(l) + case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4: + xbs = d.DecodeBytes(nil, false, true) + default: + d.d.errorf("Invalid d.bd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd) + return + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) DecodeNaked() { + if !d.bdRead { + d.readNextBd() + } + + n := &d.d.n + var decodeFurther bool + + switch d.bd { + case simpleVdNil: + n.v = valueTypeNil + case simpleVdFalse: + n.v = valueTypeBool + n.b = false + case simpleVdTrue: + n.v = valueTypeBool + n.b = true + case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3: + if d.h.SignedInteger { + n.v = valueTypeInt + n.i = d.DecodeInt(64) + } else { + n.v = valueTypeUint + n.u = d.DecodeUint(64) + } + case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3: + n.v = valueTypeInt + n.i = d.DecodeInt(64) + case simpleVdFloat32: + n.v = valueTypeFloat + n.f = d.DecodeFloat(true) + case simpleVdFloat64: + n.v = valueTypeFloat + n.f = d.DecodeFloat(false) + case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4: + n.v = valueTypeString + n.s = d.DecodeString() + case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4: + n.v = valueTypeBytes + n.l = d.DecodeBytes(nil, false, false) + case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4: + n.v = valueTypeExt + l := d.decLen() + n.u = uint64(d.r.readn1()) + n.l = d.r.readx(l) + case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4: + n.v = valueTypeArray + decodeFurther = true + case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4: + n.v = valueTypeMap + decodeFurther = true + default: + d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd) + } + + if !decodeFurther { + d.bdRead = false + } + return +} + +//------------------------------------ + +// SimpleHandle is a Handle for a very simple encoding format. +// +// simple is a simplistic codec similar to binc, but not as compact. +// - Encoding of a value is always preceeded by the descriptor byte (bd) +// - True, false, nil are encoded fully in 1 byte (the descriptor) +// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte). +// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers. +// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte) +// - Lenght of containers (strings, bytes, array, map, extensions) +// are encoded in 0, 1, 2, 4 or 8 bytes. +// Zero-length containers have no length encoded. +// For others, the number of bytes is given by pow(2, bd%3) +// - maps are encoded as [bd] [length] [[key][value]]... +// - arrays are encoded as [bd] [length] [value]... +// - extensions are encoded as [bd] [length] [tag] [byte]... +// - strings/bytearrays are encoded as [bd] [length] [byte]... +// +// The full spec will be published soon. +type SimpleHandle struct { + BasicHandle + binaryEncodingType +} + +func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) { + return h.SetExt(rt, tag, &setExtWrapper{b: ext}) +} + +func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver { + return &simpleEncDriver{e: e, w: e.w, h: h} +} + +func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver { + return &simpleDecDriver{d: d, r: d.r, h: h, br: d.bytes} +} + +func (e *simpleEncDriver) reset() { + e.w = e.e.w +} + +func (d *simpleDecDriver) reset() { + d.r = d.d.r + d.bd, d.bdRead = 0, false +} + +var _ decDriver = (*simpleDecDriver)(nil) +var _ encDriver = (*simpleEncDriver)(nil) diff --git a/vendor/github.com/ugorji/go/codec/test-cbor-goldens.json b/vendor/github.com/ugorji/go/codec/test-cbor-goldens.json new file mode 100644 index 000000000..902858671 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/test-cbor-goldens.json @@ -0,0 +1,639 @@ +[ + { + "cbor": "AA==", + "hex": "00", + "roundtrip": true, + "decoded": 0 + }, + { + "cbor": "AQ==", + "hex": "01", + "roundtrip": true, + "decoded": 1 + }, + { + "cbor": "Cg==", + "hex": "0a", + "roundtrip": true, + "decoded": 10 + }, + { + "cbor": "Fw==", + "hex": "17", + "roundtrip": true, + "decoded": 23 + }, + { + "cbor": "GBg=", + "hex": "1818", + "roundtrip": true, + "decoded": 24 + }, + { + "cbor": "GBk=", + "hex": "1819", + "roundtrip": true, + "decoded": 25 + }, + { + "cbor": "GGQ=", + "hex": "1864", + "roundtrip": true, + "decoded": 100 + }, + { + "cbor": "GQPo", + "hex": "1903e8", + "roundtrip": true, + "decoded": 1000 + }, + { + "cbor": "GgAPQkA=", + "hex": "1a000f4240", + "roundtrip": true, + "decoded": 1000000 + }, + { + "cbor": "GwAAAOjUpRAA", + "hex": "1b000000e8d4a51000", + "roundtrip": true, + "decoded": 1000000000000 + }, + { + "cbor": "G///////////", + "hex": "1bffffffffffffffff", + "roundtrip": true, + "decoded": 18446744073709551615 + }, + { + "cbor": "wkkBAAAAAAAAAAA=", + "hex": "c249010000000000000000", + "roundtrip": true, + "decoded": 18446744073709551616 + }, + { + "cbor": "O///////////", + "hex": "3bffffffffffffffff", + "roundtrip": true, + "decoded": -18446744073709551616, + "skip": true + }, + { + "cbor": "w0kBAAAAAAAAAAA=", + "hex": "c349010000000000000000", + "roundtrip": true, + "decoded": -18446744073709551617 + }, + { + "cbor": "IA==", + "hex": "20", + "roundtrip": true, + "decoded": -1 + }, + { + "cbor": "KQ==", + "hex": "29", + "roundtrip": true, + "decoded": -10 + }, + { + "cbor": "OGM=", + "hex": "3863", + "roundtrip": true, + "decoded": -100 + }, + { + "cbor": "OQPn", + "hex": "3903e7", + "roundtrip": true, + "decoded": -1000 + }, + { + "cbor": "+QAA", + "hex": "f90000", + "roundtrip": true, + "decoded": 0.0 + }, + { + "cbor": "+YAA", + "hex": "f98000", + "roundtrip": true, + "decoded": -0.0 + }, + { + "cbor": "+TwA", + "hex": "f93c00", + "roundtrip": true, + "decoded": 1.0 + }, + { + "cbor": "+z/xmZmZmZma", + "hex": "fb3ff199999999999a", + "roundtrip": true, + "decoded": 1.1 + }, + { + "cbor": "+T4A", + "hex": "f93e00", + "roundtrip": true, + "decoded": 1.5 + }, + { + "cbor": "+Xv/", + "hex": "f97bff", + "roundtrip": true, + "decoded": 65504.0 + }, + { + "cbor": "+kfDUAA=", + "hex": "fa47c35000", + "roundtrip": true, + "decoded": 100000.0 + }, + { + "cbor": "+n9///8=", + "hex": "fa7f7fffff", + "roundtrip": true, + "decoded": 3.4028234663852886e+38 + }, + { + "cbor": "+3435DyIAHWc", + "hex": "fb7e37e43c8800759c", + "roundtrip": true, + "decoded": 1.0e+300 + }, + { + "cbor": "+QAB", + "hex": "f90001", + "roundtrip": true, + "decoded": 5.960464477539063e-08 + }, + { + "cbor": "+QQA", + "hex": "f90400", + "roundtrip": true, + "decoded": 6.103515625e-05 + }, + { + "cbor": "+cQA", + "hex": "f9c400", + "roundtrip": true, + "decoded": -4.0 + }, + { + "cbor": "+8AQZmZmZmZm", + "hex": "fbc010666666666666", + "roundtrip": true, + "decoded": -4.1 + }, + { + "cbor": "+XwA", + "hex": "f97c00", + "roundtrip": true, + "diagnostic": "Infinity" + }, + { + "cbor": "+X4A", + "hex": "f97e00", + "roundtrip": true, + "diagnostic": "NaN" + }, + { + "cbor": "+fwA", + "hex": "f9fc00", + "roundtrip": true, + "diagnostic": "-Infinity" + }, + { + "cbor": "+n+AAAA=", + "hex": "fa7f800000", + "roundtrip": false, + "diagnostic": "Infinity" + }, + { + "cbor": "+n/AAAA=", + "hex": "fa7fc00000", + "roundtrip": false, + "diagnostic": "NaN" + }, + { + "cbor": "+v+AAAA=", + "hex": "faff800000", + "roundtrip": false, + "diagnostic": "-Infinity" + }, + { + "cbor": "+3/wAAAAAAAA", + "hex": "fb7ff0000000000000", + "roundtrip": false, + "diagnostic": "Infinity" + }, + { + "cbor": "+3/4AAAAAAAA", + "hex": "fb7ff8000000000000", + "roundtrip": false, + "diagnostic": "NaN" + }, + { + "cbor": "+//wAAAAAAAA", + "hex": "fbfff0000000000000", + "roundtrip": false, + "diagnostic": "-Infinity" + }, + { + "cbor": "9A==", + "hex": "f4", + "roundtrip": true, + "decoded": false + }, + { + "cbor": "9Q==", + "hex": "f5", + "roundtrip": true, + "decoded": true + }, + { + "cbor": "9g==", + "hex": "f6", + "roundtrip": true, + "decoded": null + }, + { + "cbor": "9w==", + "hex": "f7", + "roundtrip": true, + "diagnostic": "undefined" + }, + { + "cbor": "8A==", + "hex": "f0", + "roundtrip": true, + "diagnostic": "simple(16)" + }, + { + "cbor": "+Bg=", + "hex": "f818", + "roundtrip": true, + "diagnostic": "simple(24)" + }, + { + "cbor": "+P8=", + "hex": "f8ff", + "roundtrip": true, + "diagnostic": "simple(255)" + }, + { + "cbor": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==", + "hex": "c074323031332d30332d32315432303a30343a30305a", + "roundtrip": true, + "diagnostic": "0(\"2013-03-21T20:04:00Z\")" + }, + { + "cbor": "wRpRS2ew", + "hex": "c11a514b67b0", + "roundtrip": true, + "diagnostic": "1(1363896240)" + }, + { + "cbor": "wftB1FLZ7CAAAA==", + "hex": "c1fb41d452d9ec200000", + "roundtrip": true, + "diagnostic": "1(1363896240.5)" + }, + { + "cbor": "10QBAgME", + "hex": "d74401020304", + "roundtrip": true, + "diagnostic": "23(h'01020304')" + }, + { + "cbor": "2BhFZElFVEY=", + "hex": "d818456449455446", + "roundtrip": true, + "diagnostic": "24(h'6449455446')" + }, + { + "cbor": "2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==", + "hex": "d82076687474703a2f2f7777772e6578616d706c652e636f6d", + "roundtrip": true, + "diagnostic": "32(\"http://www.example.com\")" + }, + { + "cbor": "QA==", + "hex": "40", + "roundtrip": true, + "diagnostic": "h''" + }, + { + "cbor": "RAECAwQ=", + "hex": "4401020304", + "roundtrip": true, + "diagnostic": "h'01020304'" + }, + { + "cbor": "YA==", + "hex": "60", + "roundtrip": true, + "decoded": "" + }, + { + "cbor": "YWE=", + "hex": "6161", + "roundtrip": true, + "decoded": "a" + }, + { + "cbor": "ZElFVEY=", + "hex": "6449455446", + "roundtrip": true, + "decoded": "IETF" + }, + { + "cbor": "YiJc", + "hex": "62225c", + "roundtrip": true, + "decoded": "\"\\" + }, + { + "cbor": "YsO8", + "hex": "62c3bc", + "roundtrip": true, + "decoded": "ü" + }, + { + "cbor": "Y+awtA==", + "hex": "63e6b0b4", + "roundtrip": true, + "decoded": "æ°´" + }, + { + "cbor": "ZPCQhZE=", + "hex": "64f0908591", + "roundtrip": true, + "decoded": "ð…‘" + }, + { + "cbor": "gA==", + "hex": "80", + "roundtrip": true, + "decoded": [ + + ] + }, + { + "cbor": "gwECAw==", + "hex": "83010203", + "roundtrip": true, + "decoded": [ + 1, + 2, + 3 + ] + }, + { + "cbor": "gwGCAgOCBAU=", + "hex": "8301820203820405", + "roundtrip": true, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=", + "hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819", + "roundtrip": true, + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "cbor": "oA==", + "hex": "a0", + "roundtrip": true, + "decoded": { + } + }, + { + "cbor": "ogECAwQ=", + "hex": "a201020304", + "roundtrip": true, + "skip": true, + "diagnostic": "{1: 2, 3: 4}" + }, + { + "cbor": "omFhAWFiggID", + "hex": "a26161016162820203", + "roundtrip": true, + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "cbor": "gmFhoWFiYWM=", + "hex": "826161a161626163", + "roundtrip": true, + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "cbor": "pWFhYUFhYmFCYWNhQ2FkYURhZWFF", + "hex": "a56161614161626142616361436164614461656145", + "roundtrip": true, + "decoded": { + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E" + } + }, + { + "cbor": "X0IBAkMDBAX/", + "hex": "5f42010243030405ff", + "roundtrip": false, + "skip": true, + "diagnostic": "(_ h'0102', h'030405')" + }, + { + "cbor": "f2VzdHJlYWRtaW5n/w==", + "hex": "7f657374726561646d696e67ff", + "roundtrip": false, + "decoded": "streaming" + }, + { + "cbor": "n/8=", + "hex": "9fff", + "roundtrip": false, + "decoded": [ + + ] + }, + { + "cbor": "nwGCAgOfBAX//w==", + "hex": "9f018202039f0405ffff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "nwGCAgOCBAX/", + "hex": "9f01820203820405ff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "gwGCAgOfBAX/", + "hex": "83018202039f0405ff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "gwGfAgP/ggQF", + "hex": "83019f0203ff820405", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=", + "hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", + "roundtrip": false, + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "cbor": "v2FhAWFinwID//8=", + "hex": "bf61610161629f0203ffff", + "roundtrip": false, + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "cbor": "gmFhv2FiYWP/", + "hex": "826161bf61626163ff", + "roundtrip": false, + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "cbor": "v2NGdW71Y0FtdCH/", + "hex": "bf6346756ef563416d7421ff", + "roundtrip": false, + "decoded": { + "Fun": true, + "Amt": -2 + } + } +] diff --git a/vendor/github.com/ugorji/go/codec/test.py b/vendor/github.com/ugorji/go/codec/test.py new file mode 100644 index 000000000..c0ad20b34 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/test.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python + +# This will create golden files in a directory passed to it. +# A Test calls this internally to create the golden files +# So it can process them (so we don't have to checkin the files). + +# Ensure msgpack-python and cbor are installed first, using: +# sudo apt-get install python-dev +# sudo apt-get install python-pip +# pip install --user msgpack-python msgpack-rpc-python cbor + +# Ensure all "string" keys are utf strings (else encoded as bytes) + +import cbor, msgpack, msgpackrpc, sys, os, threading + +def get_test_data_list(): + # get list with all primitive types, and a combo type + l0 = [ + -8, + -1616, + -32323232, + -6464646464646464, + 192, + 1616, + 32323232, + 6464646464646464, + 192, + -3232.0, + -6464646464.0, + 3232.0, + 6464.0, + 6464646464.0, + False, + True, + u"null", + None, + u"someday", + 1328176922000002000, + u"", + -2206187877999998000, + u"bytestring", + 270, + u"none", + -2013855847999995777, + #-6795364578871345152, + ] + l1 = [ + { "true": True, + "false": False }, + { "true": u"True", + "false": False, + "uint16(1616)": 1616 }, + { "list": [1616, 32323232, True, -3232.0, {"TRUE":True, "FALSE":False}, [True, False] ], + "int32":32323232, "bool": True, + "LONG STRING": u"123456789012345678901234567890123456789012345678901234567890", + "SHORT STRING": u"1234567890" }, + { True: "true", 138: False, "false": 200 } + ] + + l = [] + l.extend(l0) + l.append(l0) + l.append(1) + l.extend(l1) + return l + +def build_test_data(destdir): + l = get_test_data_list() + for i in range(len(l)): + # packer = msgpack.Packer() + serialized = msgpack.dumps(l[i]) + f = open(os.path.join(destdir, str(i) + '.msgpack.golden'), 'wb') + f.write(serialized) + f.close() + serialized = cbor.dumps(l[i]) + f = open(os.path.join(destdir, str(i) + '.cbor.golden'), 'wb') + f.write(serialized) + f.close() + +def doRpcServer(port, stopTimeSec): + class EchoHandler(object): + def Echo123(self, msg1, msg2, msg3): + return ("1:%s 2:%s 3:%s" % (msg1, msg2, msg3)) + def EchoStruct(self, msg): + return ("%s" % msg) + + addr = msgpackrpc.Address('localhost', port) + server = msgpackrpc.Server(EchoHandler()) + server.listen(addr) + # run thread to stop it after stopTimeSec seconds if > 0 + if stopTimeSec > 0: + def myStopRpcServer(): + server.stop() + t = threading.Timer(stopTimeSec, myStopRpcServer) + t.start() + server.start() + +def doRpcClientToPythonSvc(port): + address = msgpackrpc.Address('localhost', port) + client = msgpackrpc.Client(address, unpack_encoding='utf-8') + print client.call("Echo123", "A1", "B2", "C3") + print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) + +def doRpcClientToGoSvc(port): + # print ">>>> port: ", port, " <<<<<" + address = msgpackrpc.Address('localhost', port) + client = msgpackrpc.Client(address, unpack_encoding='utf-8') + print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"]) + print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) + +def doMain(args): + if len(args) == 2 and args[0] == "testdata": + build_test_data(args[1]) + elif len(args) == 3 and args[0] == "rpc-server": + doRpcServer(int(args[1]), int(args[2])) + elif len(args) == 2 and args[0] == "rpc-client-python-service": + doRpcClientToPythonSvc(int(args[1])) + elif len(args) == 2 and args[0] == "rpc-client-go-service": + doRpcClientToGoSvc(int(args[1])) + else: + print("Usage: test.py " + + "[testdata|rpc-server|rpc-client-python-service|rpc-client-go-service] ...") + +if __name__ == "__main__": + doMain(sys.argv[1:]) + diff --git a/vendor/github.com/ugorji/go/codec/tests.sh b/vendor/github.com/ugorji/go/codec/tests.sh new file mode 100644 index 000000000..00857b620 --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/tests.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Run all the different permutations of all the tests. +# This helps ensure that nothing gets broken. + +_run() { + # 1. VARIATIONS: regular (t), canonical (c), IO R/W (i), + # binc-nosymbols (n), struct2array (s), intern string (e), + # json-indent (d), circular (l) + # 2. MODE: reflection (r), external (x), codecgen (g), unsafe (u), notfastpath (f) + # 3. OPTIONS: verbose (v), reset (z), must (m), + # + # Use combinations of mode to get exactly what you want, + # and then pass the variations you need. + + ztags="" + zargs="" + local OPTIND + OPTIND=1 + while getopts "_xurtcinsvgzmefdl" flag + do + case "x$flag" in + 'xr') ;; + 'xf') ztags="$ztags notfastpath" ;; + 'xg') ztags="$ztags codecgen" ;; + 'xx') ztags="$ztags x" ;; + 'xu') ztags="$ztags unsafe" ;; + 'xv') zargs="$zargs -tv" ;; + 'xz') zargs="$zargs -tr" ;; + 'xm') zargs="$zargs -tm" ;; + 'xl') zargs="$zargs -tl" ;; + *) ;; + esac + done + # shift $((OPTIND-1)) + printf '............. TAGS: %s .............\n' "$ztags" + # echo ">>>>>>> TAGS: $ztags" + + OPTIND=1 + while getopts "_xurtcinsvgzmefdl" flag + do + case "x$flag" in + 'xt') printf ">>>>>>> REGULAR : "; go test "-tags=$ztags" $zargs ; sleep 2 ;; + 'xc') printf ">>>>>>> CANONICAL : "; go test "-tags=$ztags" $zargs -tc; sleep 2 ;; + 'xi') printf ">>>>>>> I/O : "; go test "-tags=$ztags" $zargs -ti; sleep 2 ;; + 'xn') printf ">>>>>>> NO_SYMBOLS : "; go test "-tags=$ztags" -run=Binc $zargs -tn; sleep 2 ;; + 'xs') printf ">>>>>>> TO_ARRAY : "; go test "-tags=$ztags" $zargs -ts; sleep 2 ;; + 'xe') printf ">>>>>>> INTERN : "; go test "-tags=$ztags" $zargs -te; sleep 2 ;; + 'xd') printf ">>>>>>> INDENT : "; + go test "-tags=$ztags" -run=JsonCodecsTable -td=-1 $zargs; + go test "-tags=$ztags" -run=JsonCodecsTable -td=8 $zargs; + sleep 2 ;; + *) ;; + esac + done + shift $((OPTIND-1)) + + OPTIND=1 +} + +# echo ">>>>>>> RUNNING VARIATIONS OF TESTS" +if [[ "x$@" = "x" ]]; then + # All: r, x, g, gu + _run "-_tcinsed_ml" # regular + _run "-_tcinsed_ml_z" # regular with reset + _run "-_tcinsed_ml_f" # regular with no fastpath (notfastpath) + _run "-x_tcinsed_ml" # external + _run "-gx_tcinsed_ml" # codecgen: requires external + _run "-gxu_tcinsed_ml" # codecgen + unsafe +elif [[ "x$@" = "x-Z" ]]; then + # Regular + _run "-_tcinsed_ml" # regular + _run "-_tcinsed_ml_z" # regular with reset +elif [[ "x$@" = "x-F" ]]; then + # regular with notfastpath + _run "-_tcinsed_ml_f" # regular + _run "-_tcinsed_ml_zf" # regular with reset +else + _run "$@" +fi diff --git a/vendor/github.com/ugorji/go/codec/time.go b/vendor/github.com/ugorji/go/codec/time.go new file mode 100644 index 000000000..718b731ec --- /dev/null +++ b/vendor/github.com/ugorji/go/codec/time.go @@ -0,0 +1,233 @@ +// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a MIT license found in the LICENSE file. + +package codec + +import ( + "fmt" + "reflect" + "time" +) + +var ( + timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} + timeExtEncFn = func(rv reflect.Value) (bs []byte, err error) { + defer panicToErr(&err) + bs = timeExt{}.WriteExt(rv.Interface()) + return + } + timeExtDecFn = func(rv reflect.Value, bs []byte) (err error) { + defer panicToErr(&err) + timeExt{}.ReadExt(rv.Interface(), bs) + return + } +) + +type timeExt struct{} + +func (x timeExt) WriteExt(v interface{}) (bs []byte) { + switch v2 := v.(type) { + case time.Time: + bs = encodeTime(v2) + case *time.Time: + bs = encodeTime(*v2) + default: + panic(fmt.Errorf("unsupported format for time conversion: expecting time.Time; got %T", v2)) + } + return +} +func (x timeExt) ReadExt(v interface{}, bs []byte) { + tt, err := decodeTime(bs) + if err != nil { + panic(err) + } + *(v.(*time.Time)) = tt +} + +func (x timeExt) ConvertExt(v interface{}) interface{} { + return x.WriteExt(v) +} +func (x timeExt) UpdateExt(v interface{}, src interface{}) { + x.ReadExt(v, src.([]byte)) +} + +// EncodeTime encodes a time.Time as a []byte, including +// information on the instant in time and UTC offset. +// +// Format Description +// +// A timestamp is composed of 3 components: +// +// - secs: signed integer representing seconds since unix epoch +// - nsces: unsigned integer representing fractional seconds as a +// nanosecond offset within secs, in the range 0 <= nsecs < 1e9 +// - tz: signed integer representing timezone offset in minutes east of UTC, +// and a dst (daylight savings time) flag +// +// When encoding a timestamp, the first byte is the descriptor, which +// defines which components are encoded and how many bytes are used to +// encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it +// is not encoded in the byte array explicitly*. +// +// Descriptor 8 bits are of the form `A B C DDD EE`: +// A: Is secs component encoded? 1 = true +// B: Is nsecs component encoded? 1 = true +// C: Is tz component encoded? 1 = true +// DDD: Number of extra bytes for secs (range 0-7). +// If A = 1, secs encoded in DDD+1 bytes. +// If A = 0, secs is not encoded, and is assumed to be 0. +// If A = 1, then we need at least 1 byte to encode secs. +// DDD says the number of extra bytes beyond that 1. +// E.g. if DDD=0, then secs is represented in 1 byte. +// if DDD=2, then secs is represented in 3 bytes. +// EE: Number of extra bytes for nsecs (range 0-3). +// If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above) +// +// Following the descriptor bytes, subsequent bytes are: +// +// secs component encoded in `DDD + 1` bytes (if A == 1) +// nsecs component encoded in `EE + 1` bytes (if B == 1) +// tz component encoded in 2 bytes (if C == 1) +// +// secs and nsecs components are integers encoded in a BigEndian +// 2-complement encoding format. +// +// tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to +// Least significant bit 0 are described below: +// +// Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes). +// Bit 15 = have\_dst: set to 1 if we set the dst flag. +// Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not. +// Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format. +// +func encodeTime(t time.Time) []byte { + //t := rv.Interface().(time.Time) + tsecs, tnsecs := t.Unix(), t.Nanosecond() + var ( + bd byte + btmp [8]byte + bs [16]byte + i int = 1 + ) + l := t.Location() + if l == time.UTC { + l = nil + } + if tsecs != 0 { + bd = bd | 0x80 + bigen.PutUint64(btmp[:], uint64(tsecs)) + f := pruneSignExt(btmp[:], tsecs >= 0) + bd = bd | (byte(7-f) << 2) + copy(bs[i:], btmp[f:]) + i = i + (8 - f) + } + if tnsecs != 0 { + bd = bd | 0x40 + bigen.PutUint32(btmp[:4], uint32(tnsecs)) + f := pruneSignExt(btmp[:4], true) + bd = bd | byte(3-f) + copy(bs[i:], btmp[f:4]) + i = i + (4 - f) + } + if l != nil { + bd = bd | 0x20 + // Note that Go Libs do not give access to dst flag. + _, zoneOffset := t.Zone() + //zoneName, zoneOffset := t.Zone() + zoneOffset /= 60 + z := uint16(zoneOffset) + bigen.PutUint16(btmp[:2], z) + // clear dst flags + bs[i] = btmp[0] & 0x3f + bs[i+1] = btmp[1] + i = i + 2 + } + bs[0] = bd + return bs[0:i] +} + +// DecodeTime decodes a []byte into a time.Time. +func decodeTime(bs []byte) (tt time.Time, err error) { + bd := bs[0] + var ( + tsec int64 + tnsec uint32 + tz uint16 + i byte = 1 + i2 byte + n byte + ) + if bd&(1<<7) != 0 { + var btmp [8]byte + n = ((bd >> 2) & 0x7) + 1 + i2 = i + n + copy(btmp[8-n:], bs[i:i2]) + //if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it) + if bs[i]&(1<<7) != 0 { + copy(btmp[0:8-n], bsAll0xff) + //for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff } + } + i = i2 + tsec = int64(bigen.Uint64(btmp[:])) + } + if bd&(1<<6) != 0 { + var btmp [4]byte + n = (bd & 0x3) + 1 + i2 = i + n + copy(btmp[4-n:], bs[i:i2]) + i = i2 + tnsec = bigen.Uint32(btmp[:]) + } + if bd&(1<<5) == 0 { + tt = time.Unix(tsec, int64(tnsec)).UTC() + return + } + // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name. + // However, we need name here, so it can be shown when time is printed. + // Zone name is in form: UTC-08:00. + // Note that Go Libs do not give access to dst flag, so we ignore dst bits + + i2 = i + 2 + tz = bigen.Uint16(bs[i:i2]) + i = i2 + // sign extend sign bit into top 2 MSB (which were dst bits): + if tz&(1<<13) == 0 { // positive + tz = tz & 0x3fff //clear 2 MSBs: dst bits + } else { // negative + tz = tz | 0xc000 //set 2 MSBs: dst bits + //tzname[3] = '-' (TODO: verify. this works here) + } + tzint := int16(tz) + if tzint == 0 { + tt = time.Unix(tsec, int64(tnsec)).UTC() + } else { + // For Go Time, do not use a descriptive timezone. + // It's unnecessary, and makes it harder to do a reflect.DeepEqual. + // The Offset already tells what the offset should be, if not on UTC and unknown zone name. + // var zoneName = timeLocUTCName(tzint) + tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60)) + } + return +} + +func timeLocUTCName(tzint int16) string { + if tzint == 0 { + return "UTC" + } + var tzname = []byte("UTC+00:00") + //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below. + //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first + var tzhr, tzmin int16 + if tzint < 0 { + tzname[3] = '-' // (TODO: verify. this works here) + tzhr, tzmin = -tzint/60, (-tzint)%60 + } else { + tzhr, tzmin = tzint/60, tzint%60 + } + tzname[4] = timeDigits[tzhr/10] + tzname[5] = timeDigits[tzhr%10] + tzname[7] = timeDigits[tzmin/10] + tzname[8] = timeDigits[tzmin%10] + return string(tzname) + //return time.FixedZone(string(tzname), int(tzint)*60) +} diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/golang.org/x/crypto/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/golang.org/x/crypto/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s new file mode 100644 index 000000000..797f9b051 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s @@ -0,0 +1,20 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF +GLOBL ·REDMASK51(SB), 8, $8 + +DATA ·_121666_213(SB)/8, $996687872 +GLOBL ·_121666_213(SB), 8, $8 + +DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA +GLOBL ·_2P0(SB), 8, $8 + +DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE +GLOBL ·_2P1234(SB), 8, $8 diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s new file mode 100644 index 000000000..45484d1b5 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s @@ -0,0 +1,88 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func cswap(inout *[5]uint64, v uint64) +TEXT ·cswap(SB),7,$0 + MOVQ inout+0(FP),DI + MOVQ v+8(FP),SI + + CMPQ SI,$1 + MOVQ 0(DI),SI + MOVQ 80(DI),DX + MOVQ 8(DI),CX + MOVQ 88(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,0(DI) + MOVQ DX,80(DI) + MOVQ CX,8(DI) + MOVQ R8,88(DI) + MOVQ 16(DI),SI + MOVQ 96(DI),DX + MOVQ 24(DI),CX + MOVQ 104(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,16(DI) + MOVQ DX,96(DI) + MOVQ CX,24(DI) + MOVQ R8,104(DI) + MOVQ 32(DI),SI + MOVQ 112(DI),DX + MOVQ 40(DI),CX + MOVQ 120(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,32(DI) + MOVQ DX,112(DI) + MOVQ CX,40(DI) + MOVQ R8,120(DI) + MOVQ 48(DI),SI + MOVQ 128(DI),DX + MOVQ 56(DI),CX + MOVQ 136(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,48(DI) + MOVQ DX,128(DI) + MOVQ CX,56(DI) + MOVQ R8,136(DI) + MOVQ 64(DI),SI + MOVQ 144(DI),DX + MOVQ 72(DI),CX + MOVQ 152(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,64(DI) + MOVQ DX,144(DI) + MOVQ CX,72(DI) + MOVQ R8,152(DI) + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go new file mode 100644 index 000000000..6918c47fc --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -0,0 +1,841 @@ +// Copyright 2013 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. + +// We have a implementation in amd64 assembly so this code is only run on +// non-amd64 platforms. The amd64 assembly does not support gccgo. +// +build !amd64 gccgo appengine + +package curve25519 + +// This code is a port of the public domain, "ref10" implementation of +// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. + +// fieldElement represents an element of the field GF(2^255 - 19). An element +// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 +// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on +// context. +type fieldElement [10]int32 + +func feZero(fe *fieldElement) { + for i := range fe { + fe[i] = 0 + } +} + +func feOne(fe *fieldElement) { + feZero(fe) + fe[0] = 1 +} + +func feAdd(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] + b[i] + } +} + +func feSub(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] - b[i] + } +} + +func feCopy(dst, src *fieldElement) { + for i := range dst { + dst[i] = src[i] + } +} + +// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +func feCSwap(f, g *fieldElement, b int32) { + var x fieldElement + b = -b + for i := range x { + x[i] = b & (f[i] ^ g[i]) + } + + for i := range f { + f[i] ^= x[i] + } + for i := range g { + g[i] ^= x[i] + } +} + +// load3 reads a 24-bit, little-endian value from in. +func load3(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +// load4 reads a 32-bit, little-endian value from in. +func load4(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + r |= int64(in[3]) << 24 + return r +} + +func feFromBytes(dst *fieldElement, src *[32]byte) { + h0 := load4(src[:]) + h1 := load3(src[4:]) << 6 + h2 := load3(src[7:]) << 5 + h3 := load3(src[10:]) << 3 + h4 := load3(src[13:]) << 2 + h5 := load4(src[16:]) + h6 := load3(src[20:]) << 7 + h7 := load3(src[23:]) << 5 + h8 := load3(src[26:]) << 4 + h9 := load3(src[29:]) << 2 + + var carry [10]int64 + carry[9] = (h9 + 1<<24) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + 1<<24) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + 1<<24) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + 1<<24) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + 1<<24) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + 1<<25) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + 1<<25) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + 1<<25) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + 1<<25) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + 1<<25) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + dst[0] = int32(h0) + dst[1] = int32(h1) + dst[2] = int32(h2) + dst[3] = int32(h3) + dst[4] = int32(h4) + dst[5] = int32(h5) + dst[6] = int32(h6) + dst[7] = int32(h7) + dst[8] = int32(h8) + dst[9] = int32(h9) +} + +// feToBytes marshals h to s. +// Preconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Write p=2^255-19; q=floor(h/p). +// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). +// +// Proof: +// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. +// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. +// +// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). +// Then 0> 25 + q = (h[0] + q) >> 26 + q = (h[1] + q) >> 25 + q = (h[2] + q) >> 26 + q = (h[3] + q) >> 25 + q = (h[4] + q) >> 26 + q = (h[5] + q) >> 25 + q = (h[6] + q) >> 26 + q = (h[7] + q) >> 25 + q = (h[8] + q) >> 26 + q = (h[9] + q) >> 25 + + // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. + h[0] += 19 * q + // Goal: Output h-2^255 q, which is between 0 and 2^255-20. + + carry[0] = h[0] >> 26 + h[1] += carry[0] + h[0] -= carry[0] << 26 + carry[1] = h[1] >> 25 + h[2] += carry[1] + h[1] -= carry[1] << 25 + carry[2] = h[2] >> 26 + h[3] += carry[2] + h[2] -= carry[2] << 26 + carry[3] = h[3] >> 25 + h[4] += carry[3] + h[3] -= carry[3] << 25 + carry[4] = h[4] >> 26 + h[5] += carry[4] + h[4] -= carry[4] << 26 + carry[5] = h[5] >> 25 + h[6] += carry[5] + h[5] -= carry[5] << 25 + carry[6] = h[6] >> 26 + h[7] += carry[6] + h[6] -= carry[6] << 26 + carry[7] = h[7] >> 25 + h[8] += carry[7] + h[7] -= carry[7] << 25 + carry[8] = h[8] >> 26 + h[9] += carry[8] + h[8] -= carry[8] << 26 + carry[9] = h[9] >> 25 + h[9] -= carry[9] << 25 + // h10 = carry9 + + // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; + // evidently 2^255 h10-2^255 q = 0. + // Goal: Output h[0]+...+2^230 h[9]. + + s[0] = byte(h[0] >> 0) + s[1] = byte(h[0] >> 8) + s[2] = byte(h[0] >> 16) + s[3] = byte((h[0] >> 24) | (h[1] << 2)) + s[4] = byte(h[1] >> 6) + s[5] = byte(h[1] >> 14) + s[6] = byte((h[1] >> 22) | (h[2] << 3)) + s[7] = byte(h[2] >> 5) + s[8] = byte(h[2] >> 13) + s[9] = byte((h[2] >> 21) | (h[3] << 5)) + s[10] = byte(h[3] >> 3) + s[11] = byte(h[3] >> 11) + s[12] = byte((h[3] >> 19) | (h[4] << 6)) + s[13] = byte(h[4] >> 2) + s[14] = byte(h[4] >> 10) + s[15] = byte(h[4] >> 18) + s[16] = byte(h[5] >> 0) + s[17] = byte(h[5] >> 8) + s[18] = byte(h[5] >> 16) + s[19] = byte((h[5] >> 24) | (h[6] << 1)) + s[20] = byte(h[6] >> 7) + s[21] = byte(h[6] >> 15) + s[22] = byte((h[6] >> 23) | (h[7] << 3)) + s[23] = byte(h[7] >> 5) + s[24] = byte(h[7] >> 13) + s[25] = byte((h[7] >> 21) | (h[8] << 4)) + s[26] = byte(h[8] >> 4) + s[27] = byte(h[8] >> 12) + s[28] = byte((h[8] >> 20) | (h[9] << 6)) + s[29] = byte(h[9] >> 2) + s[30] = byte(h[9] >> 10) + s[31] = byte(h[9] >> 18) +} + +// feMul calculates h = f * g +// Can overlap h with f or g. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Notes on implementation strategy: +// +// Using schoolbook multiplication. +// Karatsuba would save a little in some cost models. +// +// Most multiplications by 2 and 19 are 32-bit precomputations; +// cheaper than 64-bit postcomputations. +// +// There is one remaining multiplication by 19 in the carry chain; +// one *19 precomputation can be merged into this, +// but the resulting data flow is considerably less clean. +// +// There are 12 carries below. +// 10 of them are 2-way parallelizable and vectorizable. +// Can get away with 11 carries, but then data flow is much deeper. +// +// With tighter constraints on inputs can squeeze carries into int32. +func feMul(h, f, g *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + g0 := g[0] + g1 := g[1] + g2 := g[2] + g3 := g[3] + g4 := g[4] + g5 := g[5] + g6 := g[6] + g7 := g[7] + g8 := g[8] + g9 := g[9] + g1_19 := 19 * g1 // 1.4*2^29 + g2_19 := 19 * g2 // 1.4*2^30; still ok + g3_19 := 19 * g3 + g4_19 := 19 * g4 + g5_19 := 19 * g5 + g6_19 := 19 * g6 + g7_19 := 19 * g7 + g8_19 := 19 * g8 + g9_19 := 19 * g9 + f1_2 := 2 * f1 + f3_2 := 2 * f3 + f5_2 := 2 * f5 + f7_2 := 2 * f7 + f9_2 := 2 * f9 + f0g0 := int64(f0) * int64(g0) + f0g1 := int64(f0) * int64(g1) + f0g2 := int64(f0) * int64(g2) + f0g3 := int64(f0) * int64(g3) + f0g4 := int64(f0) * int64(g4) + f0g5 := int64(f0) * int64(g5) + f0g6 := int64(f0) * int64(g6) + f0g7 := int64(f0) * int64(g7) + f0g8 := int64(f0) * int64(g8) + f0g9 := int64(f0) * int64(g9) + f1g0 := int64(f1) * int64(g0) + f1g1_2 := int64(f1_2) * int64(g1) + f1g2 := int64(f1) * int64(g2) + f1g3_2 := int64(f1_2) * int64(g3) + f1g4 := int64(f1) * int64(g4) + f1g5_2 := int64(f1_2) * int64(g5) + f1g6 := int64(f1) * int64(g6) + f1g7_2 := int64(f1_2) * int64(g7) + f1g8 := int64(f1) * int64(g8) + f1g9_38 := int64(f1_2) * int64(g9_19) + f2g0 := int64(f2) * int64(g0) + f2g1 := int64(f2) * int64(g1) + f2g2 := int64(f2) * int64(g2) + f2g3 := int64(f2) * int64(g3) + f2g4 := int64(f2) * int64(g4) + f2g5 := int64(f2) * int64(g5) + f2g6 := int64(f2) * int64(g6) + f2g7 := int64(f2) * int64(g7) + f2g8_19 := int64(f2) * int64(g8_19) + f2g9_19 := int64(f2) * int64(g9_19) + f3g0 := int64(f3) * int64(g0) + f3g1_2 := int64(f3_2) * int64(g1) + f3g2 := int64(f3) * int64(g2) + f3g3_2 := int64(f3_2) * int64(g3) + f3g4 := int64(f3) * int64(g4) + f3g5_2 := int64(f3_2) * int64(g5) + f3g6 := int64(f3) * int64(g6) + f3g7_38 := int64(f3_2) * int64(g7_19) + f3g8_19 := int64(f3) * int64(g8_19) + f3g9_38 := int64(f3_2) * int64(g9_19) + f4g0 := int64(f4) * int64(g0) + f4g1 := int64(f4) * int64(g1) + f4g2 := int64(f4) * int64(g2) + f4g3 := int64(f4) * int64(g3) + f4g4 := int64(f4) * int64(g4) + f4g5 := int64(f4) * int64(g5) + f4g6_19 := int64(f4) * int64(g6_19) + f4g7_19 := int64(f4) * int64(g7_19) + f4g8_19 := int64(f4) * int64(g8_19) + f4g9_19 := int64(f4) * int64(g9_19) + f5g0 := int64(f5) * int64(g0) + f5g1_2 := int64(f5_2) * int64(g1) + f5g2 := int64(f5) * int64(g2) + f5g3_2 := int64(f5_2) * int64(g3) + f5g4 := int64(f5) * int64(g4) + f5g5_38 := int64(f5_2) * int64(g5_19) + f5g6_19 := int64(f5) * int64(g6_19) + f5g7_38 := int64(f5_2) * int64(g7_19) + f5g8_19 := int64(f5) * int64(g8_19) + f5g9_38 := int64(f5_2) * int64(g9_19) + f6g0 := int64(f6) * int64(g0) + f6g1 := int64(f6) * int64(g1) + f6g2 := int64(f6) * int64(g2) + f6g3 := int64(f6) * int64(g3) + f6g4_19 := int64(f6) * int64(g4_19) + f6g5_19 := int64(f6) * int64(g5_19) + f6g6_19 := int64(f6) * int64(g6_19) + f6g7_19 := int64(f6) * int64(g7_19) + f6g8_19 := int64(f6) * int64(g8_19) + f6g9_19 := int64(f6) * int64(g9_19) + f7g0 := int64(f7) * int64(g0) + f7g1_2 := int64(f7_2) * int64(g1) + f7g2 := int64(f7) * int64(g2) + f7g3_38 := int64(f7_2) * int64(g3_19) + f7g4_19 := int64(f7) * int64(g4_19) + f7g5_38 := int64(f7_2) * int64(g5_19) + f7g6_19 := int64(f7) * int64(g6_19) + f7g7_38 := int64(f7_2) * int64(g7_19) + f7g8_19 := int64(f7) * int64(g8_19) + f7g9_38 := int64(f7_2) * int64(g9_19) + f8g0 := int64(f8) * int64(g0) + f8g1 := int64(f8) * int64(g1) + f8g2_19 := int64(f8) * int64(g2_19) + f8g3_19 := int64(f8) * int64(g3_19) + f8g4_19 := int64(f8) * int64(g4_19) + f8g5_19 := int64(f8) * int64(g5_19) + f8g6_19 := int64(f8) * int64(g6_19) + f8g7_19 := int64(f8) * int64(g7_19) + f8g8_19 := int64(f8) * int64(g8_19) + f8g9_19 := int64(f8) * int64(g9_19) + f9g0 := int64(f9) * int64(g0) + f9g1_38 := int64(f9_2) * int64(g1_19) + f9g2_19 := int64(f9) * int64(g2_19) + f9g3_38 := int64(f9_2) * int64(g3_19) + f9g4_19 := int64(f9) * int64(g4_19) + f9g5_38 := int64(f9_2) * int64(g5_19) + f9g6_19 := int64(f9) * int64(g6_19) + f9g7_38 := int64(f9_2) * int64(g7_19) + f9g8_19 := int64(f9) * int64(g8_19) + f9g9_38 := int64(f9_2) * int64(g9_19) + h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 + h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 + h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 + h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 + h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 + h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 + h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 + h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 + h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 + h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 + var carry [10]int64 + + // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) + // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 + // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) + // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + // |h0| <= 2^25 + // |h4| <= 2^25 + // |h1| <= 1.51*2^58 + // |h5| <= 1.51*2^58 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + // |h1| <= 2^24; from now on fits into int32 + // |h5| <= 2^24; from now on fits into int32 + // |h2| <= 1.21*2^59 + // |h6| <= 1.21*2^59 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + // |h2| <= 2^25; from now on fits into int32 unchanged + // |h6| <= 2^25; from now on fits into int32 unchanged + // |h3| <= 1.51*2^58 + // |h7| <= 1.51*2^58 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + // |h3| <= 2^24; from now on fits into int32 unchanged + // |h7| <= 2^24; from now on fits into int32 unchanged + // |h4| <= 1.52*2^33 + // |h8| <= 1.52*2^33 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + // |h4| <= 2^25; from now on fits into int32 unchanged + // |h8| <= 2^25; from now on fits into int32 unchanged + // |h5| <= 1.01*2^24 + // |h9| <= 1.51*2^58 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + // |h9| <= 2^24; from now on fits into int32 unchanged + // |h0| <= 1.8*2^37 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + // |h0| <= 2^25; from now on fits into int32 unchanged + // |h1| <= 1.01*2^24 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feSquare calculates h = f*f. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feSquare(h, f *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + f0_2 := 2 * f0 + f1_2 := 2 * f1 + f2_2 := 2 * f2 + f3_2 := 2 * f3 + f4_2 := 2 * f4 + f5_2 := 2 * f5 + f6_2 := 2 * f6 + f7_2 := 2 * f7 + f5_38 := 38 * f5 // 1.31*2^30 + f6_19 := 19 * f6 // 1.31*2^30 + f7_38 := 38 * f7 // 1.31*2^30 + f8_19 := 19 * f8 // 1.31*2^30 + f9_38 := 38 * f9 // 1.31*2^30 + f0f0 := int64(f0) * int64(f0) + f0f1_2 := int64(f0_2) * int64(f1) + f0f2_2 := int64(f0_2) * int64(f2) + f0f3_2 := int64(f0_2) * int64(f3) + f0f4_2 := int64(f0_2) * int64(f4) + f0f5_2 := int64(f0_2) * int64(f5) + f0f6_2 := int64(f0_2) * int64(f6) + f0f7_2 := int64(f0_2) * int64(f7) + f0f8_2 := int64(f0_2) * int64(f8) + f0f9_2 := int64(f0_2) * int64(f9) + f1f1_2 := int64(f1_2) * int64(f1) + f1f2_2 := int64(f1_2) * int64(f2) + f1f3_4 := int64(f1_2) * int64(f3_2) + f1f4_2 := int64(f1_2) * int64(f4) + f1f5_4 := int64(f1_2) * int64(f5_2) + f1f6_2 := int64(f1_2) * int64(f6) + f1f7_4 := int64(f1_2) * int64(f7_2) + f1f8_2 := int64(f1_2) * int64(f8) + f1f9_76 := int64(f1_2) * int64(f9_38) + f2f2 := int64(f2) * int64(f2) + f2f3_2 := int64(f2_2) * int64(f3) + f2f4_2 := int64(f2_2) * int64(f4) + f2f5_2 := int64(f2_2) * int64(f5) + f2f6_2 := int64(f2_2) * int64(f6) + f2f7_2 := int64(f2_2) * int64(f7) + f2f8_38 := int64(f2_2) * int64(f8_19) + f2f9_38 := int64(f2) * int64(f9_38) + f3f3_2 := int64(f3_2) * int64(f3) + f3f4_2 := int64(f3_2) * int64(f4) + f3f5_4 := int64(f3_2) * int64(f5_2) + f3f6_2 := int64(f3_2) * int64(f6) + f3f7_76 := int64(f3_2) * int64(f7_38) + f3f8_38 := int64(f3_2) * int64(f8_19) + f3f9_76 := int64(f3_2) * int64(f9_38) + f4f4 := int64(f4) * int64(f4) + f4f5_2 := int64(f4_2) * int64(f5) + f4f6_38 := int64(f4_2) * int64(f6_19) + f4f7_38 := int64(f4) * int64(f7_38) + f4f8_38 := int64(f4_2) * int64(f8_19) + f4f9_38 := int64(f4) * int64(f9_38) + f5f5_38 := int64(f5) * int64(f5_38) + f5f6_38 := int64(f5_2) * int64(f6_19) + f5f7_76 := int64(f5_2) * int64(f7_38) + f5f8_38 := int64(f5_2) * int64(f8_19) + f5f9_76 := int64(f5_2) * int64(f9_38) + f6f6_19 := int64(f6) * int64(f6_19) + f6f7_38 := int64(f6) * int64(f7_38) + f6f8_38 := int64(f6_2) * int64(f8_19) + f6f9_38 := int64(f6) * int64(f9_38) + f7f7_38 := int64(f7) * int64(f7_38) + f7f8_38 := int64(f7_2) * int64(f8_19) + f7f9_76 := int64(f7_2) * int64(f9_38) + f8f8_19 := int64(f8) * int64(f8_19) + f8f9_38 := int64(f8) * int64(f9_38) + f9f9_38 := int64(f9) * int64(f9_38) + h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 + h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 + h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 + h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 + h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 + h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 + h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 + h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 + h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 + h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 + var carry [10]int64 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feMul121666 calculates h = f * 121666. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feMul121666(h, f *fieldElement) { + h0 := int64(f[0]) * 121666 + h1 := int64(f[1]) * 121666 + h2 := int64(f[2]) * 121666 + h3 := int64(f[3]) * 121666 + h4 := int64(f[4]) * 121666 + h5 := int64(f[5]) * 121666 + h6 := int64(f[6]) * 121666 + h7 := int64(f[7]) * 121666 + h8 := int64(f[8]) * 121666 + h9 := int64(f[9]) * 121666 + var carry [10]int64 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feInvert sets out = z^-1. +func feInvert(out, z *fieldElement) { + var t0, t1, t2, t3 fieldElement + var i int + + feSquare(&t0, z) + for i = 1; i < 1; i++ { + feSquare(&t0, &t0) + } + feSquare(&t1, &t0) + for i = 1; i < 2; i++ { + feSquare(&t1, &t1) + } + feMul(&t1, z, &t1) + feMul(&t0, &t0, &t1) + feSquare(&t2, &t0) + for i = 1; i < 1; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t1, &t2) + feSquare(&t2, &t1) + for i = 1; i < 5; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 20; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 100; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t1, &t1) + for i = 1; i < 5; i++ { + feSquare(&t1, &t1) + } + feMul(out, &t1, &t0) +} + +func scalarMult(out, in, base *[32]byte) { + var e [32]byte + + copy(e[:], in[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement + feFromBytes(&x1, base) + feOne(&x2) + feCopy(&x3, &x1) + feOne(&z3) + + swap := int32(0) + for pos := 254; pos >= 0; pos-- { + b := e[pos/8] >> uint(pos&7) + b &= 1 + swap ^= int32(b) + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + swap = int32(b) + + feSub(&tmp0, &x3, &z3) + feSub(&tmp1, &x2, &z2) + feAdd(&x2, &x2, &z2) + feAdd(&z2, &x3, &z3) + feMul(&z3, &tmp0, &x2) + feMul(&z2, &z2, &tmp1) + feSquare(&tmp0, &tmp1) + feSquare(&tmp1, &x2) + feAdd(&x3, &z3, &z2) + feSub(&z2, &z3, &z2) + feMul(&x2, &tmp1, &tmp0) + feSub(&tmp1, &tmp1, &tmp0) + feSquare(&z2, &z2) + feMul121666(&z3, &tmp1) + feSquare(&x3, &x3) + feAdd(&tmp0, &tmp0, &z3) + feMul(&z3, &x1, &z2) + feMul(&z2, &tmp1, &tmp0) + } + + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + + feInvert(&z2, &z2) + feMul(&x2, &x2, &z2) + feToBytes(out, &x2) +} diff --git a/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go new file mode 100644 index 000000000..f7db9c1ce --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/doc.go @@ -0,0 +1,23 @@ +// Copyright 2012 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. + +// Package curve25519 provides an implementation of scalar multiplication on +// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html +package curve25519 + +// basePoint is the x coordinate of the generator of the curve. +var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +// ScalarMult sets dst to the product in*base where dst and base are the x +// coordinates of group points and all values are in little-endian form. +func ScalarMult(dst, in, base *[32]byte) { + scalarMult(dst, in, base) +} + +// ScalarBaseMult sets dst to the product in*base where dst and base are the x +// coordinates of group points, base is the standard generator and all values +// are in little-endian form. +func ScalarBaseMult(dst, in *[32]byte) { + ScalarMult(dst, in, &basePoint) +} diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s new file mode 100644 index 000000000..37599fac0 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s @@ -0,0 +1,94 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func freeze(inout *[5]uint64) +TEXT ·freeze(SB),7,$96-8 + MOVQ inout+0(FP), DI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 0(DI),SI + MOVQ 8(DI),DX + MOVQ 16(DI),CX + MOVQ 24(DI),R8 + MOVQ 32(DI),R9 + MOVQ ·REDMASK51(SB),AX + MOVQ AX,R10 + SUBQ $18,R10 + MOVQ $3,R11 +REDUCELOOP: + MOVQ SI,R12 + SHRQ $51,R12 + ANDQ AX,SI + ADDQ R12,DX + MOVQ DX,R12 + SHRQ $51,R12 + ANDQ AX,DX + ADDQ R12,CX + MOVQ CX,R12 + SHRQ $51,R12 + ANDQ AX,CX + ADDQ R12,R8 + MOVQ R8,R12 + SHRQ $51,R12 + ANDQ AX,R8 + ADDQ R12,R9 + MOVQ R9,R12 + SHRQ $51,R12 + ANDQ AX,R9 + IMUL3Q $19,R12,R12 + ADDQ R12,SI + SUBQ $1,R11 + JA REDUCELOOP + MOVQ $1,R12 + CMPQ R10,SI + CMOVQLT R11,R12 + CMPQ AX,DX + CMOVQNE R11,R12 + CMPQ AX,CX + CMOVQNE R11,R12 + CMPQ AX,R8 + CMOVQNE R11,R12 + CMPQ AX,R9 + CMOVQNE R11,R12 + NEGQ R12 + ANDQ R12,AX + ANDQ R12,R10 + SUBQ R10,SI + SUBQ AX,DX + SUBQ AX,CX + SUBQ AX,R8 + SUBQ AX,R9 + MOVQ SI,0(DI) + MOVQ DX,8(DI) + MOVQ CX,16(DI) + MOVQ R8,24(DI) + MOVQ R9,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s new file mode 100644 index 000000000..3949f9cfa --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s @@ -0,0 +1,1398 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func ladderstep(inout *[5][5]uint64) +TEXT ·ladderstep(SB),0,$384-8 + MOVQ inout+0(FP),DI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 40(DI),SI + MOVQ 48(DI),DX + MOVQ 56(DI),CX + MOVQ 64(DI),R8 + MOVQ 72(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 80(DI),SI + ADDQ 88(DI),DX + ADDQ 96(DI),CX + ADDQ 104(DI),R8 + ADDQ 112(DI),R9 + SUBQ 80(DI),AX + SUBQ 88(DI),R10 + SUBQ 96(DI),R11 + SUBQ 104(DI),R12 + SUBQ 112(DI),R13 + MOVQ SI,56(SP) + MOVQ DX,64(SP) + MOVQ CX,72(SP) + MOVQ R8,80(SP) + MOVQ R9,88(SP) + MOVQ AX,96(SP) + MOVQ R10,104(SP) + MOVQ R11,112(SP) + MOVQ R12,120(SP) + MOVQ R13,128(SP) + MOVQ 96(SP),AX + MULQ 96(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 104(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 112(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 120(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 128(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 104(SP),AX + MULQ 104(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 104(SP),AX + SHLQ $1,AX + MULQ 112(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 104(SP),AX + SHLQ $1,AX + MULQ 120(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 104(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 112(SP),AX + MULQ 112(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 112(SP),DX + IMUL3Q $38,DX,AX + MULQ 120(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 112(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 120(SP),DX + IMUL3Q $19,DX,AX + MULQ 120(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 120(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,136(SP) + MOVQ R8,144(SP) + MOVQ R9,152(SP) + MOVQ AX,160(SP) + MOVQ R10,168(SP) + MOVQ 56(SP),AX + MULQ 56(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 64(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 72(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 80(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 88(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 64(SP),AX + MULQ 64(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + SHLQ $1,AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 64(SP),AX + SHLQ $1,AX + MULQ 80(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 72(SP),AX + MULQ 72(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 72(SP),DX + IMUL3Q $38,DX,AX + MULQ 80(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 72(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 80(SP),DX + IMUL3Q $19,DX,AX + MULQ 80(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 80(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 88(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,176(SP) + MOVQ R8,184(SP) + MOVQ R9,192(SP) + MOVQ AX,200(SP) + MOVQ R10,208(SP) + MOVQ SI,SI + MOVQ R8,DX + MOVQ R9,CX + MOVQ AX,R8 + MOVQ R10,R9 + ADDQ ·_2P0(SB),SI + ADDQ ·_2P1234(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R8 + ADDQ ·_2P1234(SB),R9 + SUBQ 136(SP),SI + SUBQ 144(SP),DX + SUBQ 152(SP),CX + SUBQ 160(SP),R8 + SUBQ 168(SP),R9 + MOVQ SI,216(SP) + MOVQ DX,224(SP) + MOVQ CX,232(SP) + MOVQ R8,240(SP) + MOVQ R9,248(SP) + MOVQ 120(DI),SI + MOVQ 128(DI),DX + MOVQ 136(DI),CX + MOVQ 144(DI),R8 + MOVQ 152(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 160(DI),SI + ADDQ 168(DI),DX + ADDQ 176(DI),CX + ADDQ 184(DI),R8 + ADDQ 192(DI),R9 + SUBQ 160(DI),AX + SUBQ 168(DI),R10 + SUBQ 176(DI),R11 + SUBQ 184(DI),R12 + SUBQ 192(DI),R13 + MOVQ SI,256(SP) + MOVQ DX,264(SP) + MOVQ CX,272(SP) + MOVQ R8,280(SP) + MOVQ R9,288(SP) + MOVQ AX,296(SP) + MOVQ R10,304(SP) + MOVQ R11,312(SP) + MOVQ R12,320(SP) + MOVQ R13,328(SP) + MOVQ 280(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,336(SP) + MULQ 112(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 288(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,344(SP) + MULQ 104(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),AX + MULQ 96(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),AX + MULQ 104(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 256(SP),AX + MULQ 112(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 256(SP),AX + MULQ 120(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 256(SP),AX + MULQ 128(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 264(SP),AX + MULQ 96(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 264(SP),AX + MULQ 104(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 264(SP),AX + MULQ 112(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 264(SP),AX + MULQ 120(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 264(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 272(SP),AX + MULQ 96(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 272(SP),AX + MULQ 104(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 272(SP),AX + MULQ 112(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 272(SP),DX + IMUL3Q $19,DX,AX + MULQ 120(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 272(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 280(SP),AX + MULQ 96(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 280(SP),AX + MULQ 104(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 336(SP),AX + MULQ 120(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 336(SP),AX + MULQ 128(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 288(SP),AX + MULQ 96(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 344(SP),AX + MULQ 112(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 344(SP),AX + MULQ 120(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 344(SP),AX + MULQ 128(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,96(SP) + MOVQ R8,104(SP) + MOVQ R9,112(SP) + MOVQ AX,120(SP) + MOVQ R10,128(SP) + MOVQ 320(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,256(SP) + MULQ 72(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 328(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,264(SP) + MULQ 64(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 296(SP),AX + MULQ 56(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 296(SP),AX + MULQ 64(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 296(SP),AX + MULQ 72(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 296(SP),AX + MULQ 80(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 296(SP),AX + MULQ 88(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 304(SP),AX + MULQ 56(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 304(SP),AX + MULQ 64(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 304(SP),AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 304(SP),AX + MULQ 80(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 304(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 312(SP),AX + MULQ 56(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 312(SP),AX + MULQ 64(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 312(SP),AX + MULQ 72(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 312(SP),DX + IMUL3Q $19,DX,AX + MULQ 80(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 312(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 320(SP),AX + MULQ 56(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 320(SP),AX + MULQ 64(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 256(SP),AX + MULQ 80(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 256(SP),AX + MULQ 88(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 328(SP),AX + MULQ 56(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 264(SP),AX + MULQ 72(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 264(SP),AX + MULQ 80(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 264(SP),AX + MULQ 88(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,DX + MOVQ R8,CX + MOVQ R9,R11 + MOVQ AX,R12 + MOVQ R10,R13 + ADDQ ·_2P0(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 96(SP),SI + ADDQ 104(SP),R8 + ADDQ 112(SP),R9 + ADDQ 120(SP),AX + ADDQ 128(SP),R10 + SUBQ 96(SP),DX + SUBQ 104(SP),CX + SUBQ 112(SP),R11 + SUBQ 120(SP),R12 + SUBQ 128(SP),R13 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ DX,160(DI) + MOVQ CX,168(DI) + MOVQ R11,176(DI) + MOVQ R12,184(DI) + MOVQ R13,192(DI) + MOVQ 120(DI),AX + MULQ 120(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 128(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 136(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 144(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 152(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 128(DI),AX + MULQ 128(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 136(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 144(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 128(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),AX + MULQ 136(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 144(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $19,DX,AX + MULQ 144(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 152(DI),DX + IMUL3Q $19,DX,AX + MULQ 152(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ 160(DI),AX + MULQ 160(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 168(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 176(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 184(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 192(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 168(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 176(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 184(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 176(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 184(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $19,DX,AX + MULQ 184(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MULQ 192(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 184(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 16(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 8(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 0(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 8(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + MULQ 16(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + MULQ 24(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + MULQ 32(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 0(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 168(DI),AX + MULQ 8(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + MULQ 16(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + MULQ 24(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 0(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 176(DI),AX + MULQ 8(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 176(DI),AX + MULQ 16(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 24(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),AX + MULQ 0(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 184(DI),AX + MULQ 8(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 24(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 32(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),AX + MULQ 0(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 16(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 24(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 32(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 200(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 152(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 208(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 144(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(SP),AX + MULQ 136(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(SP),AX + MULQ 144(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 176(SP),AX + MULQ 152(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 176(SP),AX + MULQ 160(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 176(SP),AX + MULQ 168(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 184(SP),AX + MULQ 136(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(SP),AX + MULQ 144(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 184(SP),AX + MULQ 152(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 184(SP),AX + MULQ 160(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 184(SP),DX + IMUL3Q $19,DX,AX + MULQ 168(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 192(SP),AX + MULQ 136(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(SP),AX + MULQ 144(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 192(SP),AX + MULQ 152(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 192(SP),DX + IMUL3Q $19,DX,AX + MULQ 160(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 192(SP),DX + IMUL3Q $19,DX,AX + MULQ 168(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 200(SP),AX + MULQ 136(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 200(SP),AX + MULQ 144(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 160(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 168(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 208(SP),AX + MULQ 136(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 152(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 160(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 168(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,40(DI) + MOVQ R8,48(DI) + MOVQ R9,56(DI) + MOVQ AX,64(DI) + MOVQ R10,72(DI) + MOVQ 216(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + MOVQ AX,SI + MOVQ DX,CX + MOVQ 224(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,CX + MOVQ DX,R8 + MOVQ 232(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R8 + MOVQ DX,R9 + MOVQ 240(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R9 + MOVQ DX,R10 + MOVQ 248(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R10 + IMUL3Q $19,DX,DX + ADDQ DX,SI + ADDQ 136(SP),SI + ADDQ 144(SP),CX + ADDQ 152(SP),R8 + ADDQ 160(SP),R9 + ADDQ 168(SP),R10 + MOVQ SI,80(DI) + MOVQ CX,88(DI) + MOVQ R8,96(DI) + MOVQ R9,104(DI) + MOVQ R10,112(DI) + MOVQ 104(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 232(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 112(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 224(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 216(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 224(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 80(DI),AX + MULQ 232(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 80(DI),AX + MULQ 240(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 80(DI),AX + MULQ 248(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 88(DI),AX + MULQ 216(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 88(DI),AX + MULQ 224(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 88(DI),AX + MULQ 232(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 88(DI),AX + MULQ 240(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 88(DI),DX + IMUL3Q $19,DX,AX + MULQ 248(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),AX + MULQ 216(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 96(DI),AX + MULQ 224(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 96(DI),AX + MULQ 232(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 240(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 248(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 104(DI),AX + MULQ 216(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 104(DI),AX + MULQ 224(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 240(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 248(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 112(DI),AX + MULQ 216(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 232(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 240(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 248(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,80(DI) + MOVQ R8,88(DI) + MOVQ R9,96(DI) + MOVQ AX,104(DI) + MOVQ R10,112(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go new file mode 100644 index 000000000..5822bd533 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go @@ -0,0 +1,240 @@ +// Copyright 2012 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. + +// +build amd64,!gccgo,!appengine + +package curve25519 + +// These functions are implemented in the .s files. The names of the functions +// in the rest of the file are also taken from the SUPERCOP sources to help +// people following along. + +//go:noescape + +func cswap(inout *[5]uint64, v uint64) + +//go:noescape + +func ladderstep(inout *[5][5]uint64) + +//go:noescape + +func freeze(inout *[5]uint64) + +//go:noescape + +func mul(dest, a, b *[5]uint64) + +//go:noescape + +func square(out, in *[5]uint64) + +// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. +func mladder(xr, zr *[5]uint64, s *[32]byte) { + var work [5][5]uint64 + + work[0] = *xr + setint(&work[1], 1) + setint(&work[2], 0) + work[3] = *xr + setint(&work[4], 1) + + j := uint(6) + var prevbit byte + + for i := 31; i >= 0; i-- { + for j < 8 { + bit := ((*s)[i] >> j) & 1 + swap := bit ^ prevbit + prevbit = bit + cswap(&work[1], uint64(swap)) + ladderstep(&work) + j-- + } + j = 7 + } + + *xr = work[1] + *zr = work[2] +} + +func scalarMult(out, in, base *[32]byte) { + var e [32]byte + copy(e[:], (*in)[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var t, z [5]uint64 + unpack(&t, base) + mladder(&t, &z, &e) + invert(&z, &z) + mul(&t, &t, &z) + pack(out, &t) +} + +func setint(r *[5]uint64, v uint64) { + r[0] = v + r[1] = 0 + r[2] = 0 + r[3] = 0 + r[4] = 0 +} + +// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian +// order. +func unpack(r *[5]uint64, x *[32]byte) { + r[0] = uint64(x[0]) | + uint64(x[1])<<8 | + uint64(x[2])<<16 | + uint64(x[3])<<24 | + uint64(x[4])<<32 | + uint64(x[5])<<40 | + uint64(x[6]&7)<<48 + + r[1] = uint64(x[6])>>3 | + uint64(x[7])<<5 | + uint64(x[8])<<13 | + uint64(x[9])<<21 | + uint64(x[10])<<29 | + uint64(x[11])<<37 | + uint64(x[12]&63)<<45 + + r[2] = uint64(x[12])>>6 | + uint64(x[13])<<2 | + uint64(x[14])<<10 | + uint64(x[15])<<18 | + uint64(x[16])<<26 | + uint64(x[17])<<34 | + uint64(x[18])<<42 | + uint64(x[19]&1)<<50 + + r[3] = uint64(x[19])>>1 | + uint64(x[20])<<7 | + uint64(x[21])<<15 | + uint64(x[22])<<23 | + uint64(x[23])<<31 | + uint64(x[24])<<39 | + uint64(x[25]&15)<<47 + + r[4] = uint64(x[25])>>4 | + uint64(x[26])<<4 | + uint64(x[27])<<12 | + uint64(x[28])<<20 | + uint64(x[29])<<28 | + uint64(x[30])<<36 | + uint64(x[31]&127)<<44 +} + +// pack sets out = x where out is the usual, little-endian form of the 5, +// 51-bit limbs in x. +func pack(out *[32]byte, x *[5]uint64) { + t := *x + freeze(&t) + + out[0] = byte(t[0]) + out[1] = byte(t[0] >> 8) + out[2] = byte(t[0] >> 16) + out[3] = byte(t[0] >> 24) + out[4] = byte(t[0] >> 32) + out[5] = byte(t[0] >> 40) + out[6] = byte(t[0] >> 48) + + out[6] ^= byte(t[1]<<3) & 0xf8 + out[7] = byte(t[1] >> 5) + out[8] = byte(t[1] >> 13) + out[9] = byte(t[1] >> 21) + out[10] = byte(t[1] >> 29) + out[11] = byte(t[1] >> 37) + out[12] = byte(t[1] >> 45) + + out[12] ^= byte(t[2]<<6) & 0xc0 + out[13] = byte(t[2] >> 2) + out[14] = byte(t[2] >> 10) + out[15] = byte(t[2] >> 18) + out[16] = byte(t[2] >> 26) + out[17] = byte(t[2] >> 34) + out[18] = byte(t[2] >> 42) + out[19] = byte(t[2] >> 50) + + out[19] ^= byte(t[3]<<1) & 0xfe + out[20] = byte(t[3] >> 7) + out[21] = byte(t[3] >> 15) + out[22] = byte(t[3] >> 23) + out[23] = byte(t[3] >> 31) + out[24] = byte(t[3] >> 39) + out[25] = byte(t[3] >> 47) + + out[25] ^= byte(t[4]<<4) & 0xf0 + out[26] = byte(t[4] >> 4) + out[27] = byte(t[4] >> 12) + out[28] = byte(t[4] >> 20) + out[29] = byte(t[4] >> 28) + out[30] = byte(t[4] >> 36) + out[31] = byte(t[4] >> 44) +} + +// invert calculates r = x^-1 mod p using Fermat's little theorem. +func invert(r *[5]uint64, x *[5]uint64) { + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 + + square(&z2, x) /* 2 */ + square(&t, &z2) /* 4 */ + square(&t, &t) /* 8 */ + mul(&z9, &t, x) /* 9 */ + mul(&z11, &z9, &z2) /* 11 */ + square(&t, &z11) /* 22 */ + mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ + + square(&t, &z2_5_0) /* 2^6 - 2^1 */ + for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ + square(&t, &t) + } + mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ + + square(&t, &z2_10_0) /* 2^11 - 2^1 */ + for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ + square(&t, &t) + } + mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ + + square(&t, &z2_20_0) /* 2^21 - 2^1 */ + for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ + square(&t, &t) + } + mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ + + square(&t, &t) /* 2^41 - 2^1 */ + for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ + square(&t, &t) + } + mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ + + square(&t, &z2_50_0) /* 2^51 - 2^1 */ + for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ + square(&t, &t) + } + mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ + + square(&t, &z2_100_0) /* 2^101 - 2^1 */ + for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ + square(&t, &t) + } + mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ + + square(&t, &t) /* 2^201 - 2^1 */ + for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ + square(&t, &t) + } + mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ + + square(&t, &t) /* 2^251 - 2^1 */ + square(&t, &t) /* 2^252 - 2^2 */ + square(&t, &t) /* 2^253 - 2^3 */ + + square(&t, &t) /* 2^254 - 2^4 */ + + square(&t, &t) /* 2^255 - 2^5 */ + mul(r, &t, &z11) /* 2^255 - 21 */ +} diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s new file mode 100644 index 000000000..e48d183ee --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s @@ -0,0 +1,191 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func mul(dest, a, b *[5]uint64) +TEXT ·mul(SB),0,$128-24 + MOVQ dest+0(FP), DI + MOVQ a+8(FP), SI + MOVQ b+16(FP), DX + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ DI,56(SP) + MOVQ DX,CX + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 16(CX) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,72(SP) + MULQ 8(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 0(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 8(CX) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 0(SI),AX + MULQ 16(CX) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 0(SI),AX + MULQ 24(CX) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 0(SI),AX + MULQ 32(CX) + MOVQ AX,BX + MOVQ DX,BP + MOVQ 8(SI),AX + MULQ 0(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SI),AX + MULQ 8(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SI),AX + MULQ 16(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SI),AX + MULQ 24(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 8(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),AX + MULQ 0(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 16(SI),AX + MULQ 8(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 16(SI),AX + MULQ 16(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 24(SI),AX + MULQ 0(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 24(SI),AX + MULQ 8(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 64(SP),AX + MULQ 24(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 32(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 32(SI),AX + MULQ 0(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 72(SP),AX + MULQ 16(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 72(SP),AX + MULQ 24(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 72(SP),AX + MULQ 32(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ ·REDMASK51(SB),SI + SHLQ $13,R9:R8 + ANDQ SI,R8 + SHLQ $13,R11:R10 + ANDQ SI,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ SI,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ SI,R14 + ADDQ R13,R14 + SHLQ $13,BP:BX + ANDQ SI,BX + ADDQ R15,BX + IMUL3Q $19,BP,DX + ADDQ DX,R8 + MOVQ R8,DX + SHRQ $51,DX + ADDQ R10,DX + MOVQ DX,CX + SHRQ $51,DX + ANDQ SI,R8 + ADDQ R12,DX + MOVQ DX,R9 + SHRQ $51,DX + ANDQ SI,CX + ADDQ R14,DX + MOVQ DX,AX + SHRQ $51,DX + ANDQ SI,R9 + ADDQ BX,DX + MOVQ DX,R10 + SHRQ $51,DX + ANDQ SI,AX + IMUL3Q $19,DX,DX + ADDQ DX,R8 + ANDQ SI,R10 + MOVQ R8,0(DI) + MOVQ CX,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s new file mode 100644 index 000000000..78d1a50dd --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s @@ -0,0 +1,153 @@ +// Copyright 2012 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func square(out, in *[5]uint64) +TEXT ·square(SB),7,$96-16 + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32, SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 0(SI),AX + MULQ 0(SI) + MOVQ AX,CX + MOVQ DX,R8 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 8(SI) + MOVQ AX,R9 + MOVQ DX,R10 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 16(SI) + MOVQ AX,R11 + MOVQ DX,R12 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 24(SI) + MOVQ AX,R13 + MOVQ DX,R14 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 32(SI) + MOVQ AX,R15 + MOVQ DX,BX + MOVQ 8(SI),AX + MULQ 8(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 16(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 24(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 8(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),AX + MULQ 16(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 24(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ ·REDMASK51(SB),SI + SHLQ $13,R8:CX + ANDQ SI,CX + SHLQ $13,R10:R9 + ANDQ SI,R9 + ADDQ R8,R9 + SHLQ $13,R12:R11 + ANDQ SI,R11 + ADDQ R10,R11 + SHLQ $13,R14:R13 + ANDQ SI,R13 + ADDQ R12,R13 + SHLQ $13,BX:R15 + ANDQ SI,R15 + ADDQ R14,R15 + IMUL3Q $19,BX,DX + ADDQ DX,CX + MOVQ CX,DX + SHRQ $51,DX + ADDQ R9,DX + ANDQ SI,CX + MOVQ DX,R8 + SHRQ $51,DX + ADDQ R11,DX + ANDQ SI,R8 + MOVQ DX,R9 + SHRQ $51,DX + ADDQ R13,DX + ANDQ SI,R9 + MOVQ DX,AX + SHRQ $51,DX + ADDQ R15,DX + ANDQ SI,AX + MOVQ DX,R10 + SHRQ $51,DX + IMUL3Q $19,DX,DX + ADDQ DX,CX + ANDQ SI,R10 + MOVQ CX,0(DI) + MOVQ R8,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go new file mode 100644 index 000000000..d043c5bec --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/client.go @@ -0,0 +1,615 @@ +// Copyright 2012 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. + +/* + Package agent implements a client to an ssh-agent daemon. + +References: + [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD +*/ +package agent + +import ( + "bytes" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "encoding/base64" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "sync" + + "golang.org/x/crypto/ssh" +) + +// Agent represents the capabilities of an ssh-agent. +type Agent interface { + // List returns the identities known to the agent. + List() ([]*Key, error) + + // Sign has the agent sign the data using a protocol 2 key as defined + // in [PROTOCOL.agent] section 2.6.2. + Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) + + // Add adds a private key to the agent. + Add(key AddedKey) error + + // Remove removes all identities with the given public key. + Remove(key ssh.PublicKey) error + + // RemoveAll removes all identities. + RemoveAll() error + + // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. + Lock(passphrase []byte) error + + // Unlock undoes the effect of Lock + Unlock(passphrase []byte) error + + // Signers returns signers for all the known keys. + Signers() ([]ssh.Signer, error) +} + +// AddedKey describes an SSH key to be added to an Agent. +type AddedKey struct { + // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or + // *ecdsa.PrivateKey, which will be inserted into the agent. + PrivateKey interface{} + // Certificate, if not nil, is communicated to the agent and will be + // stored with the key. + Certificate *ssh.Certificate + // Comment is an optional, free-form string. + Comment string + // LifetimeSecs, if not zero, is the number of seconds that the + // agent will store the key for. + LifetimeSecs uint32 + // ConfirmBeforeUse, if true, requests that the agent confirm with the + // user before each use of this key. + ConfirmBeforeUse bool +} + +// See [PROTOCOL.agent], section 3. +const ( + agentRequestV1Identities = 1 + + // 3.2 Requests from client to agent for protocol 2 key operations + agentAddIdentity = 17 + agentRemoveIdentity = 18 + agentRemoveAllIdentities = 19 + agentAddIdConstrained = 25 + + // 3.3 Key-type independent requests from client to agent + agentAddSmartcardKey = 20 + agentRemoveSmartcardKey = 21 + agentLock = 22 + agentUnlock = 23 + agentAddSmartcardKeyConstrained = 26 + + // 3.7 Key constraint identifiers + agentConstrainLifetime = 1 + agentConstrainConfirm = 2 +) + +// maxAgentResponseBytes is the maximum agent reply size that is accepted. This +// is a sanity check, not a limit in the spec. +const maxAgentResponseBytes = 16 << 20 + +// Agent messages: +// These structures mirror the wire format of the corresponding ssh agent +// messages found in [PROTOCOL.agent]. + +// 3.4 Generic replies from agent to client +const agentFailure = 5 + +type failureAgentMsg struct{} + +const agentSuccess = 6 + +type successAgentMsg struct{} + +// See [PROTOCOL.agent], section 2.5.2. +const agentRequestIdentities = 11 + +type requestIdentitiesAgentMsg struct{} + +// See [PROTOCOL.agent], section 2.5.2. +const agentIdentitiesAnswer = 12 + +type identitiesAnswerAgentMsg struct { + NumKeys uint32 `sshtype:"12"` + Keys []byte `ssh:"rest"` +} + +// See [PROTOCOL.agent], section 2.6.2. +const agentSignRequest = 13 + +type signRequestAgentMsg struct { + KeyBlob []byte `sshtype:"13"` + Data []byte + Flags uint32 +} + +// See [PROTOCOL.agent], section 2.6.2. + +// 3.6 Replies from agent to client for protocol 2 key operations +const agentSignResponse = 14 + +type signResponseAgentMsg struct { + SigBlob []byte `sshtype:"14"` +} + +type publicKey struct { + Format string + Rest []byte `ssh:"rest"` +} + +// Key represents a protocol 2 public key as defined in +// [PROTOCOL.agent], section 2.5.2. +type Key struct { + Format string + Blob []byte + Comment string +} + +func clientErr(err error) error { + return fmt.Errorf("agent: client error: %v", err) +} + +// String returns the storage form of an agent key with the format, base64 +// encoded serialized key, and the comment if it is not empty. +func (k *Key) String() string { + s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) + + if k.Comment != "" { + s += " " + k.Comment + } + + return s +} + +// Type returns the public key type. +func (k *Key) Type() string { + return k.Format +} + +// Marshal returns key blob to satisfy the ssh.PublicKey interface. +func (k *Key) Marshal() []byte { + return k.Blob +} + +// Verify satisfies the ssh.PublicKey interface, but is not +// implemented for agent keys. +func (k *Key) Verify(data []byte, sig *ssh.Signature) error { + return errors.New("agent: agent key does not know how to verify") +} + +type wireKey struct { + Format string + Rest []byte `ssh:"rest"` +} + +func parseKey(in []byte) (out *Key, rest []byte, err error) { + var record struct { + Blob []byte + Comment string + Rest []byte `ssh:"rest"` + } + + if err := ssh.Unmarshal(in, &record); err != nil { + return nil, nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(record.Blob, &wk); err != nil { + return nil, nil, err + } + + return &Key{ + Format: wk.Format, + Blob: record.Blob, + Comment: record.Comment, + }, record.Rest, nil +} + +// client is a client for an ssh-agent process. +type client struct { + // conn is typically a *net.UnixConn + conn io.ReadWriter + // mu is used to prevent concurrent access to the agent + mu sync.Mutex +} + +// NewClient returns an Agent that talks to an ssh-agent process over +// the given connection. +func NewClient(rw io.ReadWriter) Agent { + return &client{conn: rw} +} + +// call sends an RPC to the agent. On success, the reply is +// unmarshaled into reply and replyType is set to the first byte of +// the reply, which contains the type of the message. +func (c *client) call(req []byte) (reply interface{}, err error) { + c.mu.Lock() + defer c.mu.Unlock() + + msg := make([]byte, 4+len(req)) + binary.BigEndian.PutUint32(msg, uint32(len(req))) + copy(msg[4:], req) + if _, err = c.conn.Write(msg); err != nil { + return nil, clientErr(err) + } + + var respSizeBuf [4]byte + if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { + return nil, clientErr(err) + } + respSize := binary.BigEndian.Uint32(respSizeBuf[:]) + if respSize > maxAgentResponseBytes { + return nil, clientErr(err) + } + + buf := make([]byte, respSize) + if _, err = io.ReadFull(c.conn, buf); err != nil { + return nil, clientErr(err) + } + reply, err = unmarshal(buf) + if err != nil { + return nil, clientErr(err) + } + return reply, err +} + +func (c *client) simpleCall(req []byte) error { + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +func (c *client) RemoveAll() error { + return c.simpleCall([]byte{agentRemoveAllIdentities}) +} + +func (c *client) Remove(key ssh.PublicKey) error { + req := ssh.Marshal(&agentRemoveIdentityMsg{ + KeyBlob: key.Marshal(), + }) + return c.simpleCall(req) +} + +func (c *client) Lock(passphrase []byte) error { + req := ssh.Marshal(&agentLockMsg{ + Passphrase: passphrase, + }) + return c.simpleCall(req) +} + +func (c *client) Unlock(passphrase []byte) error { + req := ssh.Marshal(&agentUnlockMsg{ + Passphrase: passphrase, + }) + return c.simpleCall(req) +} + +// List returns the identities known to the agent. +func (c *client) List() ([]*Key, error) { + // see [PROTOCOL.agent] section 2.5.2. + req := []byte{agentRequestIdentities} + + msg, err := c.call(req) + if err != nil { + return nil, err + } + + switch msg := msg.(type) { + case *identitiesAnswerAgentMsg: + if msg.NumKeys > maxAgentResponseBytes/8 { + return nil, errors.New("agent: too many keys in agent reply") + } + keys := make([]*Key, msg.NumKeys) + data := msg.Keys + for i := uint32(0); i < msg.NumKeys; i++ { + var key *Key + var err error + if key, data, err = parseKey(data); err != nil { + return nil, err + } + keys[i] = key + } + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") + } + panic("unreachable") +} + +// Sign has the agent sign the data using a protocol 2 key as defined +// in [PROTOCOL.agent] section 2.6.2. +func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { + req := ssh.Marshal(signRequestAgentMsg{ + KeyBlob: key.Marshal(), + Data: data, + }) + + msg, err := c.call(req) + if err != nil { + return nil, err + } + + switch msg := msg.(type) { + case *signResponseAgentMsg: + var sig ssh.Signature + if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { + return nil, err + } + + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") + } + panic("unreachable") +} + +// unmarshal parses an agent message in packet, returning the parsed +// form and the message type of packet. +func unmarshal(packet []byte) (interface{}, error) { + if len(packet) < 1 { + return nil, errors.New("agent: empty packet") + } + var msg interface{} + switch packet[0] { + case agentFailure: + return new(failureAgentMsg), nil + case agentSuccess: + return new(successAgentMsg), nil + case agentIdentitiesAnswer: + msg = new(identitiesAnswerAgentMsg) + case agentSignResponse: + msg = new(signResponseAgentMsg) + default: + return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) + } + if err := ssh.Unmarshal(packet, msg); err != nil { + return nil, err + } + return msg, nil +} + +type rsaKeyMsg struct { + Type string `sshtype:"17"` + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int // IQMP = Inverse Q Mod P + P *big.Int + Q *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type dsaKeyMsg struct { + Type string `sshtype:"17"` + P *big.Int + Q *big.Int + G *big.Int + Y *big.Int + X *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ecdsaKeyMsg struct { + Type string `sshtype:"17"` + Curve string + KeyBytes []byte + D *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +// Insert adds a private key to the agent. +func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { + var req []byte + switch k := s.(type) { + case *rsa.PrivateKey: + if len(k.Primes) != 2 { + return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) + } + k.Precompute() + req = ssh.Marshal(rsaKeyMsg{ + Type: ssh.KeyAlgoRSA, + N: k.N, + E: big.NewInt(int64(k.E)), + D: k.D, + Iqmp: k.Precomputed.Qinv, + P: k.Primes[0], + Q: k.Primes[1], + Comments: comment, + Constraints: constraints, + }) + case *dsa.PrivateKey: + req = ssh.Marshal(dsaKeyMsg{ + Type: ssh.KeyAlgoDSA, + P: k.P, + Q: k.Q, + G: k.G, + Y: k.Y, + X: k.X, + Comments: comment, + Constraints: constraints, + }) + case *ecdsa.PrivateKey: + nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) + req = ssh.Marshal(ecdsaKeyMsg{ + Type: "ecdsa-sha2-" + nistID, + Curve: nistID, + KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), + D: k.D, + Comments: comment, + Constraints: constraints, + }) + default: + return fmt.Errorf("agent: unsupported key type %T", s) + } + + // if constraints are present then the message type needs to be changed. + if len(constraints) != 0 { + req[0] = agentAddIdConstrained + } + + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +type rsaCertMsg struct { + Type string `sshtype:"17"` + CertBytes []byte + D *big.Int + Iqmp *big.Int // IQMP = Inverse Q Mod P + P *big.Int + Q *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type dsaCertMsg struct { + Type string `sshtype:"17"` + CertBytes []byte + X *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ecdsaCertMsg struct { + Type string `sshtype:"17"` + CertBytes []byte + D *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +// Insert adds a private key to the agent. If a certificate is given, +// that certificate is added instead as public key. +func (c *client) Add(key AddedKey) error { + var constraints []byte + + if secs := key.LifetimeSecs; secs != 0 { + constraints = append(constraints, agentConstrainLifetime) + + var secsBytes [4]byte + binary.BigEndian.PutUint32(secsBytes[:], secs) + constraints = append(constraints, secsBytes[:]...) + } + + if key.ConfirmBeforeUse { + constraints = append(constraints, agentConstrainConfirm) + } + + if cert := key.Certificate; cert == nil { + return c.insertKey(key.PrivateKey, key.Comment, constraints) + } else { + return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) + } +} + +func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { + var req []byte + switch k := s.(type) { + case *rsa.PrivateKey: + if len(k.Primes) != 2 { + return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) + } + k.Precompute() + req = ssh.Marshal(rsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + D: k.D, + Iqmp: k.Precomputed.Qinv, + P: k.Primes[0], + Q: k.Primes[1], + Comments: comment, + Constraints: constraints, + }) + case *dsa.PrivateKey: + req = ssh.Marshal(dsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + X: k.X, + Comments: comment, + }) + case *ecdsa.PrivateKey: + req = ssh.Marshal(ecdsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + D: k.D, + Comments: comment, + }) + default: + return fmt.Errorf("agent: unsupported key type %T", s) + } + + // if constraints are present then the message type needs to be changed. + if len(constraints) != 0 { + req[0] = agentAddIdConstrained + } + + signer, err := ssh.NewSignerFromKey(s) + if err != nil { + return err + } + if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + return errors.New("agent: signer and cert have different public key") + } + + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +// Signers provides a callback for client authentication. +func (c *client) Signers() ([]ssh.Signer, error) { + keys, err := c.List() + if err != nil { + return nil, err + } + + var result []ssh.Signer + for _, k := range keys { + result = append(result, &agentKeyringSigner{c, k}) + } + return result, nil +} + +type agentKeyringSigner struct { + agent *client + pub ssh.PublicKey +} + +func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { + return s.pub +} + +func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { + // The agent has its own entropy source, so the rand argument is ignored. + return s.agent.Sign(s.pub, data) +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/golang.org/x/crypto/ssh/agent/forward.go new file mode 100644 index 000000000..fd24ba900 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/forward.go @@ -0,0 +1,103 @@ +// Copyright 2014 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. + +package agent + +import ( + "errors" + "io" + "net" + "sync" + + "golang.org/x/crypto/ssh" +) + +// RequestAgentForwarding sets up agent forwarding for the session. +// ForwardToAgent or ForwardToRemote should be called to route +// the authentication requests. +func RequestAgentForwarding(session *ssh.Session) error { + ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) + if err != nil { + return err + } + if !ok { + return errors.New("forwarding request denied") + } + return nil +} + +// ForwardToAgent routes authentication requests to the given keyring. +func ForwardToAgent(client *ssh.Client, keyring Agent) error { + channels := client.HandleChannelOpen(channelType) + if channels == nil { + return errors.New("agent: already have handler for " + channelType) + } + + go func() { + for ch := range channels { + channel, reqs, err := ch.Accept() + if err != nil { + continue + } + go ssh.DiscardRequests(reqs) + go func() { + ServeAgent(keyring, channel) + channel.Close() + }() + } + }() + return nil +} + +const channelType = "auth-agent@openssh.com" + +// ForwardToRemote routes authentication requests to the ssh-agent +// process serving on the given unix socket. +func ForwardToRemote(client *ssh.Client, addr string) error { + channels := client.HandleChannelOpen(channelType) + if channels == nil { + return errors.New("agent: already have handler for " + channelType) + } + conn, err := net.Dial("unix", addr) + if err != nil { + return err + } + conn.Close() + + go func() { + for ch := range channels { + channel, reqs, err := ch.Accept() + if err != nil { + continue + } + go ssh.DiscardRequests(reqs) + go forwardUnixSocket(channel, addr) + } + }() + return nil +} + +func forwardUnixSocket(channel ssh.Channel, addr string) { + conn, err := net.Dial("unix", addr) + if err != nil { + return + } + + var wg sync.WaitGroup + wg.Add(2) + go func() { + io.Copy(conn, channel) + conn.(*net.UnixConn).CloseWrite() + wg.Done() + }() + go func() { + io.Copy(channel, conn) + channel.CloseWrite() + wg.Done() + }() + + wg.Wait() + conn.Close() + channel.Close() +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go new file mode 100644 index 000000000..12ffa82b1 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -0,0 +1,184 @@ +// Copyright 2014 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. + +package agent + +import ( + "bytes" + "crypto/rand" + "crypto/subtle" + "errors" + "fmt" + "sync" + + "golang.org/x/crypto/ssh" +) + +type privKey struct { + signer ssh.Signer + comment string +} + +type keyring struct { + mu sync.Mutex + keys []privKey + + locked bool + passphrase []byte +} + +var errLocked = errors.New("agent: locked") + +// NewKeyring returns an Agent that holds keys in memory. It is safe +// for concurrent use by multiple goroutines. +func NewKeyring() Agent { + return &keyring{} +} + +// RemoveAll removes all identities. +func (r *keyring) RemoveAll() error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + r.keys = nil + return nil +} + +// Remove removes all identities with the given public key. +func (r *keyring) Remove(key ssh.PublicKey) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + want := key.Marshal() + found := false + for i := 0; i < len(r.keys); { + if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { + found = true + r.keys[i] = r.keys[len(r.keys)-1] + r.keys = r.keys[:len(r.keys)-1] + continue + } else { + i++ + } + } + + if !found { + return errors.New("agent: key not found") + } + return nil +} + +// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. +func (r *keyring) Lock(passphrase []byte) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + r.locked = true + r.passphrase = passphrase + return nil +} + +// Unlock undoes the effect of Lock +func (r *keyring) Unlock(passphrase []byte) error { + r.mu.Lock() + defer r.mu.Unlock() + if !r.locked { + return errors.New("agent: not locked") + } + if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { + return fmt.Errorf("agent: incorrect passphrase") + } + + r.locked = false + r.passphrase = nil + return nil +} + +// List returns the identities known to the agent. +func (r *keyring) List() ([]*Key, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + // section 2.7: locked agents return empty. + return nil, nil + } + + var ids []*Key + for _, k := range r.keys { + pub := k.signer.PublicKey() + ids = append(ids, &Key{ + Format: pub.Type(), + Blob: pub.Marshal(), + Comment: k.comment}) + } + return ids, nil +} + +// Insert adds a private key to the keyring. If a certificate +// is given, that certificate is added as public key. Note that +// any constraints given are ignored. +func (r *keyring) Add(key AddedKey) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + signer, err := ssh.NewSignerFromKey(key.PrivateKey) + + if err != nil { + return err + } + + if cert := key.Certificate; cert != nil { + signer, err = ssh.NewCertSigner(cert, signer) + if err != nil { + return err + } + } + + r.keys = append(r.keys, privKey{signer, key.Comment}) + + return nil +} + +// Sign returns a signature for the data. +func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return nil, errLocked + } + + wanted := key.Marshal() + for _, k := range r.keys { + if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { + return k.signer.Sign(rand.Reader, data) + } + } + return nil, errors.New("not found") +} + +// Signers returns signers for all the known keys. +func (r *keyring) Signers() ([]ssh.Signer, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return nil, errLocked + } + + s := make([]ssh.Signer, 0, len(r.keys)) + for _, k := range r.keys { + s = append(s, k.signer) + } + return s, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go new file mode 100644 index 000000000..b21a20180 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/server.go @@ -0,0 +1,209 @@ +// Copyright 2012 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. + +package agent + +import ( + "crypto/rsa" + "encoding/binary" + "fmt" + "io" + "log" + "math/big" + + "golang.org/x/crypto/ssh" +) + +// Server wraps an Agent and uses it to implement the agent side of +// the SSH-agent, wire protocol. +type server struct { + agent Agent +} + +func (s *server) processRequestBytes(reqData []byte) []byte { + rep, err := s.processRequest(reqData) + if err != nil { + if err != errLocked { + // TODO(hanwen): provide better logging interface? + log.Printf("agent %d: %v", reqData[0], err) + } + return []byte{agentFailure} + } + + if err == nil && rep == nil { + return []byte{agentSuccess} + } + + return ssh.Marshal(rep) +} + +func marshalKey(k *Key) []byte { + var record struct { + Blob []byte + Comment string + } + record.Blob = k.Marshal() + record.Comment = k.Comment + + return ssh.Marshal(&record) +} + +type agentV1IdentityMsg struct { + Numkeys uint32 `sshtype:"2"` +} + +type agentRemoveIdentityMsg struct { + KeyBlob []byte `sshtype:"18"` +} + +type agentLockMsg struct { + Passphrase []byte `sshtype:"22"` +} + +type agentUnlockMsg struct { + Passphrase []byte `sshtype:"23"` +} + +func (s *server) processRequest(data []byte) (interface{}, error) { + switch data[0] { + case agentRequestV1Identities: + return &agentV1IdentityMsg{0}, nil + case agentRemoveIdentity: + var req agentRemoveIdentityMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { + return nil, err + } + + return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) + + case agentRemoveAllIdentities: + return nil, s.agent.RemoveAll() + + case agentLock: + var req agentLockMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + return nil, s.agent.Lock(req.Passphrase) + + case agentUnlock: + var req agentLockMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + return nil, s.agent.Unlock(req.Passphrase) + + case agentSignRequest: + var req signRequestAgentMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { + return nil, err + } + + k := &Key{ + Format: wk.Format, + Blob: req.KeyBlob, + } + + sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags. + if err != nil { + return nil, err + } + return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil + case agentRequestIdentities: + keys, err := s.agent.List() + if err != nil { + return nil, err + } + + rep := identitiesAnswerAgentMsg{ + NumKeys: uint32(len(keys)), + } + for _, k := range keys { + rep.Keys = append(rep.Keys, marshalKey(k)...) + } + return rep, nil + case agentAddIdentity: + return nil, s.insertIdentity(data) + } + + return nil, fmt.Errorf("unknown opcode %d", data[0]) +} + +func (s *server) insertIdentity(req []byte) error { + var record struct { + Type string `sshtype:"17"` + Rest []byte `ssh:"rest"` + } + if err := ssh.Unmarshal(req, &record); err != nil { + return err + } + + switch record.Type { + case ssh.KeyAlgoRSA: + var k rsaKeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return err + } + + priv := rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + E: int(k.E.Int64()), + N: k.N, + }, + D: k.D, + Primes: []*big.Int{k.P, k.Q}, + } + priv.Precompute() + + return s.agent.Add(AddedKey{PrivateKey: &priv, Comment: k.Comments}) + } + return fmt.Errorf("not implemented: %s", record.Type) +} + +// ServeAgent serves the agent protocol on the given connection. It +// returns when an I/O error occurs. +func ServeAgent(agent Agent, c io.ReadWriter) error { + s := &server{agent} + + var length [4]byte + for { + if _, err := io.ReadFull(c, length[:]); err != nil { + return err + } + l := binary.BigEndian.Uint32(length[:]) + if l > maxAgentResponseBytes { + // We also cap requests. + return fmt.Errorf("agent: request too large: %d", l) + } + + req := make([]byte, l) + if _, err := io.ReadFull(c, req); err != nil { + return err + } + + repData := s.processRequestBytes(req) + if len(repData) > maxAgentResponseBytes { + return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) + } + + binary.BigEndian.PutUint32(length[:], uint32(len(repData))) + if _, err := c.Write(length[:]); err != nil { + return err + } + if _, err := c.Write(repData); err != nil { + return err + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go new file mode 100644 index 000000000..6931b5114 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/buffer.go @@ -0,0 +1,98 @@ +// Copyright 2012 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. + +package ssh + +import ( + "io" + "sync" +) + +// buffer provides a linked list buffer for data exchange +// between producer and consumer. Theoretically the buffer is +// of unlimited capacity as it does no allocation of its own. +type buffer struct { + // protects concurrent access to head, tail and closed + *sync.Cond + + head *element // the buffer that will be read first + tail *element // the buffer that will be read last + + closed bool +} + +// An element represents a single link in a linked list. +type element struct { + buf []byte + next *element +} + +// newBuffer returns an empty buffer that is not closed. +func newBuffer() *buffer { + e := new(element) + b := &buffer{ + Cond: newCond(), + head: e, + tail: e, + } + return b +} + +// write makes buf available for Read to receive. +// buf must not be modified after the call to write. +func (b *buffer) write(buf []byte) { + b.Cond.L.Lock() + e := &element{buf: buf} + b.tail.next = e + b.tail = e + b.Cond.Signal() + b.Cond.L.Unlock() +} + +// eof closes the buffer. Reads from the buffer once all +// the data has been consumed will receive os.EOF. +func (b *buffer) eof() error { + b.Cond.L.Lock() + b.closed = true + b.Cond.Signal() + b.Cond.L.Unlock() + return nil +} + +// Read reads data from the internal buffer in buf. Reads will block +// if no data is available, or until the buffer is closed. +func (b *buffer) Read(buf []byte) (n int, err error) { + b.Cond.L.Lock() + defer b.Cond.L.Unlock() + + for len(buf) > 0 { + // if there is data in b.head, copy it + if len(b.head.buf) > 0 { + r := copy(buf, b.head.buf) + buf, b.head.buf = buf[r:], b.head.buf[r:] + n += r + continue + } + // if there is a next buffer, make it the head + if len(b.head.buf) == 0 && b.head != b.tail { + b.head = b.head.next + continue + } + + // if at least one byte has been copied, return + if n > 0 { + break + } + + // if nothing was read, and there is nothing outstanding + // check to see if the buffer is closed. + if b.closed { + err = io.EOF + break + } + // out of buffers, wait for producer + b.Cond.Wait() + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go new file mode 100644 index 000000000..385770036 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -0,0 +1,501 @@ +// Copyright 2012 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. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "sort" + "time" +) + +// These constants from [PROTOCOL.certkeys] represent the algorithm names +// for certificate types supported by this package. +const ( + CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" + CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" + CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" + CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" +) + +// Certificate types distinguish between host and user +// certificates. The values can be set in the CertType field of +// Certificate. +const ( + UserCert = 1 + HostCert = 2 +) + +// Signature represents a cryptographic signature. +type Signature struct { + Format string + Blob []byte +} + +// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that +// a certificate does not expire. +const CertTimeInfinity = 1<<64 - 1 + +// An Certificate represents an OpenSSH certificate as defined in +// [PROTOCOL.certkeys]?rev=1.8. +type Certificate struct { + Nonce []byte + Key PublicKey + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []string + ValidAfter uint64 + ValidBefore uint64 + Permissions + Reserved []byte + SignatureKey PublicKey + Signature *Signature +} + +// genericCertData holds the key-independent part of the certificate data. +// Overall, certificates contain an nonce, public key fields and +// key-independent fields. +type genericCertData struct { + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []byte + ValidAfter uint64 + ValidBefore uint64 + CriticalOptions []byte + Extensions []byte + Reserved []byte + SignatureKey []byte + Signature []byte +} + +func marshalStringList(namelist []string) []byte { + var to []byte + for _, name := range namelist { + s := struct{ N string }{name} + to = append(to, Marshal(&s)...) + } + return to +} + +type optionsTuple struct { + Key string + Value []byte +} + +type optionsTupleValue struct { + Value string +} + +// serialize a map of critical options or extensions +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty string value +func marshalTuples(tups map[string]string) []byte { + keys := make([]string, 0, len(tups)) + for key := range tups { + keys = append(keys, key) + } + sort.Strings(keys) + + var ret []byte + for _, key := range keys { + s := optionsTuple{Key: key} + if value := tups[key]; len(value) > 0 { + s.Value = Marshal(&optionsTupleValue{value}) + } + ret = append(ret, Marshal(&s)...) + } + return ret +} + +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty option value +func parseTuples(in []byte) (map[string]string, error) { + tups := map[string]string{} + var lastKey string + var haveLastKey bool + + for len(in) > 0 { + var key, val, extra []byte + var ok bool + + if key, in, ok = parseString(in); !ok { + return nil, errShortRead + } + keyStr := string(key) + // according to [PROTOCOL.certkeys], the names must be in + // lexical order. + if haveLastKey && keyStr <= lastKey { + return nil, fmt.Errorf("ssh: certificate options are not in lexical order") + } + lastKey, haveLastKey = keyStr, true + // the next field is a data field, which if non-empty has a string embedded + if val, in, ok = parseString(in); !ok { + return nil, errShortRead + } + if len(val) > 0 { + val, extra, ok = parseString(val) + if !ok { + return nil, errShortRead + } + if len(extra) > 0 { + return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") + } + tups[keyStr] = string(val) + } else { + tups[keyStr] = "" + } + } + return tups, nil +} + +func parseCert(in []byte, privAlgo string) (*Certificate, error) { + nonce, rest, ok := parseString(in) + if !ok { + return nil, errShortRead + } + + key, rest, err := parsePubKey(rest, privAlgo) + if err != nil { + return nil, err + } + + var g genericCertData + if err := Unmarshal(rest, &g); err != nil { + return nil, err + } + + c := &Certificate{ + Nonce: nonce, + Key: key, + Serial: g.Serial, + CertType: g.CertType, + KeyId: g.KeyId, + ValidAfter: g.ValidAfter, + ValidBefore: g.ValidBefore, + } + + for principals := g.ValidPrincipals; len(principals) > 0; { + principal, rest, ok := parseString(principals) + if !ok { + return nil, errShortRead + } + c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) + principals = rest + } + + c.CriticalOptions, err = parseTuples(g.CriticalOptions) + if err != nil { + return nil, err + } + c.Extensions, err = parseTuples(g.Extensions) + if err != nil { + return nil, err + } + c.Reserved = g.Reserved + k, err := ParsePublicKey(g.SignatureKey) + if err != nil { + return nil, err + } + + c.SignatureKey = k + c.Signature, rest, ok = parseSignatureBody(g.Signature) + if !ok || len(rest) > 0 { + return nil, errors.New("ssh: signature parse error") + } + + return c, nil +} + +type openSSHCertSigner struct { + pub *Certificate + signer Signer +} + +// NewCertSigner returns a Signer that signs with the given Certificate, whose +// private key is held by signer. It returns an error if the public key in cert +// doesn't match the key used by signer. +func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { + if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + return nil, errors.New("ssh: signer and cert have different public key") + } + + return &openSSHCertSigner{cert, signer}, nil +} + +func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + return s.signer.Sign(rand, data) +} + +func (s *openSSHCertSigner) PublicKey() PublicKey { + return s.pub +} + +const sourceAddressCriticalOption = "source-address" + +// CertChecker does the work of verifying a certificate. Its methods +// can be plugged into ClientConfig.HostKeyCallback and +// ServerConfig.PublicKeyCallback. For the CertChecker to work, +// minimally, the IsAuthority callback should be set. +type CertChecker struct { + // SupportedCriticalOptions lists the CriticalOptions that the + // server application layer understands. These are only used + // for user certificates. + SupportedCriticalOptions []string + + // IsAuthority should return true if the key is recognized as + // an authority. This allows for certificates to be signed by other + // certificates. + IsAuthority func(auth PublicKey) bool + + // Clock is used for verifying time stamps. If nil, time.Now + // is used. + Clock func() time.Time + + // UserKeyFallback is called when CertChecker.Authenticate encounters a + // public key that is not a certificate. It must implement validation + // of user keys or else, if nil, all such keys are rejected. + UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // HostKeyFallback is called when CertChecker.CheckHostKey encounters a + // public key that is not a certificate. It must implement host key + // validation or else, if nil, all such keys are rejected. + HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error + + // IsRevoked is called for each certificate so that revocation checking + // can be implemented. It should return true if the given certificate + // is revoked and false otherwise. If nil, no certificates are + // considered to have been revoked. + IsRevoked func(cert *Certificate) bool +} + +// CheckHostKey checks a host key certificate. This method can be +// plugged into ClientConfig.HostKeyCallback. +func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { + cert, ok := key.(*Certificate) + if !ok { + if c.HostKeyFallback != nil { + return c.HostKeyFallback(addr, remote, key) + } + return errors.New("ssh: non-certificate host key") + } + if cert.CertType != HostCert { + return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) + } + + return c.CheckCert(addr, cert) +} + +// Authenticate checks a user certificate. Authenticate can be used as +// a value for ServerConfig.PublicKeyCallback. +func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { + cert, ok := pubKey.(*Certificate) + if !ok { + if c.UserKeyFallback != nil { + return c.UserKeyFallback(conn, pubKey) + } + return nil, errors.New("ssh: normal key pairs not accepted") + } + + if cert.CertType != UserCert { + return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) + } + + if err := c.CheckCert(conn.User(), cert); err != nil { + return nil, err + } + + return &cert.Permissions, nil +} + +// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and +// the signature of the certificate. +func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { + if c.IsRevoked != nil && c.IsRevoked(cert) { + return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial) + } + + for opt, _ := range cert.CriticalOptions { + // sourceAddressCriticalOption will be enforced by + // serverAuthenticate + if opt == sourceAddressCriticalOption { + continue + } + + found := false + for _, supp := range c.SupportedCriticalOptions { + if supp == opt { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) + } + } + + if len(cert.ValidPrincipals) > 0 { + // By default, certs are valid for all users/hosts. + found := false + for _, p := range cert.ValidPrincipals { + if p == principal { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) + } + } + + if !c.IsAuthority(cert.SignatureKey) { + return fmt.Errorf("ssh: certificate signed by unrecognized authority") + } + + clock := c.Clock + if clock == nil { + clock = time.Now + } + + unixNow := clock().Unix() + if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { + return fmt.Errorf("ssh: cert is not yet valid") + } + if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { + return fmt.Errorf("ssh: cert has expired") + } + if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { + return fmt.Errorf("ssh: certificate signature does not verify") + } + + return nil +} + +// SignCert sets c.SignatureKey to the authority's public key and stores a +// Signature, by authority, in the certificate. +func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { + c.Nonce = make([]byte, 32) + if _, err := io.ReadFull(rand, c.Nonce); err != nil { + return err + } + c.SignatureKey = authority.PublicKey() + + sig, err := authority.Sign(rand, c.bytesForSigning()) + if err != nil { + return err + } + c.Signature = sig + return nil +} + +var certAlgoNames = map[string]string{ + KeyAlgoRSA: CertAlgoRSAv01, + KeyAlgoDSA: CertAlgoDSAv01, + KeyAlgoECDSA256: CertAlgoECDSA256v01, + KeyAlgoECDSA384: CertAlgoECDSA384v01, + KeyAlgoECDSA521: CertAlgoECDSA521v01, +} + +// certToPrivAlgo returns the underlying algorithm for a certificate algorithm. +// Panics if a non-certificate algorithm is passed. +func certToPrivAlgo(algo string) string { + for privAlgo, pubAlgo := range certAlgoNames { + if pubAlgo == algo { + return privAlgo + } + } + panic("unknown cert algorithm") +} + +func (cert *Certificate) bytesForSigning() []byte { + c2 := *cert + c2.Signature = nil + out := c2.Marshal() + // Drop trailing signature length. + return out[:len(out)-4] +} + +// Marshal serializes c into OpenSSH's wire format. It is part of the +// PublicKey interface. +func (c *Certificate) Marshal() []byte { + generic := genericCertData{ + Serial: c.Serial, + CertType: c.CertType, + KeyId: c.KeyId, + ValidPrincipals: marshalStringList(c.ValidPrincipals), + ValidAfter: uint64(c.ValidAfter), + ValidBefore: uint64(c.ValidBefore), + CriticalOptions: marshalTuples(c.CriticalOptions), + Extensions: marshalTuples(c.Extensions), + Reserved: c.Reserved, + SignatureKey: c.SignatureKey.Marshal(), + } + if c.Signature != nil { + generic.Signature = Marshal(c.Signature) + } + genericBytes := Marshal(&generic) + keyBytes := c.Key.Marshal() + _, keyBytes, _ = parseString(keyBytes) + prefix := Marshal(&struct { + Name string + Nonce []byte + Key []byte `ssh:"rest"` + }{c.Type(), c.Nonce, keyBytes}) + + result := make([]byte, 0, len(prefix)+len(genericBytes)) + result = append(result, prefix...) + result = append(result, genericBytes...) + return result +} + +// Type returns the key name. It is part of the PublicKey interface. +func (c *Certificate) Type() string { + algo, ok := certAlgoNames[c.Key.Type()] + if !ok { + panic("unknown cert key type") + } + return algo +} + +// Verify verifies a signature against the certificate's public +// key. It is part of the PublicKey interface. +func (c *Certificate) Verify(data []byte, sig *Signature) error { + return c.Key.Verify(data, sig) +} + +func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { + format, in, ok := parseString(in) + if !ok { + return + } + + out = &Signature{ + Format: string(format), + } + + if out.Blob, in, ok = parseString(in); !ok { + return + } + + return out, in, ok +} + +func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { + sigBytes, rest, ok := parseString(in) + if !ok { + return + } + + out, trailing, ok := parseSignatureBody(sigBytes) + if !ok || len(trailing) > 0 { + return nil, nil, false + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go new file mode 100644 index 000000000..5403c7e45 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -0,0 +1,631 @@ +// Copyright 2011 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. + +package ssh + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "log" + "sync" +) + +const ( + minPacketLength = 9 + // channelMaxPacket contains the maximum number of bytes that will be + // sent in a single packet. As per RFC 4253, section 6.1, 32k is also + // the minimum. + channelMaxPacket = 1 << 15 + // We follow OpenSSH here. + channelWindowSize = 64 * channelMaxPacket +) + +// NewChannel represents an incoming request to a channel. It must either be +// accepted for use by calling Accept, or rejected by calling Reject. +type NewChannel interface { + // Accept accepts the channel creation request. It returns the Channel + // and a Go channel containing SSH requests. The Go channel must be + // serviced otherwise the Channel will hang. + Accept() (Channel, <-chan *Request, error) + + // Reject rejects the channel creation request. After calling + // this, no other methods on the Channel may be called. + Reject(reason RejectionReason, message string) error + + // ChannelType returns the type of the channel, as supplied by the + // client. + ChannelType() string + + // ExtraData returns the arbitrary payload for this channel, as supplied + // by the client. This data is specific to the channel type. + ExtraData() []byte +} + +// A Channel is an ordered, reliable, flow-controlled, duplex stream +// that is multiplexed over an SSH connection. +type Channel interface { + // Read reads up to len(data) bytes from the channel. + Read(data []byte) (int, error) + + // Write writes len(data) bytes to the channel. + Write(data []byte) (int, error) + + // Close signals end of channel use. No data may be sent after this + // call. + Close() error + + // CloseWrite signals the end of sending in-band + // data. Requests may still be sent, and the other side may + // still send data + CloseWrite() error + + // SendRequest sends a channel request. If wantReply is true, + // it will wait for a reply and return the result as a + // boolean, otherwise the return value will be false. Channel + // requests are out-of-band messages so they may be sent even + // if the data stream is closed or blocked by flow control. + SendRequest(name string, wantReply bool, payload []byte) (bool, error) + + // Stderr returns an io.ReadWriter that writes to this channel + // with the extended data type set to stderr. Stderr may + // safely be read and written from a different goroutine than + // Read and Write respectively. + Stderr() io.ReadWriter +} + +// Request is a request sent outside of the normal stream of +// data. Requests can either be specific to an SSH channel, or they +// can be global. +type Request struct { + Type string + WantReply bool + Payload []byte + + ch *channel + mux *mux +} + +// Reply sends a response to a request. It must be called for all requests +// where WantReply is true and is a no-op otherwise. The payload argument is +// ignored for replies to channel-specific requests. +func (r *Request) Reply(ok bool, payload []byte) error { + if !r.WantReply { + return nil + } + + if r.ch == nil { + return r.mux.ackRequest(ok, payload) + } + + return r.ch.ackRequest(ok) +} + +// RejectionReason is an enumeration used when rejecting channel creation +// requests. See RFC 4254, section 5.1. +type RejectionReason uint32 + +const ( + Prohibited RejectionReason = iota + 1 + ConnectionFailed + UnknownChannelType + ResourceShortage +) + +// String converts the rejection reason to human readable form. +func (r RejectionReason) String() string { + switch r { + case Prohibited: + return "administratively prohibited" + case ConnectionFailed: + return "connect failed" + case UnknownChannelType: + return "unknown channel type" + case ResourceShortage: + return "resource shortage" + } + return fmt.Sprintf("unknown reason %d", int(r)) +} + +func min(a uint32, b int) uint32 { + if a < uint32(b) { + return a + } + return uint32(b) +} + +type channelDirection uint8 + +const ( + channelInbound channelDirection = iota + channelOutbound +) + +// channel is an implementation of the Channel interface that works +// with the mux class. +type channel struct { + // R/O after creation + chanType string + extraData []byte + localId, remoteId uint32 + + // maxIncomingPayload and maxRemotePayload are the maximum + // payload sizes of normal and extended data packets for + // receiving and sending, respectively. The wire packet will + // be 9 or 13 bytes larger (excluding encryption overhead). + maxIncomingPayload uint32 + maxRemotePayload uint32 + + mux *mux + + // decided is set to true if an accept or reject message has been sent + // (for outbound channels) or received (for inbound channels). + decided bool + + // direction contains either channelOutbound, for channels created + // locally, or channelInbound, for channels created by the peer. + direction channelDirection + + // Pending internal channel messages. + msg chan interface{} + + // Since requests have no ID, there can be only one request + // with WantReply=true outstanding. This lock is held by a + // goroutine that has such an outgoing request pending. + sentRequestMu sync.Mutex + + incomingRequests chan *Request + + sentEOF bool + + // thread-safe data + remoteWin window + pending *buffer + extPending *buffer + + // windowMu protects myWindow, the flow-control window. + windowMu sync.Mutex + myWindow uint32 + + // writeMu serializes calls to mux.conn.writePacket() and + // protects sentClose and packetPool. This mutex must be + // different from windowMu, as writePacket can block if there + // is a key exchange pending. + writeMu sync.Mutex + sentClose bool + + // packetPool has a buffer for each extended channel ID to + // save allocations during writes. + packetPool map[uint32][]byte +} + +// writePacket sends a packet. If the packet is a channel close, it updates +// sentClose. This method takes the lock c.writeMu. +func (c *channel) writePacket(packet []byte) error { + c.writeMu.Lock() + if c.sentClose { + c.writeMu.Unlock() + return io.EOF + } + c.sentClose = (packet[0] == msgChannelClose) + err := c.mux.conn.writePacket(packet) + c.writeMu.Unlock() + return err +} + +func (c *channel) sendMessage(msg interface{}) error { + if debugMux { + log.Printf("send %d: %#v", c.mux.chanList.offset, msg) + } + + p := Marshal(msg) + binary.BigEndian.PutUint32(p[1:], c.remoteId) + return c.writePacket(p) +} + +// WriteExtended writes data to a specific extended stream. These streams are +// used, for example, for stderr. +func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { + if c.sentEOF { + return 0, io.EOF + } + // 1 byte message type, 4 bytes remoteId, 4 bytes data length + opCode := byte(msgChannelData) + headerLength := uint32(9) + if extendedCode > 0 { + headerLength += 4 + opCode = msgChannelExtendedData + } + + c.writeMu.Lock() + packet := c.packetPool[extendedCode] + // We don't remove the buffer from packetPool, so + // WriteExtended calls from different goroutines will be + // flagged as errors by the race detector. + c.writeMu.Unlock() + + for len(data) > 0 { + space := min(c.maxRemotePayload, len(data)) + if space, err = c.remoteWin.reserve(space); err != nil { + return n, err + } + if want := headerLength + space; uint32(cap(packet)) < want { + packet = make([]byte, want) + } else { + packet = packet[:want] + } + + todo := data[:space] + + packet[0] = opCode + binary.BigEndian.PutUint32(packet[1:], c.remoteId) + if extendedCode > 0 { + binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) + } + binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) + copy(packet[headerLength:], todo) + if err = c.writePacket(packet); err != nil { + return n, err + } + + n += len(todo) + data = data[len(todo):] + } + + c.writeMu.Lock() + c.packetPool[extendedCode] = packet + c.writeMu.Unlock() + + return n, err +} + +func (c *channel) handleData(packet []byte) error { + headerLen := 9 + isExtendedData := packet[0] == msgChannelExtendedData + if isExtendedData { + headerLen = 13 + } + if len(packet) < headerLen { + // malformed data packet + return parseError(packet[0]) + } + + var extended uint32 + if isExtendedData { + extended = binary.BigEndian.Uint32(packet[5:]) + } + + length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) + if length == 0 { + return nil + } + if length > c.maxIncomingPayload { + // TODO(hanwen): should send Disconnect? + return errors.New("ssh: incoming packet exceeds maximum payload size") + } + + data := packet[headerLen:] + if length != uint32(len(data)) { + return errors.New("ssh: wrong packet length") + } + + c.windowMu.Lock() + if c.myWindow < length { + c.windowMu.Unlock() + // TODO(hanwen): should send Disconnect with reason? + return errors.New("ssh: remote side wrote too much") + } + c.myWindow -= length + c.windowMu.Unlock() + + if extended == 1 { + c.extPending.write(data) + } else if extended > 0 { + // discard other extended data. + } else { + c.pending.write(data) + } + return nil +} + +func (c *channel) adjustWindow(n uint32) error { + c.windowMu.Lock() + // Since myWindow is managed on our side, and can never exceed + // the initial window setting, we don't worry about overflow. + c.myWindow += uint32(n) + c.windowMu.Unlock() + return c.sendMessage(windowAdjustMsg{ + AdditionalBytes: uint32(n), + }) +} + +func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { + switch extended { + case 1: + n, err = c.extPending.Read(data) + case 0: + n, err = c.pending.Read(data) + default: + return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) + } + + if n > 0 { + err = c.adjustWindow(uint32(n)) + // sendWindowAdjust can return io.EOF if the remote + // peer has closed the connection, however we want to + // defer forwarding io.EOF to the caller of Read until + // the buffer has been drained. + if n > 0 && err == io.EOF { + err = nil + } + } + + return n, err +} + +func (c *channel) close() { + c.pending.eof() + c.extPending.eof() + close(c.msg) + close(c.incomingRequests) + c.writeMu.Lock() + // This is not necesary for a normal channel teardown, but if + // there was another error, it is. + c.sentClose = true + c.writeMu.Unlock() + // Unblock writers. + c.remoteWin.close() +} + +// responseMessageReceived is called when a success or failure message is +// received on a channel to check that such a message is reasonable for the +// given channel. +func (c *channel) responseMessageReceived() error { + if c.direction == channelInbound { + return errors.New("ssh: channel response message received on inbound channel") + } + if c.decided { + return errors.New("ssh: duplicate response received for channel") + } + c.decided = true + return nil +} + +func (c *channel) handlePacket(packet []byte) error { + switch packet[0] { + case msgChannelData, msgChannelExtendedData: + return c.handleData(packet) + case msgChannelClose: + c.sendMessage(channelCloseMsg{PeersId: c.remoteId}) + c.mux.chanList.remove(c.localId) + c.close() + return nil + case msgChannelEOF: + // RFC 4254 is mute on how EOF affects dataExt messages but + // it is logical to signal EOF at the same time. + c.extPending.eof() + c.pending.eof() + return nil + } + + decoded, err := decode(packet) + if err != nil { + return err + } + + switch msg := decoded.(type) { + case *channelOpenFailureMsg: + if err := c.responseMessageReceived(); err != nil { + return err + } + c.mux.chanList.remove(msg.PeersId) + c.msg <- msg + case *channelOpenConfirmMsg: + if err := c.responseMessageReceived(); err != nil { + return err + } + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) + } + c.remoteId = msg.MyId + c.maxRemotePayload = msg.MaxPacketSize + c.remoteWin.add(msg.MyWindow) + c.msg <- msg + case *windowAdjustMsg: + if !c.remoteWin.add(msg.AdditionalBytes) { + return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) + } + case *channelRequestMsg: + req := Request{ + Type: msg.Request, + WantReply: msg.WantReply, + Payload: msg.RequestSpecificData, + ch: c, + } + + c.incomingRequests <- &req + default: + c.msg <- msg + } + return nil +} + +func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { + ch := &channel{ + remoteWin: window{Cond: newCond()}, + myWindow: channelWindowSize, + pending: newBuffer(), + extPending: newBuffer(), + direction: direction, + incomingRequests: make(chan *Request, 16), + msg: make(chan interface{}, 16), + chanType: chanType, + extraData: extraData, + mux: m, + packetPool: make(map[uint32][]byte), + } + ch.localId = m.chanList.add(ch) + return ch +} + +var errUndecided = errors.New("ssh: must Accept or Reject channel") +var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") + +type extChannel struct { + code uint32 + ch *channel +} + +func (e *extChannel) Write(data []byte) (n int, err error) { + return e.ch.WriteExtended(data, e.code) +} + +func (e *extChannel) Read(data []byte) (n int, err error) { + return e.ch.ReadExtended(data, e.code) +} + +func (c *channel) Accept() (Channel, <-chan *Request, error) { + if c.decided { + return nil, nil, errDecidedAlready + } + c.maxIncomingPayload = channelMaxPacket + confirm := channelOpenConfirmMsg{ + PeersId: c.remoteId, + MyId: c.localId, + MyWindow: c.myWindow, + MaxPacketSize: c.maxIncomingPayload, + } + c.decided = true + if err := c.sendMessage(confirm); err != nil { + return nil, nil, err + } + + return c, c.incomingRequests, nil +} + +func (ch *channel) Reject(reason RejectionReason, message string) error { + if ch.decided { + return errDecidedAlready + } + reject := channelOpenFailureMsg{ + PeersId: ch.remoteId, + Reason: reason, + Message: message, + Language: "en", + } + ch.decided = true + return ch.sendMessage(reject) +} + +func (ch *channel) Read(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.ReadExtended(data, 0) +} + +func (ch *channel) Write(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.WriteExtended(data, 0) +} + +func (ch *channel) CloseWrite() error { + if !ch.decided { + return errUndecided + } + ch.sentEOF = true + return ch.sendMessage(channelEOFMsg{ + PeersId: ch.remoteId}) +} + +func (ch *channel) Close() error { + if !ch.decided { + return errUndecided + } + + return ch.sendMessage(channelCloseMsg{ + PeersId: ch.remoteId}) +} + +// Extended returns an io.ReadWriter that sends and receives data on the given, +// SSH extended stream. Such streams are used, for example, for stderr. +func (ch *channel) Extended(code uint32) io.ReadWriter { + if !ch.decided { + return nil + } + return &extChannel{code, ch} +} + +func (ch *channel) Stderr() io.ReadWriter { + return ch.Extended(1) +} + +func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + if !ch.decided { + return false, errUndecided + } + + if wantReply { + ch.sentRequestMu.Lock() + defer ch.sentRequestMu.Unlock() + } + + msg := channelRequestMsg{ + PeersId: ch.remoteId, + Request: name, + WantReply: wantReply, + RequestSpecificData: payload, + } + + if err := ch.sendMessage(msg); err != nil { + return false, err + } + + if wantReply { + m, ok := (<-ch.msg) + if !ok { + return false, io.EOF + } + switch m.(type) { + case *channelRequestFailureMsg: + return false, nil + case *channelRequestSuccessMsg: + return true, nil + default: + return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) + } + } + + return false, nil +} + +// ackRequest either sends an ack or nack to the channel request. +func (ch *channel) ackRequest(ok bool) error { + if !ch.decided { + return errUndecided + } + + var msg interface{} + if !ok { + msg = channelRequestFailureMsg{ + PeersId: ch.remoteId, + } + } else { + msg = channelRequestSuccessMsg{ + PeersId: ch.remoteId, + } + } + return ch.sendMessage(msg) +} + +func (ch *channel) ChannelType() string { + return ch.chanType +} + +func (ch *channel) ExtraData() []byte { + return ch.extraData +} diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go new file mode 100644 index 000000000..2732963f3 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -0,0 +1,552 @@ +// Copyright 2011 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. + +package ssh + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rc4" + "crypto/subtle" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" +) + +const ( + packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. + + // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations + // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC + // indicates implementations SHOULD be able to handle larger packet sizes, but then + // waffles on about reasonable limits. + // + // OpenSSH caps their maxPacket at 256kB so we choose to do + // the same. maxPacket is also used to ensure that uint32 + // length fields do not overflow, so it should remain well + // below 4G. + maxPacket = 256 * 1024 +) + +// noneCipher implements cipher.Stream and provides no encryption. It is used +// by the transport before the first key-exchange. +type noneCipher struct{} + +func (c noneCipher) XORKeyStream(dst, src []byte) { + copy(dst, src) +} + +func newAESCTR(key, iv []byte) (cipher.Stream, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewCTR(c, iv), nil +} + +func newRC4(key, iv []byte) (cipher.Stream, error) { + return rc4.NewCipher(key) +} + +type streamCipherMode struct { + keySize int + ivSize int + skip int + createFunc func(key, iv []byte) (cipher.Stream, error) +} + +func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { + if len(key) < c.keySize { + panic("ssh: key length too small for cipher") + } + if len(iv) < c.ivSize { + panic("ssh: iv too small for cipher") + } + + stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) + if err != nil { + return nil, err + } + + var streamDump []byte + if c.skip > 0 { + streamDump = make([]byte, 512) + } + + for remainingToDump := c.skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + return stream, nil +} + +// cipherModes documents properties of supported ciphers. Ciphers not included +// are not supported and will not be negotiated, even if explicitly requested in +// ClientConfig.Crypto.Ciphers. +var cipherModes = map[string]*streamCipherMode{ + // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms + // are defined in the order specified in the RFC. + "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, + "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, + "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, + + // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. + // They are defined in the order specified in the RFC. + "arcfour128": {16, 0, 1536, newRC4}, + "arcfour256": {32, 0, 1536, newRC4}, + + // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. + // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and + // RC4) has problems with weak keys, and should be used with caution." + // RFC4345 introduces improved versions of Arcfour. + "arcfour": {16, 0, 0, newRC4}, + + // AES-GCM is not a stream cipher, so it is constructed with a + // special case. If we add any more non-stream ciphers, we + // should invest a cleaner way to do this. + gcmCipherID: {16, 12, 0, nil}, + + // CBC mode is insecure and so is not included in the default config. + // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely + // needed, it's possible to specify a custom Config to enable it. + // You should expect that an active attacker can recover plaintext if + // you do. + aes128cbcID: {16, aes.BlockSize, 0, nil}, +} + +// prefixLen is the length of the packet prefix that contains the packet length +// and number of padding bytes. +const prefixLen = 5 + +// streamPacketCipher is a packetCipher using a stream cipher. +type streamPacketCipher struct { + mac hash.Hash + cipher cipher.Stream + + // The following members are to avoid per-packet allocations. + prefix [prefixLen]byte + seqNumBytes [4]byte + padding [2 * packetSizeMultiple]byte + packetData []byte + macResult []byte +} + +// readPacket reads and decrypt a single packet from the reader argument. +func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, s.prefix[:]); err != nil { + return nil, err + } + + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + length := binary.BigEndian.Uint32(s.prefix[0:4]) + paddingLength := uint32(s.prefix[4]) + + var macSize uint32 + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + s.mac.Write(s.prefix[:]) + macSize = uint32(s.mac.Size()) + } + + if length <= paddingLength+1 { + return nil, errors.New("ssh: invalid packet length, packet too small") + } + + if length > maxPacket { + return nil, errors.New("ssh: invalid packet length, packet too large") + } + + // the maxPacket check above ensures that length-1+macSize + // does not overflow. + if uint32(cap(s.packetData)) < length-1+macSize { + s.packetData = make([]byte, length-1+macSize) + } else { + s.packetData = s.packetData[:length-1+macSize] + } + + if _, err := io.ReadFull(r, s.packetData); err != nil { + return nil, err + } + mac := s.packetData[length-1:] + data := s.packetData[:length-1] + s.cipher.XORKeyStream(data, data) + + if s.mac != nil { + s.mac.Write(data) + s.macResult = s.mac.Sum(s.macResult[:0]) + if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { + return nil, errors.New("ssh: MAC failure") + } + } + + return s.packetData[:length-paddingLength-1], nil +} + +// writePacket encrypts and sends a packet of data to the writer argument +func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + if len(packet) > maxPacket { + return errors.New("ssh: packet too large") + } + + paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple + if paddingLength < 4 { + paddingLength += packetSizeMultiple + } + + length := len(packet) + 1 + paddingLength + binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) + s.prefix[4] = byte(paddingLength) + padding := s.padding[:paddingLength] + if _, err := io.ReadFull(rand, padding); err != nil { + return err + } + + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + s.mac.Write(s.prefix[:]) + s.mac.Write(packet) + s.mac.Write(padding) + } + + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + s.cipher.XORKeyStream(packet, packet) + s.cipher.XORKeyStream(padding, padding) + + if _, err := w.Write(s.prefix[:]); err != nil { + return err + } + if _, err := w.Write(packet); err != nil { + return err + } + if _, err := w.Write(padding); err != nil { + return err + } + + if s.mac != nil { + s.macResult = s.mac.Sum(s.macResult[:0]) + if _, err := w.Write(s.macResult); err != nil { + return err + } + } + + return nil +} + +type gcmCipher struct { + aead cipher.AEAD + prefix [4]byte + iv []byte + buf []byte +} + +func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + aead, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + return &gcmCipher{ + aead: aead, + iv: iv, + }, nil +} + +const gcmTagSize = 16 + +func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + // Pad out to multiple of 16 bytes. This is different from the + // stream cipher because that encrypts the length too. + padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) + if padding < 4 { + padding += packetSizeMultiple + } + + length := uint32(len(packet) + int(padding) + 1) + binary.BigEndian.PutUint32(c.prefix[:], length) + if _, err := w.Write(c.prefix[:]); err != nil { + return err + } + + if cap(c.buf) < int(length) { + c.buf = make([]byte, length) + } else { + c.buf = c.buf[:length] + } + + c.buf[0] = padding + copy(c.buf[1:], packet) + if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { + return err + } + c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if _, err := w.Write(c.buf); err != nil { + return err + } + c.incIV() + + return nil +} + +func (c *gcmCipher) incIV() { + for i := 4 + 7; i >= 4; i-- { + c.iv[i]++ + if c.iv[i] != 0 { + break + } + } +} + +func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, c.prefix[:]); err != nil { + return nil, err + } + length := binary.BigEndian.Uint32(c.prefix[:]) + if length > maxPacket { + return nil, errors.New("ssh: max packet length exceeded.") + } + + if cap(c.buf) < int(length+gcmTagSize) { + c.buf = make([]byte, length+gcmTagSize) + } else { + c.buf = c.buf[:length+gcmTagSize] + } + + if _, err := io.ReadFull(r, c.buf); err != nil { + return nil, err + } + + plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if err != nil { + return nil, err + } + c.incIV() + + padding := plain[0] + if padding < 4 || padding >= 20 { + return nil, fmt.Errorf("ssh: illegal padding %d", padding) + } + + if int(padding+1) >= len(plain) { + return nil, fmt.Errorf("ssh: padding %d too large", padding) + } + plain = plain[1 : length-uint32(padding)] + return plain, nil +} + +// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 +type cbcCipher struct { + mac hash.Hash + macSize uint32 + decrypter cipher.BlockMode + encrypter cipher.BlockMode + + // The following members are to avoid per-packet allocations. + seqNumBytes [4]byte + packetData []byte + macResult []byte + + // Amount of data we should still read to hide which + // verification error triggered. + oracleCamouflage uint32 +} + +func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + cbc := &cbcCipher{ + mac: macModes[algs.MAC].new(macKey), + decrypter: cipher.NewCBCDecrypter(c, iv), + encrypter: cipher.NewCBCEncrypter(c, iv), + packetData: make([]byte, 1024), + } + if cbc.mac != nil { + cbc.macSize = uint32(cbc.mac.Size()) + } + + return cbc, nil +} + +func maxUInt32(a, b int) uint32 { + if a > b { + return uint32(a) + } + return uint32(b) +} + +const ( + cbcMinPacketSizeMultiple = 8 + cbcMinPacketSize = 16 + cbcMinPaddingSize = 4 +) + +// cbcError represents a verification error that may leak information. +type cbcError string + +func (e cbcError) Error() string { return string(e) } + +func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + p, err := c.readPacketLeaky(seqNum, r) + if err != nil { + if _, ok := err.(cbcError); ok { + // Verification error: read a fixed amount of + // data, to make distinguishing between + // failing MAC and failing length check more + // difficult. + io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) + } + } + return p, err +} + +func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { + blockSize := c.decrypter.BlockSize() + + // Read the header, which will include some of the subsequent data in the + // case of block ciphers - this is copied back to the payload later. + // How many bytes of payload/padding will be read with this first read. + firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) + firstBlock := c.packetData[:firstBlockLength] + if _, err := io.ReadFull(r, firstBlock); err != nil { + return nil, err + } + + c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength + + c.decrypter.CryptBlocks(firstBlock, firstBlock) + length := binary.BigEndian.Uint32(firstBlock[:4]) + if length > maxPacket { + return nil, cbcError("ssh: packet too large") + } + if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { + // The minimum size of a packet is 16 (or the cipher block size, whichever + // is larger) bytes. + return nil, cbcError("ssh: packet too small") + } + // The length of the packet (including the length field but not the MAC) must + // be a multiple of the block size or 8, whichever is larger. + if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { + return nil, cbcError("ssh: invalid packet length multiple") + } + + paddingLength := uint32(firstBlock[4]) + if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { + return nil, cbcError("ssh: invalid packet length") + } + + // Positions within the c.packetData buffer: + macStart := 4 + length + paddingStart := macStart - paddingLength + + // Entire packet size, starting before length, ending at end of mac. + entirePacketSize := macStart + c.macSize + + // Ensure c.packetData is large enough for the entire packet data. + if uint32(cap(c.packetData)) < entirePacketSize { + // Still need to upsize and copy, but this should be rare at runtime, only + // on upsizing the packetData buffer. + c.packetData = make([]byte, entirePacketSize) + copy(c.packetData, firstBlock) + } else { + c.packetData = c.packetData[:entirePacketSize] + } + + if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil { + return nil, err + } else { + c.oracleCamouflage -= uint32(n) + } + + remainingCrypted := c.packetData[firstBlockLength:macStart] + c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) + + mac := c.packetData[macStart:] + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData[:macStart]) + c.macResult = c.mac.Sum(c.macResult[:0]) + if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { + return nil, cbcError("ssh: MAC failure") + } + } + + return c.packetData[prefixLen:paddingStart], nil +} + +func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) + + // Length of encrypted portion of the packet (header, payload, padding). + // Enforce minimum padding and packet size. + encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) + // Enforce block size. + encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize + + length := encLength - 4 + paddingLength := int(length) - (1 + len(packet)) + + // Overall buffer contains: header, payload, padding, mac. + // Space for the MAC is reserved in the capacity but not the slice length. + bufferSize := encLength + c.macSize + if uint32(cap(c.packetData)) < bufferSize { + c.packetData = make([]byte, encLength, bufferSize) + } else { + c.packetData = c.packetData[:encLength] + } + + p := c.packetData + + // Packet header. + binary.BigEndian.PutUint32(p, length) + p = p[4:] + p[0] = byte(paddingLength) + + // Payload. + p = p[1:] + copy(p, packet) + + // Padding. + p = p[len(packet):] + if _, err := io.ReadFull(rand, p); err != nil { + return err + } + + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData) + // The MAC is now appended into the capacity reserved for it earlier. + c.packetData = c.mac.Sum(c.packetData) + } + + c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) + + if _, err := w.Write(c.packetData); err != nil { + return err + } + + return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go new file mode 100644 index 000000000..0b9fbe500 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -0,0 +1,213 @@ +// Copyright 2011 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. + +package ssh + +import ( + "errors" + "fmt" + "net" + "sync" +) + +// Client implements a traditional SSH client that supports shells, +// subprocesses, port forwarding and tunneled dialing. +type Client struct { + Conn + + forwards forwardList // forwarded tcpip connections from the remote side + mu sync.Mutex + channelHandlers map[string]chan NewChannel +} + +// HandleChannelOpen returns a channel on which NewChannel requests +// for the given type are sent. If the type already is being handled, +// nil is returned. The channel is closed when the connection is closed. +func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { + c.mu.Lock() + defer c.mu.Unlock() + if c.channelHandlers == nil { + // The SSH channel has been closed. + c := make(chan NewChannel) + close(c) + return c + } + + ch := c.channelHandlers[channelType] + if ch != nil { + return nil + } + + ch = make(chan NewChannel, 16) + c.channelHandlers[channelType] = ch + return ch +} + +// NewClient creates a Client on top of the given connection. +func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { + conn := &Client{ + Conn: c, + channelHandlers: make(map[string]chan NewChannel, 1), + } + + go conn.handleGlobalRequests(reqs) + go conn.handleChannelOpens(chans) + go func() { + conn.Wait() + conn.forwards.closeAll() + }() + go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) + return conn +} + +// NewClientConn establishes an authenticated SSH connection using c +// as the underlying transport. The Request and NewChannel channels +// must be serviced or the connection will hang. +func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + conn := &connection{ + sshConn: sshConn{conn: c}, + } + + if err := conn.clientHandshake(addr, &fullConf); err != nil { + c.Close() + return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) + } + conn.mux = newMux(conn.transport) + return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil +} + +// clientHandshake performs the client side key exchange. See RFC 4253 Section +// 7. +func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { + if config.ClientVersion != "" { + c.clientVersion = []byte(config.ClientVersion) + } else { + c.clientVersion = []byte(packageVersion) + } + var err error + c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) + if err != nil { + return err + } + + c.transport = newClientTransport( + newTransport(c.sshConn.conn, config.Rand, true /* is client */), + c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) + if err := c.transport.requestKeyChange(); err != nil { + return err + } + + if packet, err := c.transport.readPacket(); err != nil { + return err + } else if packet[0] != msgNewKeys { + return unexpectedMessageError(msgNewKeys, packet[0]) + } + + // We just did the key change, so the session ID is established. + c.sessionID = c.transport.getSessionID() + + return c.clientAuthenticate(config) +} + +// verifyHostKeySignature verifies the host key obtained in the key +// exchange. +func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { + sig, rest, ok := parseSignatureBody(result.Signature) + if len(rest) > 0 || !ok { + return errors.New("ssh: signature parse error") + } + + return hostKey.Verify(result.H, sig) +} + +// NewSession opens a new Session for this client. (A session is a remote +// execution of a program.) +func (c *Client) NewSession() (*Session, error) { + ch, in, err := c.OpenChannel("session", nil) + if err != nil { + return nil, err + } + return newSession(ch, in) +} + +func (c *Client) handleGlobalRequests(incoming <-chan *Request) { + for r := range incoming { + // This handles keepalive messages and matches + // the behaviour of OpenSSH. + r.Reply(false, nil) + } +} + +// handleChannelOpens channel open messages from the remote side. +func (c *Client) handleChannelOpens(in <-chan NewChannel) { + for ch := range in { + c.mu.Lock() + handler := c.channelHandlers[ch.ChannelType()] + c.mu.Unlock() + + if handler != nil { + handler <- ch + } else { + ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) + } + } + + c.mu.Lock() + for _, ch := range c.channelHandlers { + close(ch) + } + c.channelHandlers = nil + c.mu.Unlock() +} + +// Dial starts a client connection to the given SSH server. It is a +// convenience function that connects to the given network address, +// initiates the SSH handshake, and then sets up a Client. For access +// to incoming channels and requests, use net.Dial with NewClientConn +// instead. +func Dial(network, addr string, config *ClientConfig) (*Client, error) { + conn, err := net.Dial(network, addr) + if err != nil { + return nil, err + } + c, chans, reqs, err := NewClientConn(conn, addr, config) + if err != nil { + return nil, err + } + return NewClient(c, chans, reqs), nil +} + +// A ClientConfig structure is used to configure a Client. It must not be +// modified after having been passed to an SSH function. +type ClientConfig struct { + // Config contains configuration that is shared between clients and + // servers. + Config + + // User contains the username to authenticate as. + User string + + // Auth contains possible authentication methods to use with the + // server. Only the first instance of a particular RFC 4252 method will + // be used during authentication. + Auth []AuthMethod + + // HostKeyCallback, if not nil, is called during the cryptographic + // handshake to validate the server's host key. A nil HostKeyCallback + // implies that all host keys are accepted. + HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error + + // ClientVersion contains the version identification string that will + // be used for the connection. If empty, a reasonable default is used. + ClientVersion string + + // HostKeyAlgorithms lists the key types that the client will + // accept from the server as host key, in order of + // preference. If empty, a reasonable default is used. Any + // string returned from PublicKey.Type method may be used, or + // any of the CertAlgoXxxx and KeyAlgoXxxx constants. + HostKeyAlgorithms []string +} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go new file mode 100644 index 000000000..e15be3ef2 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -0,0 +1,441 @@ +// Copyright 2011 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. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" +) + +// clientAuthenticate authenticates with the remote server. See RFC 4252. +func (c *connection) clientAuthenticate(config *ClientConfig) error { + // initiate user auth session + if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { + return err + } + packet, err := c.transport.readPacket() + if err != nil { + return err + } + var serviceAccept serviceAcceptMsg + if err := Unmarshal(packet, &serviceAccept); err != nil { + return err + } + + // during the authentication phase the client first attempts the "none" method + // then any untried methods suggested by the server. + tried := make(map[string]bool) + var lastMethods []string + for auth := AuthMethod(new(noneAuth)); auth != nil; { + ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand) + if err != nil { + return err + } + if ok { + // success + return nil + } + tried[auth.method()] = true + if methods == nil { + methods = lastMethods + } + lastMethods = methods + + auth = nil + + findNext: + for _, a := range config.Auth { + candidateMethod := a.method() + if tried[candidateMethod] { + continue + } + for _, meth := range methods { + if meth == candidateMethod { + auth = a + break findNext + } + } + } + } + return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried)) +} + +func keys(m map[string]bool) []string { + s := make([]string, 0, len(m)) + + for key := range m { + s = append(s, key) + } + return s +} + +// An AuthMethod represents an instance of an RFC 4252 authentication method. +type AuthMethod interface { + // auth authenticates user over transport t. + // Returns true if authentication is successful. + // If authentication is not successful, a []string of alternative + // method names is returned. If the slice is nil, it will be ignored + // and the previous set of possible methods will be reused. + auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error) + + // method returns the RFC 4252 method name. + method() string +} + +// "none" authentication, RFC 4252 section 5.2. +type noneAuth int + +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + if err := c.writePacket(Marshal(&userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: "none", + })); err != nil { + return false, nil, err + } + + return handleAuthResponse(c) +} + +func (n *noneAuth) method() string { + return "none" +} + +// passwordCallback is an AuthMethod that fetches the password through +// a function call, e.g. by prompting the user. +type passwordCallback func() (password string, err error) + +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + type passwordAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + Reply bool + Password string + } + + pw, err := cb() + // REVIEW NOTE: is there a need to support skipping a password attempt? + // The program may only find out that the user doesn't have a password + // when prompting. + if err != nil { + return false, nil, err + } + + if err := c.writePacket(Marshal(&passwordAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + Reply: false, + Password: pw, + })); err != nil { + return false, nil, err + } + + return handleAuthResponse(c) +} + +func (cb passwordCallback) method() string { + return "password" +} + +// Password returns an AuthMethod using the given password. +func Password(secret string) AuthMethod { + return passwordCallback(func() (string, error) { return secret, nil }) +} + +// PasswordCallback returns an AuthMethod that uses a callback for +// fetching a password. +func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { + return passwordCallback(prompt) +} + +type publickeyAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + // HasSig indicates to the receiver packet that the auth request is signed and + // should be used for authentication of the request. + HasSig bool + Algoname string + PubKey []byte + // Sig is tagged with "rest" so Marshal will exclude it during + // validateKey + Sig []byte `ssh:"rest"` +} + +// publicKeyCallback is an AuthMethod that uses a set of key +// pairs for authentication. +type publicKeyCallback func() ([]Signer, error) + +func (cb publicKeyCallback) method() string { + return "publickey" +} + +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + // Authentication is performed in two stages. The first stage sends an + // enquiry to test if each key is acceptable to the remote. The second + // stage attempts to authenticate with the valid keys obtained in the + // first stage. + + signers, err := cb() + if err != nil { + return false, nil, err + } + var validKeys []Signer + for _, signer := range signers { + if ok, err := validateKey(signer.PublicKey(), user, c); ok { + validKeys = append(validKeys, signer) + } else { + if err != nil { + return false, nil, err + } + } + } + + // methods that may continue if this auth is not successful. + var methods []string + for _, signer := range validKeys { + pub := signer.PublicKey() + + pubKey := pub.Marshal() + sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + }, []byte(pub.Type()), pubKey)) + if err != nil { + return false, nil, err + } + + // manually wrap the serialized signature in a string + s := Marshal(sign) + sig := make([]byte, stringLength(len(s))) + marshalString(sig, s) + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + HasSig: true, + Algoname: pub.Type(), + PubKey: pubKey, + Sig: sig, + } + p := Marshal(&msg) + if err := c.writePacket(p); err != nil { + return false, nil, err + } + var success bool + success, methods, err = handleAuthResponse(c) + if err != nil { + return false, nil, err + } + if success { + return success, methods, err + } + } + return false, methods, nil +} + +// validateKey validates the key provided is acceptable to the server. +func validateKey(key PublicKey, user string, c packetConn) (bool, error) { + pubKey := key.Marshal() + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: "publickey", + HasSig: false, + Algoname: key.Type(), + PubKey: pubKey, + } + if err := c.writePacket(Marshal(&msg)); err != nil { + return false, err + } + + return confirmKeyAck(key, c) +} + +func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { + pubKey := key.Marshal() + algoname := key.Type() + + for { + packet, err := c.readPacket() + if err != nil { + return false, err + } + switch packet[0] { + case msgUserAuthBanner: + // TODO(gpaul): add callback to present the banner to the user + case msgUserAuthPubKeyOk: + var msg userAuthPubKeyOkMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, err + } + if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { + return false, nil + } + return true, nil + case msgUserAuthFailure: + return false, nil + default: + return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + } +} + +// PublicKeys returns an AuthMethod that uses the given key +// pairs. +func PublicKeys(signers ...Signer) AuthMethod { + return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) +} + +// PublicKeysCallback returns an AuthMethod that runs the given +// function to obtain a list of key pairs. +func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { + return publicKeyCallback(getSigners) +} + +// handleAuthResponse returns whether the preceding authentication request succeeded +// along with a list of remaining authentication methods to try next and +// an error if an unexpected response was received. +func handleAuthResponse(c packetConn) (bool, []string, error) { + for { + packet, err := c.readPacket() + if err != nil { + return false, nil, err + } + + switch packet[0] { + case msgUserAuthBanner: + // TODO: add callback to present the banner to the user + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + return false, msg.Methods, nil + case msgUserAuthSuccess: + return true, nil, nil + case msgDisconnect: + return false, nil, io.EOF + default: + return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + } +} + +// KeyboardInteractiveChallenge should print questions, optionally +// disabling echoing (e.g. for passwords), and return all the answers. +// Challenge may be called multiple times in a single session. After +// successful authentication, the server may send a challenge with no +// questions, for which the user and instruction messages should be +// printed. RFC 4256 section 3.3 details how the UI should behave for +// both CLI and GUI environments. +type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) + +// KeyboardInteractive returns a AuthMethod using a prompt/response +// sequence controlled by the server. +func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { + return challenge +} + +func (cb KeyboardInteractiveChallenge) method() string { + return "keyboard-interactive" +} + +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + type initiateMsg struct { + User string `sshtype:"50"` + Service string + Method string + Language string + Submethods string + } + + if err := c.writePacket(Marshal(&initiateMsg{ + User: user, + Service: serviceSSH, + Method: "keyboard-interactive", + })); err != nil { + return false, nil, err + } + + for { + packet, err := c.readPacket() + if err != nil { + return false, nil, err + } + + // like handleAuthResponse, but with less options. + switch packet[0] { + case msgUserAuthBanner: + // TODO: Print banners during userauth. + continue + case msgUserAuthInfoRequest: + // OK + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + return false, msg.Methods, nil + case msgUserAuthSuccess: + return true, nil, nil + default: + return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } + + var msg userAuthInfoRequestMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + + // Manually unpack the prompt/echo pairs. + rest := msg.Prompts + var prompts []string + var echos []bool + for i := 0; i < int(msg.NumPrompts); i++ { + prompt, r, ok := parseString(rest) + if !ok || len(r) == 0 { + return false, nil, errors.New("ssh: prompt format error") + } + prompts = append(prompts, string(prompt)) + echos = append(echos, r[0] != 0) + rest = r[1:] + } + + if len(rest) != 0 { + return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs") + } + + answers, err := cb(msg.User, msg.Instruction, prompts, echos) + if err != nil { + return false, nil, err + } + + if len(answers) != len(prompts) { + return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") + } + responseLength := 1 + 4 + for _, a := range answers { + responseLength += stringLength(len(a)) + } + serialized := make([]byte, responseLength) + p := serialized + p[0] = msgUserAuthInfoResponse + p = p[1:] + p = marshalUint32(p, uint32(len(answers))) + for _, a := range answers { + p = marshalString(p, []byte(a)) + } + + if err := c.writePacket(serialized); err != nil { + return false, nil, err + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go new file mode 100644 index 000000000..9fc739e1d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -0,0 +1,354 @@ +// Copyright 2011 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. + +package ssh + +import ( + "crypto" + "crypto/rand" + "fmt" + "io" + "sync" + + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" +) + +// These are string constants in the SSH protocol. +const ( + compressionNone = "none" + serviceUserAuth = "ssh-userauth" + serviceSSH = "ssh-connection" +) + +// supportedCiphers specifies the supported ciphers in preference order. +var supportedCiphers = []string{ + "aes128-ctr", "aes192-ctr", "aes256-ctr", + "aes128-gcm@openssh.com", + "arcfour256", "arcfour128", +} + +// supportedKexAlgos specifies the supported key-exchange algorithms in +// preference order. +var supportedKexAlgos = []string{ + kexAlgoCurve25519SHA256, + // P384 and P521 are not constant-time yet, but since we don't + // reuse ephemeral keys, using them for ECDH should be OK. + kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, + kexAlgoDH14SHA1, kexAlgoDH1SHA1, +} + +// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods +// of authenticating servers) in preference order. +var supportedHostKeyAlgos = []string{ + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, + CertAlgoECDSA384v01, CertAlgoECDSA521v01, + + KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, + KeyAlgoRSA, KeyAlgoDSA, +} + +// supportedMACs specifies a default set of MAC algorithms in preference order. +// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed +// because they have reached the end of their useful life. +var supportedMACs = []string{ + "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", +} + +var supportedCompressions = []string{compressionNone} + +// hashFuncs keeps the mapping of supported algorithms to their respective +// hashes needed for signature verification. +var hashFuncs = map[string]crypto.Hash{ + KeyAlgoRSA: crypto.SHA1, + KeyAlgoDSA: crypto.SHA1, + KeyAlgoECDSA256: crypto.SHA256, + KeyAlgoECDSA384: crypto.SHA384, + KeyAlgoECDSA521: crypto.SHA512, + CertAlgoRSAv01: crypto.SHA1, + CertAlgoDSAv01: crypto.SHA1, + CertAlgoECDSA256v01: crypto.SHA256, + CertAlgoECDSA384v01: crypto.SHA384, + CertAlgoECDSA521v01: crypto.SHA512, +} + +// unexpectedMessageError results when the SSH message that we received didn't +// match what we wanted. +func unexpectedMessageError(expected, got uint8) error { + return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) +} + +// parseError results from a malformed SSH message. +func parseError(tag uint8) error { + return fmt.Errorf("ssh: parse error in message type %d", tag) +} + +func findCommon(what string, client []string, server []string) (common string, err error) { + for _, c := range client { + for _, s := range server { + if c == s { + return c, nil + } + } + } + return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) +} + +type directionAlgorithms struct { + Cipher string + MAC string + Compression string +} + +type algorithms struct { + kex string + hostKey string + w directionAlgorithms + r directionAlgorithms +} + +func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { + result := &algorithms{} + + result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) + if err != nil { + return + } + + result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + if err != nil { + return + } + + result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + if err != nil { + return + } + + result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + if err != nil { + return + } + + result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) + if err != nil { + return + } + + result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) + if err != nil { + return + } + + result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + if err != nil { + return + } + + result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + if err != nil { + return + } + + return result, nil +} + +// If rekeythreshold is too small, we can't make any progress sending +// stuff. +const minRekeyThreshold uint64 = 256 + +// Config contains configuration data common to both ServerConfig and +// ClientConfig. +type Config struct { + // Rand provides the source of entropy for cryptographic + // primitives. If Rand is nil, the cryptographic random reader + // in package crypto/rand will be used. + Rand io.Reader + + // The maximum number of bytes sent or received after which a + // new key is negotiated. It must be at least 256. If + // unspecified, 1 gigabyte is used. + RekeyThreshold uint64 + + // The allowed key exchanges algorithms. If unspecified then a + // default set of algorithms is used. + KeyExchanges []string + + // The allowed cipher algorithms. If unspecified then a sensible + // default is used. + Ciphers []string + + // The allowed MAC algorithms. If unspecified then a sensible default + // is used. + MACs []string +} + +// SetDefaults sets sensible values for unset fields in config. This is +// exported for testing: Configs passed to SSH functions are copied and have +// default values set automatically. +func (c *Config) SetDefaults() { + if c.Rand == nil { + c.Rand = rand.Reader + } + if c.Ciphers == nil { + c.Ciphers = supportedCiphers + } + var ciphers []string + for _, c := range c.Ciphers { + if cipherModes[c] != nil { + // reject the cipher if we have no cipherModes definition + ciphers = append(ciphers, c) + } + } + c.Ciphers = ciphers + + if c.KeyExchanges == nil { + c.KeyExchanges = supportedKexAlgos + } + + if c.MACs == nil { + c.MACs = supportedMACs + } + + if c.RekeyThreshold == 0 { + // RFC 4253, section 9 suggests rekeying after 1G. + c.RekeyThreshold = 1 << 30 + } + if c.RekeyThreshold < minRekeyThreshold { + c.RekeyThreshold = minRekeyThreshold + } +} + +// buildDataSignedForAuth returns the data that is signed in order to prove +// possession of a private key. See RFC 4252, section 7. +func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { + data := struct { + Session []byte + Type byte + User string + Service string + Method string + Sign bool + Algo []byte + PubKey []byte + }{ + sessionId, + msgUserAuthRequest, + req.User, + req.Service, + req.Method, + true, + algo, + pubKey, + } + return Marshal(data) +} + +func appendU16(buf []byte, n uint16) []byte { + return append(buf, byte(n>>8), byte(n)) +} + +func appendU32(buf []byte, n uint32) []byte { + return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendU64(buf []byte, n uint64) []byte { + return append(buf, + byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), + byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendInt(buf []byte, n int) []byte { + return appendU32(buf, uint32(n)) +} + +func appendString(buf []byte, s string) []byte { + buf = appendU32(buf, uint32(len(s))) + buf = append(buf, s...) + return buf +} + +func appendBool(buf []byte, b bool) []byte { + if b { + return append(buf, 1) + } + return append(buf, 0) +} + +// newCond is a helper to hide the fact that there is no usable zero +// value for sync.Cond. +func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } + +// window represents the buffer available to clients +// wishing to write to a channel. +type window struct { + *sync.Cond + win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 + writeWaiters int + closed bool +} + +// add adds win to the amount of window available +// for consumers. +func (w *window) add(win uint32) bool { + // a zero sized window adjust is a noop. + if win == 0 { + return true + } + w.L.Lock() + if w.win+win < win { + w.L.Unlock() + return false + } + w.win += win + // It is unusual that multiple goroutines would be attempting to reserve + // window space, but not guaranteed. Use broadcast to notify all waiters + // that additional window is available. + w.Broadcast() + w.L.Unlock() + return true +} + +// close sets the window to closed, so all reservations fail +// immediately. +func (w *window) close() { + w.L.Lock() + w.closed = true + w.Broadcast() + w.L.Unlock() +} + +// reserve reserves win from the available window capacity. +// If no capacity remains, reserve will block. reserve may +// return less than requested. +func (w *window) reserve(win uint32) (uint32, error) { + var err error + w.L.Lock() + w.writeWaiters++ + w.Broadcast() + for w.win == 0 && !w.closed { + w.Wait() + } + w.writeWaiters-- + if w.win < win { + win = w.win + } + w.win -= win + if w.closed { + err = io.EOF + } + w.L.Unlock() + return win, err +} + +// waitWriterBlocked waits until some goroutine is blocked for further +// writes. It is used in tests only. +func (w *window) waitWriterBlocked() { + w.Cond.L.Lock() + for w.writeWaiters == 0 { + w.Cond.Wait() + } + w.Cond.L.Unlock() +} diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go new file mode 100644 index 000000000..979d919e8 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/connection.go @@ -0,0 +1,144 @@ +// Copyright 2013 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. + +package ssh + +import ( + "fmt" + "net" +) + +// OpenChannelError is returned if the other side rejects an +// OpenChannel request. +type OpenChannelError struct { + Reason RejectionReason + Message string +} + +func (e *OpenChannelError) Error() string { + return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) +} + +// ConnMetadata holds metadata for the connection. +type ConnMetadata interface { + // User returns the user ID for this connection. + // It is empty if no authentication is used. + User() string + + // SessionID returns the sesson hash, also denoted by H. + SessionID() []byte + + // ClientVersion returns the client's version string as hashed + // into the session ID. + ClientVersion() []byte + + // ServerVersion returns the server's version string as hashed + // into the session ID. + ServerVersion() []byte + + // RemoteAddr returns the remote address for this connection. + RemoteAddr() net.Addr + + // LocalAddr returns the local address for this connection. + LocalAddr() net.Addr +} + +// Conn represents an SSH connection for both server and client roles. +// Conn is the basis for implementing an application layer, such +// as ClientConn, which implements the traditional shell access for +// clients. +type Conn interface { + ConnMetadata + + // SendRequest sends a global request, and returns the + // reply. If wantReply is true, it returns the response status + // and payload. See also RFC4254, section 4. + SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) + + // OpenChannel tries to open an channel. If the request is + // rejected, it returns *OpenChannelError. On success it returns + // the SSH Channel and a Go channel for incoming, out-of-band + // requests. The Go channel must be serviced, or the + // connection will hang. + OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) + + // Close closes the underlying network connection + Close() error + + // Wait blocks until the connection has shut down, and returns the + // error causing the shutdown. + Wait() error + + // TODO(hanwen): consider exposing: + // RequestKeyChange + // Disconnect +} + +// DiscardRequests consumes and rejects all requests from the +// passed-in channel. +func DiscardRequests(in <-chan *Request) { + for req := range in { + if req.WantReply { + req.Reply(false, nil) + } + } +} + +// A connection represents an incoming connection. +type connection struct { + transport *handshakeTransport + sshConn + + // The connection protocol. + *mux +} + +func (c *connection) Close() error { + return c.sshConn.conn.Close() +} + +// sshconn provides net.Conn metadata, but disallows direct reads and +// writes. +type sshConn struct { + conn net.Conn + + user string + sessionID []byte + clientVersion []byte + serverVersion []byte +} + +func dup(src []byte) []byte { + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +func (c *sshConn) User() string { + return c.user +} + +func (c *sshConn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +func (c *sshConn) Close() error { + return c.conn.Close() +} + +func (c *sshConn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +func (c *sshConn) SessionID() []byte { + return dup(c.sessionID) +} + +func (c *sshConn) ClientVersion() []byte { + return dup(c.clientVersion) +} + +func (c *sshConn) ServerVersion() []byte { + return dup(c.serverVersion) +} diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go new file mode 100644 index 000000000..a5ff8af6b --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/doc.go @@ -0,0 +1,18 @@ +// Copyright 2011 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. + +/* +Package ssh implements an SSH client and server. + +SSH is a transport security protocol, an authentication protocol and a +family of application protocols. The most typical application level +protocol is a remote shell and this is specifically implemented. However, +the multiplexed nature of SSH is exposed to users that wish to support +others. + +References: + [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD + [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 +*/ +package ssh diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go new file mode 100644 index 000000000..1c54f7587 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -0,0 +1,412 @@ +// Copyright 2013 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. + +package ssh + +import ( + "crypto/rand" + "errors" + "fmt" + "io" + "log" + "net" + "sync" +) + +// debugHandshake, if set, prints messages sent and received. Key +// exchange messages are printed as if DH were used, so the debug +// messages are wrong when using ECDH. +const debugHandshake = false + +// keyingTransport is a packet based transport that supports key +// changes. It need not be thread-safe. It should pass through +// msgNewKeys in both directions. +type keyingTransport interface { + packetConn + + // prepareKeyChange sets up a key change. The key change for a + // direction will be effected if a msgNewKeys message is sent + // or received. + prepareKeyChange(*algorithms, *kexResult) error + + // getSessionID returns the session ID. prepareKeyChange must + // have been called once. + getSessionID() []byte +} + +// rekeyingTransport is the interface of handshakeTransport that we +// (internally) expose to ClientConn and ServerConn. +type rekeyingTransport interface { + packetConn + + // requestKeyChange asks the remote side to change keys. All + // writes are blocked until the key change succeeds, which is + // signaled by reading a msgNewKeys. + requestKeyChange() error + + // getSessionID returns the session ID. This is only valid + // after the first key change has completed. + getSessionID() []byte +} + +// handshakeTransport implements rekeying on top of a keyingTransport +// and offers a thread-safe writePacket() interface. +type handshakeTransport struct { + conn keyingTransport + config *Config + + serverVersion []byte + clientVersion []byte + + // hostKeys is non-empty if we are the server. In that case, + // it contains all host keys that can be used to sign the + // connection. + hostKeys []Signer + + // hostKeyAlgorithms is non-empty if we are the client. In that case, + // we accept these key types from the server as host key. + hostKeyAlgorithms []string + + // On read error, incoming is closed, and readError is set. + incoming chan []byte + readError error + + // data for host key checking + hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error + dialAddress string + remoteAddr net.Addr + + readSinceKex uint64 + + // Protects the writing side of the connection + mu sync.Mutex + cond *sync.Cond + sentInitPacket []byte + sentInitMsg *kexInitMsg + writtenSinceKex uint64 + writeError error +} + +func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { + t := &handshakeTransport{ + conn: conn, + serverVersion: serverVersion, + clientVersion: clientVersion, + incoming: make(chan []byte, 16), + config: config, + } + t.cond = sync.NewCond(&t.mu) + return t +} + +func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.dialAddress = dialAddr + t.remoteAddr = addr + t.hostKeyCallback = config.HostKeyCallback + if config.HostKeyAlgorithms != nil { + t.hostKeyAlgorithms = config.HostKeyAlgorithms + } else { + t.hostKeyAlgorithms = supportedHostKeyAlgos + } + go t.readLoop() + return t +} + +func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.hostKeys = config.hostKeys + go t.readLoop() + return t +} + +func (t *handshakeTransport) getSessionID() []byte { + return t.conn.getSessionID() +} + +func (t *handshakeTransport) id() string { + if len(t.hostKeys) > 0 { + return "server" + } + return "client" +} + +func (t *handshakeTransport) readPacket() ([]byte, error) { + p, ok := <-t.incoming + if !ok { + return nil, t.readError + } + return p, nil +} + +func (t *handshakeTransport) readLoop() { + for { + p, err := t.readOnePacket() + if err != nil { + t.readError = err + close(t.incoming) + break + } + if p[0] == msgIgnore || p[0] == msgDebug { + continue + } + t.incoming <- p + } + + // If we can't read, declare the writing part dead too. + t.mu.Lock() + defer t.mu.Unlock() + if t.writeError == nil { + t.writeError = t.readError + } + t.cond.Broadcast() +} + +func (t *handshakeTransport) readOnePacket() ([]byte, error) { + if t.readSinceKex > t.config.RekeyThreshold { + if err := t.requestKeyChange(); err != nil { + return nil, err + } + } + + p, err := t.conn.readPacket() + if err != nil { + return nil, err + } + + t.readSinceKex += uint64(len(p)) + if debugHandshake { + msg, err := decode(p) + log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err) + } + if p[0] != msgKexInit { + return p, nil + } + err = t.enterKeyExchange(p) + + t.mu.Lock() + if err != nil { + // drop connection + t.conn.Close() + t.writeError = err + } + + if debugHandshake { + log.Printf("%s exited key exchange, err %v", t.id(), err) + } + + // Unblock writers. + t.sentInitMsg = nil + t.sentInitPacket = nil + t.cond.Broadcast() + t.writtenSinceKex = 0 + t.mu.Unlock() + + if err != nil { + return nil, err + } + + t.readSinceKex = 0 + return []byte{msgNewKeys}, nil +} + +// sendKexInit sends a key change message, and returns the message +// that was sent. After initiating the key change, all writes will be +// blocked until the change is done, and a failed key change will +// close the underlying transport. This function is safe for +// concurrent use by multiple goroutines. +func (t *handshakeTransport) sendKexInit() (*kexInitMsg, []byte, error) { + t.mu.Lock() + defer t.mu.Unlock() + return t.sendKexInitLocked() +} + +func (t *handshakeTransport) requestKeyChange() error { + _, _, err := t.sendKexInit() + return err +} + +// sendKexInitLocked sends a key change message. t.mu must be locked +// while this happens. +func (t *handshakeTransport) sendKexInitLocked() (*kexInitMsg, []byte, error) { + // kexInits may be sent either in response to the other side, + // or because our side wants to initiate a key change, so we + // may have already sent a kexInit. In that case, don't send a + // second kexInit. + if t.sentInitMsg != nil { + return t.sentInitMsg, t.sentInitPacket, nil + } + msg := &kexInitMsg{ + KexAlgos: t.config.KeyExchanges, + CiphersClientServer: t.config.Ciphers, + CiphersServerClient: t.config.Ciphers, + MACsClientServer: t.config.MACs, + MACsServerClient: t.config.MACs, + CompressionClientServer: supportedCompressions, + CompressionServerClient: supportedCompressions, + } + io.ReadFull(rand.Reader, msg.Cookie[:]) + + if len(t.hostKeys) > 0 { + for _, k := range t.hostKeys { + msg.ServerHostKeyAlgos = append( + msg.ServerHostKeyAlgos, k.PublicKey().Type()) + } + } else { + msg.ServerHostKeyAlgos = t.hostKeyAlgorithms + } + packet := Marshal(msg) + + // writePacket destroys the contents, so save a copy. + packetCopy := make([]byte, len(packet)) + copy(packetCopy, packet) + + if err := t.conn.writePacket(packetCopy); err != nil { + return nil, nil, err + } + + t.sentInitMsg = msg + t.sentInitPacket = packet + return msg, packet, nil +} + +func (t *handshakeTransport) writePacket(p []byte) error { + t.mu.Lock() + defer t.mu.Unlock() + + if t.writtenSinceKex > t.config.RekeyThreshold { + t.sendKexInitLocked() + } + for t.sentInitMsg != nil && t.writeError == nil { + t.cond.Wait() + } + if t.writeError != nil { + return t.writeError + } + t.writtenSinceKex += uint64(len(p)) + + switch p[0] { + case msgKexInit: + return errors.New("ssh: only handshakeTransport can send kexInit") + case msgNewKeys: + return errors.New("ssh: only handshakeTransport can send newKeys") + default: + return t.conn.writePacket(p) + } +} + +func (t *handshakeTransport) Close() error { + return t.conn.Close() +} + +// enterKeyExchange runs the key exchange. +func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + if debugHandshake { + log.Printf("%s entered key exchange", t.id()) + } + myInit, myInitPacket, err := t.sendKexInit() + if err != nil { + return err + } + + otherInit := &kexInitMsg{} + if err := Unmarshal(otherInitPacket, otherInit); err != nil { + return err + } + + magics := handshakeMagics{ + clientVersion: t.clientVersion, + serverVersion: t.serverVersion, + clientKexInit: otherInitPacket, + serverKexInit: myInitPacket, + } + + clientInit := otherInit + serverInit := myInit + if len(t.hostKeys) == 0 { + clientInit = myInit + serverInit = otherInit + + magics.clientKexInit = myInitPacket + magics.serverKexInit = otherInitPacket + } + + algs, err := findAgreedAlgorithms(clientInit, serverInit) + if err != nil { + return err + } + + // We don't send FirstKexFollows, but we handle receiving it. + if otherInit.FirstKexFollows && algs.kex != otherInit.KexAlgos[0] { + // other side sent a kex message for the wrong algorithm, + // which we have to ignore. + if _, err := t.conn.readPacket(); err != nil { + return err + } + } + + kex, ok := kexAlgoMap[algs.kex] + if !ok { + return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex) + } + + var result *kexResult + if len(t.hostKeys) > 0 { + result, err = t.server(kex, algs, &magics) + } else { + result, err = t.client(kex, algs, &magics) + } + + if err != nil { + return err + } + + t.conn.prepareKeyChange(algs, result) + if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { + return err + } + if packet, err := t.conn.readPacket(); err != nil { + return err + } else if packet[0] != msgNewKeys { + return unexpectedMessageError(msgNewKeys, packet[0]) + } + return nil +} + +func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { + var hostKey Signer + for _, k := range t.hostKeys { + if algs.hostKey == k.PublicKey().Type() { + hostKey = k + } + } + + r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey) + return r, err +} + +func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { + result, err := kex.Client(t.conn, t.config.Rand, magics) + if err != nil { + return nil, err + } + + hostKey, err := ParsePublicKey(result.HostKey) + if err != nil { + return nil, err + } + + if err := verifyHostKeySignature(hostKey, result); err != nil { + return nil, err + } + + if t.hostKeyCallback != nil { + err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) + if err != nil { + return nil, err + } + } + + return result, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go new file mode 100644 index 000000000..3ec603c0a --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/kex.go @@ -0,0 +1,526 @@ +// Copyright 2013 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. + +package ssh + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/subtle" + "errors" + "io" + "math/big" + + "golang.org/x/crypto/curve25519" +) + +const ( + kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" + kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" + kexAlgoECDH256 = "ecdh-sha2-nistp256" + kexAlgoECDH384 = "ecdh-sha2-nistp384" + kexAlgoECDH521 = "ecdh-sha2-nistp521" + kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" +) + +// kexResult captures the outcome of a key exchange. +type kexResult struct { + // Session hash. See also RFC 4253, section 8. + H []byte + + // Shared secret. See also RFC 4253, section 8. + K []byte + + // Host key as hashed into H. + HostKey []byte + + // Signature of H. + Signature []byte + + // A cryptographic hash function that matches the security + // level of the key exchange algorithm. It is used for + // calculating H, and for deriving keys from H and K. + Hash crypto.Hash + + // The session ID, which is the first H computed. This is used + // to signal data inside transport. + SessionID []byte +} + +// handshakeMagics contains data that is always included in the +// session hash. +type handshakeMagics struct { + clientVersion, serverVersion []byte + clientKexInit, serverKexInit []byte +} + +func (m *handshakeMagics) write(w io.Writer) { + writeString(w, m.clientVersion) + writeString(w, m.serverVersion) + writeString(w, m.clientKexInit) + writeString(w, m.serverKexInit) +} + +// kexAlgorithm abstracts different key exchange algorithms. +type kexAlgorithm interface { + // Server runs server-side key agreement, signing the result + // with a hostkey. + Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) + + // Client runs the client-side key agreement. Caller is + // responsible for verifying the host key signature. + Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) +} + +// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. +type dhGroup struct { + g, p *big.Int +} + +func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { + if theirPublic.Sign() <= 0 || theirPublic.Cmp(group.p) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") + } + return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil +} + +func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { + hashFunc := crypto.SHA1 + + x, err := rand.Int(randSource, group.p) + if err != nil { + return nil, err + } + X := new(big.Int).Exp(group.g, x, group.p) + kexDHInit := kexDHInitMsg{ + X: X, + } + if err := c.writePacket(Marshal(&kexDHInit)); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexDHReply kexDHReplyMsg + if err = Unmarshal(packet, &kexDHReply); err != nil { + return nil, err + } + + kInt, err := group.diffieHellman(kexDHReply.Y, x) + if err != nil { + return nil, err + } + + h := hashFunc.New() + magics.write(h) + writeString(h, kexDHReply.HostKey) + writeInt(h, X) + writeInt(h, kexDHReply.Y) + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: kexDHReply.HostKey, + Signature: kexDHReply.Signature, + Hash: crypto.SHA1, + }, nil +} + +func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + hashFunc := crypto.SHA1 + packet, err := c.readPacket() + if err != nil { + return + } + var kexDHInit kexDHInitMsg + if err = Unmarshal(packet, &kexDHInit); err != nil { + return + } + + y, err := rand.Int(randSource, group.p) + if err != nil { + return + } + + Y := new(big.Int).Exp(group.g, y, group.p) + kInt, err := group.diffieHellman(kexDHInit.X, y) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := hashFunc.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeInt(h, kexDHInit.X) + writeInt(h, Y) + + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, randSource, H) + if err != nil { + return nil, err + } + + kexDHReply := kexDHReplyMsg{ + HostKey: hostKeyBytes, + Y: Y, + Signature: sig, + } + packet = Marshal(&kexDHReply) + + err = c.writePacket(packet) + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA1, + }, nil +} + +// ecdh performs Elliptic Curve Diffie-Hellman key exchange as +// described in RFC 5656, section 4. +type ecdh struct { + curve elliptic.Curve +} + +func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + kexInit := kexECDHInitMsg{ + ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), + } + + serialized := Marshal(&kexInit) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + + x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) + if err != nil { + return nil, err + } + + // generate shared secret + secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kexInit.ClientPubKey) + writeString(h, reply.EphemeralPubKey) + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: ecHash(kex.curve), + }, nil +} + +// unmarshalECKey parses and checks an EC key. +func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { + x, y = elliptic.Unmarshal(curve, pubkey) + if x == nil { + return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") + } + if !validateECPublicKey(curve, x, y) { + return nil, nil, errors.New("ssh: public key not on curve") + } + return x, y, nil +} + +// validateECPublicKey checks that the point is a valid public key for +// the given curve. See [SEC1], 3.2.2 +func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + + if x.Cmp(curve.Params().P) >= 0 { + return false + } + + if y.Cmp(curve.Params().P) >= 0 { + return false + } + + if !curve.IsOnCurve(x, y) { + return false + } + + // We don't check if N * PubKey == 0, since + // + // - the NIST curves have cofactor = 1, so this is implicit. + // (We don't foresee an implementation that supports non NIST + // curves) + // + // - for ephemeral keys, we don't need to worry about small + // subgroup attacks. + return true +} + +func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexECDHInit kexECDHInitMsg + if err = Unmarshal(packet, &kexECDHInit); err != nil { + return nil, err + } + + clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) + if err != nil { + return nil, err + } + + // We could cache this key across multiple users/multiple + // connection attempts, but the benefit is small. OpenSSH + // generates a new key for each incoming connection. + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) + + // generate shared secret + secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexECDHInit.ClientPubKey) + writeString(h, serializedEphKey) + + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, rand, H) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: serializedEphKey, + HostKey: hostKeyBytes, + Signature: sig, + } + + serialized := Marshal(&reply) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + return &kexResult{ + H: H, + K: K, + HostKey: reply.HostKey, + Signature: sig, + Hash: ecHash(kex.curve), + }, nil +} + +var kexAlgoMap = map[string]kexAlgorithm{} + +func init() { + // This is the group called diffie-hellman-group1-sha1 in RFC + // 4253 and Oakley Group 2 in RFC 2409. + p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) + kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + } + + // This is the group called diffie-hellman-group14-sha1 in RFC + // 4253 and Oakley Group 14 in RFC 3526. + p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + + kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + } + + kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} + kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} + kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} + kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} +} + +// curve25519sha256 implements the curve25519-sha256@libssh.org key +// agreement protocol, as described in +// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt +type curve25519sha256 struct{} + +type curve25519KeyPair struct { + priv [32]byte + pub [32]byte +} + +func (kp *curve25519KeyPair) generate(rand io.Reader) error { + if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { + return err + } + curve25519.ScalarBaseMult(&kp.pub, &kp.priv) + return nil +} + +// curve25519Zeros is just an array of 32 zero bytes so that we have something +// convenient to compare against in order to reject curve25519 points with the +// wrong order. +var curve25519Zeros [32]byte + +func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + if len(reply.EphemeralPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var servPub, secret [32]byte + copy(servPub[:], reply.EphemeralPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &servPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kp.pub[:]) + writeString(h, reply.EphemeralPubKey) + + kInt := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: crypto.SHA256, + }, nil +} + +func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return + } + var kexInit kexECDHInitMsg + if err = Unmarshal(packet, &kexInit); err != nil { + return + } + + if len(kexInit.ClientPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + + var clientPub, secret [32]byte + copy(clientPub[:], kexInit.ClientPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &clientPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexInit.ClientPubKey) + writeString(h, kp.pub[:]) + + kInt := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + H := h.Sum(nil) + + sig, err := signAndMarshal(priv, rand, H) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: kp.pub[:], + HostKey: hostKeyBytes, + Signature: sig, + } + if err := c.writePacket(Marshal(&reply)); err != nil { + return nil, err + } + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA256, + }, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go new file mode 100644 index 000000000..cfc970b2c --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -0,0 +1,720 @@ +// Copyright 2012 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. + +package ssh + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509" + "encoding/asn1" + "encoding/base64" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "strings" +) + +// These constants represent the algorithm names for key types supported by this +// package. +const ( + KeyAlgoRSA = "ssh-rsa" + KeyAlgoDSA = "ssh-dss" + KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" + KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" + KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" +) + +// parsePubKey parses a public key of the given algorithm. +// Use ParsePublicKey for keys with prepended algorithm. +func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { + switch algo { + case KeyAlgoRSA: + return parseRSA(in) + case KeyAlgoDSA: + return parseDSA(in) + case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: + return parseECDSA(in) + case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01: + cert, err := parseCert(in, certToPrivAlgo(algo)) + if err != nil { + return nil, nil, err + } + return cert, nil, nil + } + return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err) +} + +// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format +// (see sshd(8) manual page) once the options and key type fields have been +// removed. +func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { + in = bytes.TrimSpace(in) + + i := bytes.IndexAny(in, " \t") + if i == -1 { + i = len(in) + } + base64Key := in[:i] + + key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) + n, err := base64.StdEncoding.Decode(key, base64Key) + if err != nil { + return nil, "", err + } + key = key[:n] + out, err = ParsePublicKey(key) + if err != nil { + return nil, "", err + } + comment = string(bytes.TrimSpace(in[i:])) + return out, comment, nil +} + +// ParseKnownHosts parses an entry in the format of the known_hosts file. +// +// The known_hosts format is documented in the sshd(8) manual page. This +// function will parse a single entry from in. On successful return, marker +// will contain the optional marker value (i.e. "cert-authority" or "revoked") +// or else be empty, hosts will contain the hosts that this entry matches, +// pubKey will contain the public key and comment will contain any trailing +// comment at the end of the line. See the sshd(8) manual page for the various +// forms that a host string can take. +// +// The unparsed remainder of the input will be returned in rest. This function +// can be called repeatedly to parse multiple entries. +// +// If no entries were found in the input then err will be io.EOF. Otherwise a +// non-nil err value indicates a parse error. +func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + // Strip out the begining of the known_host key. + // This is either an optional marker or a (set of) hostname(s). + keyFields := bytes.Fields(in) + if len(keyFields) < 3 || len(keyFields) > 5 { + return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") + } + + // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated + // list of hosts + marker := "" + if keyFields[0][0] == '@' { + marker = string(keyFields[0][1:]) + keyFields = keyFields[1:] + } + + hosts := string(keyFields[0]) + // keyFields[1] contains the key type (e.g. “ssh-rsaâ€). + // However, that information is duplicated inside the + // base64-encoded key and so is ignored here. + + key := bytes.Join(keyFields[2:], []byte(" ")) + if pubKey, comment, err = parseAuthorizedKey(key); err != nil { + return "", nil, nil, "", nil, err + } + + return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil + } + + return "", nil, nil, "", nil, io.EOF +} + +// ParseAuthorizedKeys parses a public key from an authorized_keys +// file used in OpenSSH according to the sshd(8) manual page. +func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + return out, comment, options, rest, nil + } + + // No key type recognised. Maybe there's an options field at + // the beginning. + var b byte + inQuote := false + var candidateOptions []string + optionStart := 0 + for i, b = range in { + isEnd := !inQuote && (b == ' ' || b == '\t') + if (b == ',' && !inQuote) || isEnd { + if i-optionStart > 0 { + candidateOptions = append(candidateOptions, string(in[optionStart:i])) + } + optionStart = i + 1 + } + if isEnd { + break + } + if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { + inQuote = !inQuote + } + } + for i < len(in) && (in[i] == ' ' || in[i] == '\t') { + i++ + } + if i == len(in) { + // Invalid line: unmatched quote + in = rest + continue + } + + in = in[i:] + i = bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + options = candidateOptions + return out, comment, options, rest, nil + } + + in = rest + continue + } + + return nil, "", nil, nil, errors.New("ssh: no key found") +} + +// ParsePublicKey parses an SSH public key formatted for use in +// the SSH wire protocol according to RFC 4253, section 6.6. +func ParsePublicKey(in []byte) (out PublicKey, err error) { + algo, in, ok := parseString(in) + if !ok { + return nil, errShortRead + } + var rest []byte + out, rest, err = parsePubKey(in, string(algo)) + if len(rest) > 0 { + return nil, errors.New("ssh: trailing junk in public key") + } + + return out, err +} + +// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH +// authorized_keys file. The return value ends with newline. +func MarshalAuthorizedKey(key PublicKey) []byte { + b := &bytes.Buffer{} + b.WriteString(key.Type()) + b.WriteByte(' ') + e := base64.NewEncoder(base64.StdEncoding, b) + e.Write(key.Marshal()) + e.Close() + b.WriteByte('\n') + return b.Bytes() +} + +// PublicKey is an abstraction of different types of public keys. +type PublicKey interface { + // Type returns the key's type, e.g. "ssh-rsa". + Type() string + + // Marshal returns the serialized key data in SSH wire format, + // with the name prefix. + Marshal() []byte + + // Verify that sig is a signature on the given data using this + // key. This function will hash the data appropriately first. + Verify(data []byte, sig *Signature) error +} + +// A Signer can create signatures that verify against a public key. +type Signer interface { + // PublicKey returns an associated PublicKey instance. + PublicKey() PublicKey + + // Sign returns raw signature for the given data. This method + // will apply the hash specified for the keytype to the data. + Sign(rand io.Reader, data []byte) (*Signature, error) +} + +type rsaPublicKey rsa.PublicKey + +func (r *rsaPublicKey) Type() string { + return "ssh-rsa" +} + +// parseRSA parses an RSA key according to RFC 4253, section 6.6. +func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + E *big.Int + N *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if w.E.BitLen() > 24 { + return nil, nil, errors.New("ssh: exponent too large") + } + e := w.E.Int64() + if e < 3 || e&1 == 0 { + return nil, nil, errors.New("ssh: incorrect exponent") + } + + var key rsa.PublicKey + key.E = int(e) + key.N = w.N + return (*rsaPublicKey)(&key), w.Rest, nil +} + +func (r *rsaPublicKey) Marshal() []byte { + e := new(big.Int).SetInt64(int64(r.E)) + wirekey := struct { + Name string + E *big.Int + N *big.Int + }{ + KeyAlgoRSA, + e, + r.N, + } + return Marshal(&wirekey) +} + +func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != r.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) + } + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob) +} + +type dsaPublicKey dsa.PublicKey + +func (r *dsaPublicKey) Type() string { + return "ssh-dss" +} + +// parseDSA parses an DSA key according to RFC 4253, section 6.6. +func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + P, Q, G, Y *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := &dsaPublicKey{ + Parameters: dsa.Parameters{ + P: w.P, + Q: w.Q, + G: w.G, + }, + Y: w.Y, + } + return key, w.Rest, nil +} + +func (k *dsaPublicKey) Marshal() []byte { + w := struct { + Name string + P, Q, G, Y *big.Int + }{ + k.Type(), + k.P, + k.Q, + k.G, + k.Y, + } + + return Marshal(&w) +} + +func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 4253, section 6.6, + // The value for 'dss_signature_blob' is encoded as a string containing + // r, followed by s (which are 160-bit integers, without lengths or + // padding, unsigned, and in network byte order). + // For DSS purposes, sig.Blob should be exactly 40 bytes in length. + if len(sig.Blob) != 40 { + return errors.New("ssh: DSA signature parse error") + } + r := new(big.Int).SetBytes(sig.Blob[:20]) + s := new(big.Int).SetBytes(sig.Blob[20:]) + if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +type dsaPrivateKey struct { + *dsa.PrivateKey +} + +func (k *dsaPrivateKey) PublicKey() PublicKey { + return (*dsaPublicKey)(&k.PrivateKey.PublicKey) +} + +func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + r, s, err := dsa.Sign(rand, k.PrivateKey, digest) + if err != nil { + return nil, err + } + + sig := make([]byte, 40) + rb := r.Bytes() + sb := s.Bytes() + + copy(sig[20-len(rb):20], rb) + copy(sig[40-len(sb):], sb) + + return &Signature{ + Format: k.PublicKey().Type(), + Blob: sig, + }, nil +} + +type ecdsaPublicKey ecdsa.PublicKey + +func (key *ecdsaPublicKey) Type() string { + return "ecdsa-sha2-" + key.nistID() +} + +func (key *ecdsaPublicKey) nistID() string { + switch key.Params().BitSize { + case 256: + return "nistp256" + case 384: + return "nistp384" + case 521: + return "nistp521" + } + panic("ssh: unsupported ecdsa key size") +} + +func supportedEllipticCurve(curve elliptic.Curve) bool { + return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() +} + +// ecHash returns the hash to match the given elliptic curve, see RFC +// 5656, section 6.2.1 +func ecHash(curve elliptic.Curve) crypto.Hash { + bitSize := curve.Params().BitSize + switch { + case bitSize <= 256: + return crypto.SHA256 + case bitSize <= 384: + return crypto.SHA384 + } + return crypto.SHA512 +} + +// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. +func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + Curve string + KeyBytes []byte + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := new(ecdsa.PublicKey) + + switch w.Curve { + case "nistp256": + key.Curve = elliptic.P256() + case "nistp384": + key.Curve = elliptic.P384() + case "nistp521": + key.Curve = elliptic.P521() + default: + return nil, nil, errors.New("ssh: unsupported curve") + } + + key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) + if key.X == nil || key.Y == nil { + return nil, nil, errors.New("ssh: invalid curve point") + } + return (*ecdsaPublicKey)(key), w.Rest, nil +} + +func (key *ecdsaPublicKey) Marshal() []byte { + // See RFC 5656, section 3.1. + keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) + w := struct { + Name string + ID string + Key []byte + }{ + key.Type(), + key.nistID(), + keyBytes, + } + + return Marshal(&w) +} + +func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != key.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) + } + + h := ecHash(key.Curve).New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 5656, section 3.1.2, + // The ecdsa_signature_blob value has the following specific encoding: + // mpint r + // mpint s + var ecSig struct { + R *big.Int + S *big.Int + } + + if err := Unmarshal(sig.Blob, &ecSig); err != nil { + return err + } + + if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, +// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding +// Signer instance. ECDSA keys must use P-256, P-384 or P-521. +func NewSignerFromKey(key interface{}) (Signer, error) { + switch key := key.(type) { + case crypto.Signer: + return NewSignerFromSigner(key) + case *dsa.PrivateKey: + return &dsaPrivateKey{key}, nil + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +type wrappedSigner struct { + signer crypto.Signer + pubKey PublicKey +} + +// NewSignerFromSigner takes any crypto.Signer implementation and +// returns a corresponding Signer interface. This can be used, for +// example, with keys kept in hardware modules. +func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { + pubKey, err := NewPublicKey(signer.Public()) + if err != nil { + return nil, err + } + + return &wrappedSigner{signer, pubKey}, nil +} + +func (s *wrappedSigner) PublicKey() PublicKey { + return s.pubKey +} + +func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + var hashFunc crypto.Hash + + switch key := s.pubKey.(type) { + case *rsaPublicKey, *dsaPublicKey: + hashFunc = crypto.SHA1 + case *ecdsaPublicKey: + hashFunc = ecHash(key.Curve) + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } + + h := hashFunc.New() + h.Write(data) + digest := h.Sum(nil) + + signature, err := s.signer.Sign(rand, digest, hashFunc) + if err != nil { + return nil, err + } + + // crypto.Signer.Sign is expected to return an ASN.1-encoded signature + // for ECDSA and DSA, but that's not the encoding expected by SSH, so + // re-encode. + switch s.pubKey.(type) { + case *ecdsaPublicKey, *dsaPublicKey: + type asn1Signature struct { + R, S *big.Int + } + asn1Sig := new(asn1Signature) + _, err := asn1.Unmarshal(signature, asn1Sig) + if err != nil { + return nil, err + } + + switch s.pubKey.(type) { + case *ecdsaPublicKey: + signature = Marshal(asn1Sig) + + case *dsaPublicKey: + signature = make([]byte, 40) + r := asn1Sig.R.Bytes() + s := asn1Sig.S.Bytes() + copy(signature[20-len(r):20], r) + copy(signature[40-len(s):40], s) + } + } + + return &Signature{ + Format: s.pubKey.Type(), + Blob: signature, + }, nil +} + +// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or +// any other crypto.Signer and returns a corresponding Signer instance. ECDSA +// keys must use P-256, P-384 or P-521. +func NewPublicKey(key interface{}) (PublicKey, error) { + switch key := key.(type) { + case *rsa.PublicKey: + return (*rsaPublicKey)(key), nil + case *ecdsa.PublicKey: + if !supportedEllipticCurve(key.Curve) { + return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.") + } + return (*ecdsaPublicKey)(key), nil + case *dsa.PublicKey: + return (*dsaPublicKey)(key), nil + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports +// the same keys as ParseRawPrivateKey. +func ParsePrivateKey(pemBytes []byte) (Signer, error) { + key, err := ParseRawPrivateKey(pemBytes) + if err != nil { + return nil, err + } + + return NewSignerFromKey(key) +} + +// ParseRawPrivateKey returns a private key from a PEM encoded private key. It +// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. +func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { + block, _ := pem.Decode(pemBytes) + if block == nil { + return nil, errors.New("ssh: no key found") + } + + switch block.Type { + case "RSA PRIVATE KEY": + return x509.ParsePKCS1PrivateKey(block.Bytes) + case "EC PRIVATE KEY": + return x509.ParseECPrivateKey(block.Bytes) + case "DSA PRIVATE KEY": + return ParseDSAPrivateKey(block.Bytes) + default: + return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + } +} + +// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as +// specified by the OpenSSL DSA man page. +func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { + var k struct { + Version int + P *big.Int + Q *big.Int + G *big.Int + Priv *big.Int + Pub *big.Int + } + rest, err := asn1.Unmarshal(der, &k) + if err != nil { + return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) + } + if len(rest) > 0 { + return nil, errors.New("ssh: garbage after DSA key") + } + + return &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + }, + Y: k.Priv, + }, + X: k.Pub, + }, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go new file mode 100644 index 000000000..07744ad67 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mac.go @@ -0,0 +1,57 @@ +// Copyright 2012 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. + +package ssh + +// Message authentication support + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "hash" +) + +type macMode struct { + keySize int + new func(key []byte) hash.Hash +} + +// truncatingMAC wraps around a hash.Hash and truncates the output digest to +// a given size. +type truncatingMAC struct { + length int + hmac hash.Hash +} + +func (t truncatingMAC) Write(data []byte) (int, error) { + return t.hmac.Write(data) +} + +func (t truncatingMAC) Sum(in []byte) []byte { + out := t.hmac.Sum(in) + return out[:len(in)+t.length] +} + +func (t truncatingMAC) Reset() { + t.hmac.Reset() +} + +func (t truncatingMAC) Size() int { + return t.length +} + +func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } + +var macModes = map[string]*macMode{ + "hmac-sha2-256": {32, func(key []byte) hash.Hash { + return hmac.New(sha256.New, key) + }}, + "hmac-sha1": {20, func(key []byte) hash.Hash { + return hmac.New(sha1.New, key) + }}, + "hmac-sha1-96": {20, func(key []byte) hash.Hash { + return truncatingMAC{12, hmac.New(sha1.New, key)} + }}, +} diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go new file mode 100644 index 000000000..eaf610669 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -0,0 +1,725 @@ +// Copyright 2011 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. + +package ssh + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "reflect" + "strconv" +) + +// These are SSH message type numbers. They are scattered around several +// documents but many were taken from [SSH-PARAMETERS]. +const ( + msgIgnore = 2 + msgUnimplemented = 3 + msgDebug = 4 + msgNewKeys = 21 + + // Standard authentication messages + msgUserAuthSuccess = 52 + msgUserAuthBanner = 53 +) + +// SSH messages: +// +// These structures mirror the wire format of the corresponding SSH messages. +// They are marshaled using reflection with the marshal and unmarshal functions +// in this file. The only wrinkle is that a final member of type []byte with a +// ssh tag of "rest" receives the remainder of a packet when unmarshaling. + +// See RFC 4253, section 11.1. +const msgDisconnect = 1 + +// disconnectMsg is the message that signals a disconnect. It is also +// the error type returned from mux.Wait() +type disconnectMsg struct { + Reason uint32 `sshtype:"1"` + Message string + Language string +} + +func (d *disconnectMsg) Error() string { + return fmt.Sprintf("ssh: disconnect reason %d: %s", d.Reason, d.Message) +} + +// See RFC 4253, section 7.1. +const msgKexInit = 20 + +type kexInitMsg struct { + Cookie [16]byte `sshtype:"20"` + KexAlgos []string + ServerHostKeyAlgos []string + CiphersClientServer []string + CiphersServerClient []string + MACsClientServer []string + MACsServerClient []string + CompressionClientServer []string + CompressionServerClient []string + LanguagesClientServer []string + LanguagesServerClient []string + FirstKexFollows bool + Reserved uint32 +} + +// See RFC 4253, section 8. + +// Diffie-Helman +const msgKexDHInit = 30 + +type kexDHInitMsg struct { + X *big.Int `sshtype:"30"` +} + +const msgKexECDHInit = 30 + +type kexECDHInitMsg struct { + ClientPubKey []byte `sshtype:"30"` +} + +const msgKexECDHReply = 31 + +type kexECDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + EphemeralPubKey []byte + Signature []byte +} + +const msgKexDHReply = 31 + +type kexDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + Y *big.Int + Signature []byte +} + +// See RFC 4253, section 10. +const msgServiceRequest = 5 + +type serviceRequestMsg struct { + Service string `sshtype:"5"` +} + +// See RFC 4253, section 10. +const msgServiceAccept = 6 + +type serviceAcceptMsg struct { + Service string `sshtype:"6"` +} + +// See RFC 4252, section 5. +const msgUserAuthRequest = 50 + +type userAuthRequestMsg struct { + User string `sshtype:"50"` + Service string + Method string + Payload []byte `ssh:"rest"` +} + +// See RFC 4252, section 5.1 +const msgUserAuthFailure = 51 + +type userAuthFailureMsg struct { + Methods []string `sshtype:"51"` + PartialSuccess bool +} + +// See RFC 4256, section 3.2 +const msgUserAuthInfoRequest = 60 +const msgUserAuthInfoResponse = 61 + +type userAuthInfoRequestMsg struct { + User string `sshtype:"60"` + Instruction string + DeprecatedLanguage string + NumPrompts uint32 + Prompts []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpen = 90 + +type channelOpenMsg struct { + ChanType string `sshtype:"90"` + PeersId uint32 + PeersWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +const msgChannelExtendedData = 95 +const msgChannelData = 94 + +// See RFC 4254, section 5.1. +const msgChannelOpenConfirm = 91 + +type channelOpenConfirmMsg struct { + PeersId uint32 `sshtype:"91"` + MyId uint32 + MyWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpenFailure = 92 + +type channelOpenFailureMsg struct { + PeersId uint32 `sshtype:"92"` + Reason RejectionReason + Message string + Language string +} + +const msgChannelRequest = 98 + +type channelRequestMsg struct { + PeersId uint32 `sshtype:"98"` + Request string + WantReply bool + RequestSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.4. +const msgChannelSuccess = 99 + +type channelRequestSuccessMsg struct { + PeersId uint32 `sshtype:"99"` +} + +// See RFC 4254, section 5.4. +const msgChannelFailure = 100 + +type channelRequestFailureMsg struct { + PeersId uint32 `sshtype:"100"` +} + +// See RFC 4254, section 5.3 +const msgChannelClose = 97 + +type channelCloseMsg struct { + PeersId uint32 `sshtype:"97"` +} + +// See RFC 4254, section 5.3 +const msgChannelEOF = 96 + +type channelEOFMsg struct { + PeersId uint32 `sshtype:"96"` +} + +// See RFC 4254, section 4 +const msgGlobalRequest = 80 + +type globalRequestMsg struct { + Type string `sshtype:"80"` + WantReply bool + Data []byte `ssh:"rest"` +} + +// See RFC 4254, section 4 +const msgRequestSuccess = 81 + +type globalRequestSuccessMsg struct { + Data []byte `ssh:"rest" sshtype:"81"` +} + +// See RFC 4254, section 4 +const msgRequestFailure = 82 + +type globalRequestFailureMsg struct { + Data []byte `ssh:"rest" sshtype:"82"` +} + +// See RFC 4254, section 5.2 +const msgChannelWindowAdjust = 93 + +type windowAdjustMsg struct { + PeersId uint32 `sshtype:"93"` + AdditionalBytes uint32 +} + +// See RFC 4252, section 7 +const msgUserAuthPubKeyOk = 60 + +type userAuthPubKeyOkMsg struct { + Algo string `sshtype:"60"` + PubKey []byte +} + +// typeTag returns the type byte for the given type. The type should +// be struct. +func typeTag(structType reflect.Type) byte { + var tag byte + var tagStr string + tagStr = structType.Field(0).Tag.Get("sshtype") + i, err := strconv.Atoi(tagStr) + if err == nil { + tag = byte(i) + } + return tag +} + +func fieldError(t reflect.Type, field int, problem string) error { + if problem != "" { + problem = ": " + problem + } + return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) +} + +var errShortRead = errors.New("ssh: short read") + +// Unmarshal parses data in SSH wire format into a structure. The out +// argument should be a pointer to struct. If the first member of the +// struct has the "sshtype" tag set to a number in decimal, the packet +// must start that number. In case of error, Unmarshal returns a +// ParseError or UnexpectedMessageError. +func Unmarshal(data []byte, out interface{}) error { + v := reflect.ValueOf(out).Elem() + structType := v.Type() + expectedType := typeTag(structType) + if len(data) == 0 { + return parseError(expectedType) + } + if expectedType > 0 { + if data[0] != expectedType { + return unexpectedMessageError(expectedType, data[0]) + } + data = data[1:] + } + + var ok bool + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + t := field.Type() + switch t.Kind() { + case reflect.Bool: + if len(data) < 1 { + return errShortRead + } + field.SetBool(data[0] != 0) + data = data[1:] + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + return fieldError(structType, i, "array of unsupported type") + } + if len(data) < t.Len() { + return errShortRead + } + for j, n := 0, t.Len(); j < n; j++ { + field.Index(j).Set(reflect.ValueOf(data[j])) + } + data = data[t.Len():] + case reflect.Uint64: + var u64 uint64 + if u64, data, ok = parseUint64(data); !ok { + return errShortRead + } + field.SetUint(u64) + case reflect.Uint32: + var u32 uint32 + if u32, data, ok = parseUint32(data); !ok { + return errShortRead + } + field.SetUint(uint64(u32)) + case reflect.Uint8: + if len(data) < 1 { + return errShortRead + } + field.SetUint(uint64(data[0])) + data = data[1:] + case reflect.String: + var s []byte + if s, data, ok = parseString(data); !ok { + return fieldError(structType, i, "") + } + field.SetString(string(s)) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if structType.Field(i).Tag.Get("ssh") == "rest" { + field.Set(reflect.ValueOf(data)) + data = nil + } else { + var s []byte + if s, data, ok = parseString(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(s)) + } + case reflect.String: + var nl []string + if nl, data, ok = parseNameList(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(nl)) + default: + return fieldError(structType, i, "slice of unsupported type") + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + if n, data, ok = parseInt(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(n)) + } else { + return fieldError(structType, i, "pointer to unsupported type") + } + default: + return fieldError(structType, i, "unsupported type") + } + } + + if len(data) != 0 { + return parseError(expectedType) + } + + return nil +} + +// Marshal serializes the message in msg to SSH wire format. The msg +// argument should be a struct or pointer to struct. If the first +// member has the "sshtype" tag set to a number in decimal, that +// number is prepended to the result. If the last of member has the +// "ssh" tag set to "rest", its contents are appended to the output. +func Marshal(msg interface{}) []byte { + out := make([]byte, 0, 64) + return marshalStruct(out, msg) +} + +func marshalStruct(out []byte, msg interface{}) []byte { + v := reflect.Indirect(reflect.ValueOf(msg)) + msgType := typeTag(v.Type()) + if msgType > 0 { + out = append(out, msgType) + } + + for i, n := 0, v.NumField(); i < n; i++ { + field := v.Field(i) + switch t := field.Type(); t.Kind() { + case reflect.Bool: + var v uint8 + if field.Bool() { + v = 1 + } + out = append(out, v) + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) + } + for j, l := 0, t.Len(); j < l; j++ { + out = append(out, uint8(field.Index(j).Uint())) + } + case reflect.Uint32: + out = appendU32(out, uint32(field.Uint())) + case reflect.Uint64: + out = appendU64(out, uint64(field.Uint())) + case reflect.Uint8: + out = append(out, uint8(field.Uint())) + case reflect.String: + s := field.String() + out = appendInt(out, len(s)) + out = append(out, s...) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if v.Type().Field(i).Tag.Get("ssh") != "rest" { + out = appendInt(out, field.Len()) + } + out = append(out, field.Bytes()...) + case reflect.String: + offset := len(out) + out = appendU32(out, 0) + if n := field.Len(); n > 0 { + for j := 0; j < n; j++ { + f := field.Index(j) + if j != 0 { + out = append(out, ',') + } + out = append(out, f.String()...) + } + // overwrite length value + binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) + } + default: + panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + nValue := reflect.ValueOf(&n) + nValue.Elem().Set(field) + needed := intLength(n) + oldLength := len(out) + + if cap(out)-len(out) < needed { + newOut := make([]byte, len(out), 2*(len(out)+needed)) + copy(newOut, out) + out = newOut + } + out = out[:oldLength+needed] + marshalInt(out[oldLength:], n) + } else { + panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) + } + } + } + + return out +} + +var bigOne = big.NewInt(1) + +func parseString(in []byte) (out, rest []byte, ok bool) { + if len(in) < 4 { + return + } + length := binary.BigEndian.Uint32(in) + in = in[4:] + if uint32(len(in)) < length { + return + } + out = in[:length] + rest = in[length:] + ok = true + return +} + +var ( + comma = []byte{','} + emptyNameList = []string{} +) + +func parseNameList(in []byte) (out []string, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + if len(contents) == 0 { + out = emptyNameList + return + } + parts := bytes.Split(contents, comma) + out = make([]string, len(parts)) + for i, part := range parts { + out[i] = string(part) + } + return +} + +func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + out = new(big.Int) + + if len(contents) > 0 && contents[0]&0x80 == 0x80 { + // This is a negative number + notBytes := make([]byte, len(contents)) + for i := range notBytes { + notBytes[i] = ^contents[i] + } + out.SetBytes(notBytes) + out.Add(out, bigOne) + out.Neg(out) + } else { + // Positive number + out.SetBytes(contents) + } + ok = true + return +} + +func parseUint32(in []byte) (uint32, []byte, bool) { + if len(in) < 4 { + return 0, nil, false + } + return binary.BigEndian.Uint32(in), in[4:], true +} + +func parseUint64(in []byte) (uint64, []byte, bool) { + if len(in) < 8 { + return 0, nil, false + } + return binary.BigEndian.Uint64(in), in[8:], true +} + +func intLength(n *big.Int) int { + length := 4 /* length bytes */ + if n.Sign() < 0 { + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bitLen := nMinus1.BitLen() + if bitLen%8 == 0 { + // The number will need 0xff padding + length++ + } + length += (bitLen + 7) / 8 + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bitLen := n.BitLen() + if bitLen%8 == 0 { + // The number will need 0x00 padding + length++ + } + length += (bitLen + 7) / 8 + } + + return length +} + +func marshalUint32(to []byte, n uint32) []byte { + binary.BigEndian.PutUint32(to, n) + return to[4:] +} + +func marshalUint64(to []byte, n uint64) []byte { + binary.BigEndian.PutUint64(to, n) + return to[8:] +} + +func marshalInt(to []byte, n *big.Int) []byte { + lengthBytes := to + to = to[4:] + length := 0 + + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll subtract 1 and invert. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + to[0] = 0xff + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with a 0x00 in order to + // stop it looking like a negative number. + to[0] = 0 + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } + + lengthBytes[0] = byte(length >> 24) + lengthBytes[1] = byte(length >> 16) + lengthBytes[2] = byte(length >> 8) + lengthBytes[3] = byte(length) + return to +} + +func writeInt(w io.Writer, n *big.Int) { + length := intLength(n) + buf := make([]byte, length) + marshalInt(buf, n) + w.Write(buf) +} + +func writeString(w io.Writer, s []byte) { + var lengthBytes [4]byte + lengthBytes[0] = byte(len(s) >> 24) + lengthBytes[1] = byte(len(s) >> 16) + lengthBytes[2] = byte(len(s) >> 8) + lengthBytes[3] = byte(len(s)) + w.Write(lengthBytes[:]) + w.Write(s) +} + +func stringLength(n int) int { + return 4 + n +} + +func marshalString(to []byte, s []byte) []byte { + to[0] = byte(len(s) >> 24) + to[1] = byte(len(s) >> 16) + to[2] = byte(len(s) >> 8) + to[3] = byte(len(s)) + to = to[4:] + copy(to, s) + return to[len(s):] +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)) + +// Decode a packet into its corresponding message. +func decode(packet []byte) (interface{}, error) { + var msg interface{} + switch packet[0] { + case msgDisconnect: + msg = new(disconnectMsg) + case msgServiceRequest: + msg = new(serviceRequestMsg) + case msgServiceAccept: + msg = new(serviceAcceptMsg) + case msgKexInit: + msg = new(kexInitMsg) + case msgKexDHInit: + msg = new(kexDHInitMsg) + case msgKexDHReply: + msg = new(kexDHReplyMsg) + case msgUserAuthRequest: + msg = new(userAuthRequestMsg) + case msgUserAuthFailure: + msg = new(userAuthFailureMsg) + case msgUserAuthPubKeyOk: + msg = new(userAuthPubKeyOkMsg) + case msgGlobalRequest: + msg = new(globalRequestMsg) + case msgRequestSuccess: + msg = new(globalRequestSuccessMsg) + case msgRequestFailure: + msg = new(globalRequestFailureMsg) + case msgChannelOpen: + msg = new(channelOpenMsg) + case msgChannelOpenConfirm: + msg = new(channelOpenConfirmMsg) + case msgChannelOpenFailure: + msg = new(channelOpenFailureMsg) + case msgChannelWindowAdjust: + msg = new(windowAdjustMsg) + case msgChannelEOF: + msg = new(channelEOFMsg) + case msgChannelClose: + msg = new(channelCloseMsg) + case msgChannelRequest: + msg = new(channelRequestMsg) + case msgChannelSuccess: + msg = new(channelRequestSuccessMsg) + case msgChannelFailure: + msg = new(channelRequestFailureMsg) + default: + return nil, unexpectedMessageError(0, packet[0]) + } + if err := Unmarshal(packet, msg); err != nil { + return nil, err + } + return msg, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go new file mode 100644 index 000000000..321880ad9 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -0,0 +1,356 @@ +// Copyright 2013 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. + +package ssh + +import ( + "encoding/binary" + "fmt" + "io" + "log" + "sync" + "sync/atomic" +) + +// debugMux, if set, causes messages in the connection protocol to be +// logged. +const debugMux = false + +// chanList is a thread safe channel list. +type chanList struct { + // protects concurrent access to chans + sync.Mutex + + // chans are indexed by the local id of the channel, which the + // other side should send in the PeersId field. + chans []*channel + + // This is a debugging aid: it offsets all IDs by this + // amount. This helps distinguish otherwise identical + // server/client muxes + offset uint32 +} + +// Assigns a channel ID to the given channel. +func (c *chanList) add(ch *channel) uint32 { + c.Lock() + defer c.Unlock() + for i := range c.chans { + if c.chans[i] == nil { + c.chans[i] = ch + return uint32(i) + c.offset + } + } + c.chans = append(c.chans, ch) + return uint32(len(c.chans)-1) + c.offset +} + +// getChan returns the channel for the given ID. +func (c *chanList) getChan(id uint32) *channel { + id -= c.offset + + c.Lock() + defer c.Unlock() + if id < uint32(len(c.chans)) { + return c.chans[id] + } + return nil +} + +func (c *chanList) remove(id uint32) { + id -= c.offset + c.Lock() + if id < uint32(len(c.chans)) { + c.chans[id] = nil + } + c.Unlock() +} + +// dropAll forgets all channels it knows, returning them in a slice. +func (c *chanList) dropAll() []*channel { + c.Lock() + defer c.Unlock() + var r []*channel + + for _, ch := range c.chans { + if ch == nil { + continue + } + r = append(r, ch) + } + c.chans = nil + return r +} + +// mux represents the state for the SSH connection protocol, which +// multiplexes many channels onto a single packet transport. +type mux struct { + conn packetConn + chanList chanList + + incomingChannels chan NewChannel + + globalSentMu sync.Mutex + globalResponses chan interface{} + incomingRequests chan *Request + + errCond *sync.Cond + err error +} + +// When debugging, each new chanList instantiation has a different +// offset. +var globalOff uint32 + +func (m *mux) Wait() error { + m.errCond.L.Lock() + defer m.errCond.L.Unlock() + for m.err == nil { + m.errCond.Wait() + } + return m.err +} + +// newMux returns a mux that runs over the given connection. +func newMux(p packetConn) *mux { + m := &mux{ + conn: p, + incomingChannels: make(chan NewChannel, 16), + globalResponses: make(chan interface{}, 1), + incomingRequests: make(chan *Request, 16), + errCond: newCond(), + } + if debugMux { + m.chanList.offset = atomic.AddUint32(&globalOff, 1) + } + + go m.loop() + return m +} + +func (m *mux) sendMessage(msg interface{}) error { + p := Marshal(msg) + return m.conn.writePacket(p) +} + +func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { + if wantReply { + m.globalSentMu.Lock() + defer m.globalSentMu.Unlock() + } + + if err := m.sendMessage(globalRequestMsg{ + Type: name, + WantReply: wantReply, + Data: payload, + }); err != nil { + return false, nil, err + } + + if !wantReply { + return false, nil, nil + } + + msg, ok := <-m.globalResponses + if !ok { + return false, nil, io.EOF + } + switch msg := msg.(type) { + case *globalRequestFailureMsg: + return false, msg.Data, nil + case *globalRequestSuccessMsg: + return true, msg.Data, nil + default: + return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) + } +} + +// ackRequest must be called after processing a global request that +// has WantReply set. +func (m *mux) ackRequest(ok bool, data []byte) error { + if ok { + return m.sendMessage(globalRequestSuccessMsg{Data: data}) + } + return m.sendMessage(globalRequestFailureMsg{Data: data}) +} + +// TODO(hanwen): Disconnect is a transport layer message. We should +// probably send and receive Disconnect somewhere in the transport +// code. + +// Disconnect sends a disconnect message. +func (m *mux) Disconnect(reason uint32, message string) error { + return m.sendMessage(disconnectMsg{ + Reason: reason, + Message: message, + }) +} + +func (m *mux) Close() error { + return m.conn.Close() +} + +// loop runs the connection machine. It will process packets until an +// error is encountered. To synchronize on loop exit, use mux.Wait. +func (m *mux) loop() { + var err error + for err == nil { + err = m.onePacket() + } + + for _, ch := range m.chanList.dropAll() { + ch.close() + } + + close(m.incomingChannels) + close(m.incomingRequests) + close(m.globalResponses) + + m.conn.Close() + + m.errCond.L.Lock() + m.err = err + m.errCond.Broadcast() + m.errCond.L.Unlock() + + if debugMux { + log.Println("loop exit", err) + } +} + +// onePacket reads and processes one packet. +func (m *mux) onePacket() error { + packet, err := m.conn.readPacket() + if err != nil { + return err + } + + if debugMux { + if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { + log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) + } else { + p, _ := decode(packet) + log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) + } + } + + switch packet[0] { + case msgNewKeys: + // Ignore notification of key change. + return nil + case msgDisconnect: + return m.handleDisconnect(packet) + case msgChannelOpen: + return m.handleChannelOpen(packet) + case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: + return m.handleGlobalPacket(packet) + } + + // assume a channel packet. + if len(packet) < 5 { + return parseError(packet[0]) + } + id := binary.BigEndian.Uint32(packet[1:]) + ch := m.chanList.getChan(id) + if ch == nil { + return fmt.Errorf("ssh: invalid channel %d", id) + } + + return ch.handlePacket(packet) +} + +func (m *mux) handleDisconnect(packet []byte) error { + var d disconnectMsg + if err := Unmarshal(packet, &d); err != nil { + return err + } + + if debugMux { + log.Printf("caught disconnect: %v", d) + } + return &d +} + +func (m *mux) handleGlobalPacket(packet []byte) error { + msg, err := decode(packet) + if err != nil { + return err + } + + switch msg := msg.(type) { + case *globalRequestMsg: + m.incomingRequests <- &Request{ + Type: msg.Type, + WantReply: msg.WantReply, + Payload: msg.Data, + mux: m, + } + case *globalRequestSuccessMsg, *globalRequestFailureMsg: + m.globalResponses <- msg + default: + panic(fmt.Sprintf("not a global message %#v", msg)) + } + + return nil +} + +// handleChannelOpen schedules a channel to be Accept()ed. +func (m *mux) handleChannelOpen(packet []byte) error { + var msg channelOpenMsg + if err := Unmarshal(packet, &msg); err != nil { + return err + } + + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + failMsg := channelOpenFailureMsg{ + PeersId: msg.PeersId, + Reason: ConnectionFailed, + Message: "invalid request", + Language: "en_US.UTF-8", + } + return m.sendMessage(failMsg) + } + + c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) + c.remoteId = msg.PeersId + c.maxRemotePayload = msg.MaxPacketSize + c.remoteWin.add(msg.PeersWindow) + m.incomingChannels <- c + return nil +} + +func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { + ch, err := m.openChannel(chanType, extra) + if err != nil { + return nil, nil, err + } + + return ch, ch.incomingRequests, nil +} + +func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { + ch := m.newChannel(chanType, channelOutbound, extra) + + ch.maxIncomingPayload = channelMaxPacket + + open := channelOpenMsg{ + ChanType: chanType, + PeersWindow: ch.myWindow, + MaxPacketSize: ch.maxIncomingPayload, + TypeSpecificData: extra, + PeersId: ch.localId, + } + if err := m.sendMessage(open); err != nil { + return nil, err + } + + switch msg := (<-ch.msg).(type) { + case *channelOpenConfirmMsg: + return ch, nil + case *channelOpenFailureMsg: + return nil, &OpenChannelError{msg.Reason, msg.Message} + default: + return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go new file mode 100644 index 000000000..4781eb780 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -0,0 +1,495 @@ +// Copyright 2011 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. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" +) + +// The Permissions type holds fine-grained permissions that are +// specific to a user or a specific authentication method for a +// user. Permissions, except for "source-address", must be enforced in +// the server application layer, after successful authentication. The +// Permissions are passed on in ServerConn so a server implementation +// can honor them. +type Permissions struct { + // Critical options restrict default permissions. Common + // restrictions are "source-address" and "force-command". If + // the server cannot enforce the restriction, or does not + // recognize it, the user should not authenticate. + CriticalOptions map[string]string + + // Extensions are extra functionality that the server may + // offer on authenticated connections. Common extensions are + // "permit-agent-forwarding", "permit-X11-forwarding". Lack of + // support for an extension does not preclude authenticating a + // user. + Extensions map[string]string +} + +// ServerConfig holds server specific configuration data. +type ServerConfig struct { + // Config contains configuration shared between client and server. + Config + + hostKeys []Signer + + // NoClientAuth is true if clients are allowed to connect without + // authenticating. + NoClientAuth bool + + // PasswordCallback, if non-nil, is called when a user + // attempts to authenticate using a password. + PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) + + // PublicKeyCallback, if non-nil, is called when a client attempts public + // key authentication. It must return true if the given public key is + // valid for the given user. For example, see CertChecker.Authenticate. + PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // KeyboardInteractiveCallback, if non-nil, is called when + // keyboard-interactive authentication is selected (RFC + // 4256). The client object's Challenge function should be + // used to query the user. The callback may offer multiple + // Challenge rounds. To avoid information leaks, the client + // should be presented a challenge even if the user is + // unknown. + KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) + + // AuthLogCallback, if non-nil, is called to log all authentication + // attempts. + AuthLogCallback func(conn ConnMetadata, method string, err error) + + // ServerVersion is the version identification string to announce in + // the public handshake. + // If empty, a reasonable default is used. + // Note that RFC 4253 section 4.2 requires that this string start with + // "SSH-2.0-". + ServerVersion string +} + +// AddHostKey adds a private key as a host key. If an existing host +// key exists with the same algorithm, it is overwritten. Each server +// config must have at least one host key. +func (s *ServerConfig) AddHostKey(key Signer) { + for i, k := range s.hostKeys { + if k.PublicKey().Type() == key.PublicKey().Type() { + s.hostKeys[i] = key + return + } + } + + s.hostKeys = append(s.hostKeys, key) +} + +// cachedPubKey contains the results of querying whether a public key is +// acceptable for a user. +type cachedPubKey struct { + user string + pubKeyData []byte + result error + perms *Permissions +} + +const maxCachedPubKeys = 16 + +// pubKeyCache caches tests for public keys. Since SSH clients +// will query whether a public key is acceptable before attempting to +// authenticate with it, we end up with duplicate queries for public +// key validity. The cache only applies to a single ServerConn. +type pubKeyCache struct { + keys []cachedPubKey +} + +// get returns the result for a given user/algo/key tuple. +func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { + for _, k := range c.keys { + if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { + return k, true + } + } + return cachedPubKey{}, false +} + +// add adds the given tuple to the cache. +func (c *pubKeyCache) add(candidate cachedPubKey) { + if len(c.keys) < maxCachedPubKeys { + c.keys = append(c.keys, candidate) + } +} + +// ServerConn is an authenticated SSH connection, as seen from the +// server +type ServerConn struct { + Conn + + // If the succeeding authentication callback returned a + // non-nil Permissions pointer, it is stored here. + Permissions *Permissions +} + +// NewServerConn starts a new SSH server with c as the underlying +// transport. It starts with a handshake and, if the handshake is +// unsuccessful, it closes the connection and returns an error. The +// Request and NewChannel channels must be serviced, or the connection +// will hang. +func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + s := &connection{ + sshConn: sshConn{conn: c}, + } + perms, err := s.serverHandshake(&fullConf) + if err != nil { + c.Close() + return nil, nil, nil, err + } + return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil +} + +// signAndMarshal signs the data with the appropriate algorithm, +// and serializes the result in SSH wire format. +func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { + sig, err := k.Sign(rand, data) + if err != nil { + return nil, err + } + + return Marshal(sig), nil +} + +// handshake performs key exchange and user authentication. +func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { + if len(config.hostKeys) == 0 { + return nil, errors.New("ssh: server has no host keys") + } + + if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if config.ServerVersion != "" { + s.serverVersion = []byte(config.ServerVersion) + } else { + s.serverVersion = []byte(packageVersion) + } + var err error + s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) + if err != nil { + return nil, err + } + + tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) + s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) + + if err := s.transport.requestKeyChange(); err != nil { + return nil, err + } + + if packet, err := s.transport.readPacket(); err != nil { + return nil, err + } else if packet[0] != msgNewKeys { + return nil, unexpectedMessageError(msgNewKeys, packet[0]) + } + + // We just did the key change, so the session ID is established. + s.sessionID = s.transport.getSessionID() + + var packet []byte + if packet, err = s.transport.readPacket(); err != nil { + return nil, err + } + + var serviceRequest serviceRequestMsg + if err = Unmarshal(packet, &serviceRequest); err != nil { + return nil, err + } + if serviceRequest.Service != serviceUserAuth { + return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") + } + serviceAccept := serviceAcceptMsg{ + Service: serviceUserAuth, + } + if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { + return nil, err + } + + perms, err := s.serverAuthenticate(config) + if err != nil { + return nil, err + } + s.mux = newMux(s.transport) + return perms, err +} + +func isAcceptableAlgo(algo string) bool { + switch algo { + case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01: + return true + } + return false +} + +func checkSourceAddress(addr net.Addr, sourceAddr string) error { + if addr == nil { + return errors.New("ssh: no address known for client, but source-address match required") + } + + tcpAddr, ok := addr.(*net.TCPAddr) + if !ok { + return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) + } + + if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { + if bytes.Equal(allowedIP, tcpAddr.IP) { + return nil + } + } else { + _, ipNet, err := net.ParseCIDR(sourceAddr) + if err != nil { + return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) + } + + if ipNet.Contains(tcpAddr.IP) { + return nil + } + } + + return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) +} + +func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { + var err error + var cache pubKeyCache + var perms *Permissions + +userAuthLoop: + for { + var userAuthReq userAuthRequestMsg + if packet, err := s.transport.readPacket(); err != nil { + return nil, err + } else if err = Unmarshal(packet, &userAuthReq); err != nil { + return nil, err + } + + if userAuthReq.Service != serviceSSH { + return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) + } + + s.user = userAuthReq.User + perms = nil + authErr := errors.New("no auth passed yet") + + switch userAuthReq.Method { + case "none": + if config.NoClientAuth { + s.user = "" + authErr = nil + } + case "password": + if config.PasswordCallback == nil { + authErr = errors.New("ssh: password auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 || payload[0] != 0 { + return nil, parseError(msgUserAuthRequest) + } + payload = payload[1:] + password, payload, ok := parseString(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + perms, authErr = config.PasswordCallback(s, password) + case "keyboard-interactive": + if config.KeyboardInteractiveCallback == nil { + authErr = errors.New("ssh: keyboard-interactive auth not configubred") + break + } + + prompter := &sshClientKeyboardInteractive{s} + perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) + case "publickey": + if config.PublicKeyCallback == nil { + authErr = errors.New("ssh: publickey auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 { + return nil, parseError(msgUserAuthRequest) + } + isQuery := payload[0] == 0 + payload = payload[1:] + algoBytes, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + algo := string(algoBytes) + if !isAcceptableAlgo(algo) { + authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) + break + } + + pubKeyData, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + + pubKey, err := ParsePublicKey(pubKeyData) + if err != nil { + return nil, err + } + + candidate, ok := cache.get(s.user, pubKeyData) + if !ok { + candidate.user = s.user + candidate.pubKeyData = pubKeyData + candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) + if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { + candidate.result = checkSourceAddress( + s.RemoteAddr(), + candidate.perms.CriticalOptions[sourceAddressCriticalOption]) + } + cache.add(candidate) + } + + if isQuery { + // The client can query if the given public key + // would be okay. + if len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + if candidate.result == nil { + okMsg := userAuthPubKeyOkMsg{ + Algo: algo, + PubKey: pubKeyData, + } + if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { + return nil, err + } + continue userAuthLoop + } + authErr = candidate.result + } else { + sig, payload, ok := parseSignature(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + // Ensure the public key algo and signature algo + // are supported. Compare the private key + // algorithm name that corresponds to algo with + // sig.Format. This is usually the same, but + // for certs, the names differ. + if !isAcceptableAlgo(sig.Format) { + break + } + signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData) + + if err := pubKey.Verify(signedData, sig); err != nil { + return nil, err + } + + authErr = candidate.result + perms = candidate.perms + } + default: + authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) + } + + if config.AuthLogCallback != nil { + config.AuthLogCallback(s, userAuthReq.Method, authErr) + } + + if authErr == nil { + break userAuthLoop + } + + var failureMsg userAuthFailureMsg + if config.PasswordCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "password") + } + if config.PublicKeyCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "publickey") + } + if config.KeyboardInteractiveCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") + } + + if len(failureMsg.Methods) == 0 { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if err = s.transport.writePacket(Marshal(&failureMsg)); err != nil { + return nil, err + } + } + + if err = s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { + return nil, err + } + return perms, nil +} + +// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by +// asking the client on the other side of a ServerConn. +type sshClientKeyboardInteractive struct { + *connection +} + +func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) { + if len(questions) != len(echos) { + return nil, errors.New("ssh: echos and questions must have equal length") + } + + var prompts []byte + for i := range questions { + prompts = appendString(prompts, questions[i]) + prompts = appendBool(prompts, echos[i]) + } + + if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ + Instruction: instruction, + NumPrompts: uint32(len(questions)), + Prompts: prompts, + })); err != nil { + return nil, err + } + + packet, err := c.transport.readPacket() + if err != nil { + return nil, err + } + if packet[0] != msgUserAuthInfoResponse { + return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) + } + packet = packet[1:] + + n, packet, ok := parseUint32(packet) + if !ok || int(n) != len(questions) { + return nil, parseError(msgUserAuthInfoResponse) + } + + for i := uint32(0); i < n; i++ { + ans, rest, ok := parseString(packet) + if !ok { + return nil, parseError(msgUserAuthInfoResponse) + } + + answers = append(answers, string(ans)) + packet = rest + } + if len(packet) != 0 { + return nil, errors.New("ssh: junk at end of message") + } + + return answers, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go new file mode 100644 index 000000000..fd10cd1aa --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/session.go @@ -0,0 +1,605 @@ +// Copyright 2011 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. + +package ssh + +// Session implements an interactive session described in +// "RFC 4254, section 6". + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "sync" +) + +type Signal string + +// POSIX signals as listed in RFC 4254 Section 6.10. +const ( + SIGABRT Signal = "ABRT" + SIGALRM Signal = "ALRM" + SIGFPE Signal = "FPE" + SIGHUP Signal = "HUP" + SIGILL Signal = "ILL" + SIGINT Signal = "INT" + SIGKILL Signal = "KILL" + SIGPIPE Signal = "PIPE" + SIGQUIT Signal = "QUIT" + SIGSEGV Signal = "SEGV" + SIGTERM Signal = "TERM" + SIGUSR1 Signal = "USR1" + SIGUSR2 Signal = "USR2" +) + +var signals = map[Signal]int{ + SIGABRT: 6, + SIGALRM: 14, + SIGFPE: 8, + SIGHUP: 1, + SIGILL: 4, + SIGINT: 2, + SIGKILL: 9, + SIGPIPE: 13, + SIGQUIT: 3, + SIGSEGV: 11, + SIGTERM: 15, +} + +type TerminalModes map[uint8]uint32 + +// POSIX terminal mode flags as listed in RFC 4254 Section 8. +const ( + tty_OP_END = 0 + VINTR = 1 + VQUIT = 2 + VERASE = 3 + VKILL = 4 + VEOF = 5 + VEOL = 6 + VEOL2 = 7 + VSTART = 8 + VSTOP = 9 + VSUSP = 10 + VDSUSP = 11 + VREPRINT = 12 + VWERASE = 13 + VLNEXT = 14 + VFLUSH = 15 + VSWTCH = 16 + VSTATUS = 17 + VDISCARD = 18 + IGNPAR = 30 + PARMRK = 31 + INPCK = 32 + ISTRIP = 33 + INLCR = 34 + IGNCR = 35 + ICRNL = 36 + IUCLC = 37 + IXON = 38 + IXANY = 39 + IXOFF = 40 + IMAXBEL = 41 + ISIG = 50 + ICANON = 51 + XCASE = 52 + ECHO = 53 + ECHOE = 54 + ECHOK = 55 + ECHONL = 56 + NOFLSH = 57 + TOSTOP = 58 + IEXTEN = 59 + ECHOCTL = 60 + ECHOKE = 61 + PENDIN = 62 + OPOST = 70 + OLCUC = 71 + ONLCR = 72 + OCRNL = 73 + ONOCR = 74 + ONLRET = 75 + CS7 = 90 + CS8 = 91 + PARENB = 92 + PARODD = 93 + TTY_OP_ISPEED = 128 + TTY_OP_OSPEED = 129 +) + +// A Session represents a connection to a remote command or shell. +type Session struct { + // Stdin specifies the remote process's standard input. + // If Stdin is nil, the remote process reads from an empty + // bytes.Buffer. + Stdin io.Reader + + // Stdout and Stderr specify the remote process's standard + // output and error. + // + // If either is nil, Run connects the corresponding file + // descriptor to an instance of ioutil.Discard. There is a + // fixed amount of buffering that is shared for the two streams. + // If either blocks it may eventually cause the remote + // command to block. + Stdout io.Writer + Stderr io.Writer + + ch Channel // the channel backing this session + started bool // true once Start, Run or Shell is invoked. + copyFuncs []func() error + errors chan error // one send per copyFunc + + // true if pipe method is active + stdinpipe, stdoutpipe, stderrpipe bool + + // stdinPipeWriter is non-nil if StdinPipe has not been called + // and Stdin was specified by the user; it is the write end of + // a pipe connecting Session.Stdin to the stdin channel. + stdinPipeWriter io.WriteCloser + + exitStatus chan error +} + +// SendRequest sends an out-of-band channel request on the SSH channel +// underlying the session. +func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + return s.ch.SendRequest(name, wantReply, payload) +} + +func (s *Session) Close() error { + return s.ch.Close() +} + +// RFC 4254 Section 6.4. +type setenvRequest struct { + Name string + Value string +} + +// Setenv sets an environment variable that will be applied to any +// command executed by Shell or Run. +func (s *Session) Setenv(name, value string) error { + msg := setenvRequest{ + Name: name, + Value: value, + } + ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: setenv failed") + } + return err +} + +// RFC 4254 Section 6.2. +type ptyRequestMsg struct { + Term string + Columns uint32 + Rows uint32 + Width uint32 + Height uint32 + Modelist string +} + +// RequestPty requests the association of a pty with the session on the remote host. +func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { + var tm []byte + for k, v := range termmodes { + kv := struct { + Key byte + Val uint32 + }{k, v} + + tm = append(tm, Marshal(&kv)...) + } + tm = append(tm, tty_OP_END) + req := ptyRequestMsg{ + Term: term, + Columns: uint32(w), + Rows: uint32(h), + Width: uint32(w * 8), + Height: uint32(h * 8), + Modelist: string(tm), + } + ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) + if err == nil && !ok { + err = errors.New("ssh: pty-req failed") + } + return err +} + +// RFC 4254 Section 6.5. +type subsystemRequestMsg struct { + Subsystem string +} + +// RequestSubsystem requests the association of a subsystem with the session on the remote host. +// A subsystem is a predefined command that runs in the background when the ssh session is initiated +func (s *Session) RequestSubsystem(subsystem string) error { + msg := subsystemRequestMsg{ + Subsystem: subsystem, + } + ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: subsystem request failed") + } + return err +} + +// RFC 4254 Section 6.9. +type signalMsg struct { + Signal string +} + +// Signal sends the given signal to the remote process. +// sig is one of the SIG* constants. +func (s *Session) Signal(sig Signal) error { + msg := signalMsg{ + Signal: string(sig), + } + + _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) + return err +} + +// RFC 4254 Section 6.5. +type execMsg struct { + Command string +} + +// Start runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start or Shell. +func (s *Session) Start(cmd string) error { + if s.started { + return errors.New("ssh: session already started") + } + req := execMsg{ + Command: cmd, + } + + ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) + if err == nil && !ok { + err = fmt.Errorf("ssh: command %v failed", cmd) + } + if err != nil { + return err + } + return s.start() +} + +// Run runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start, Shell, Output, +// or CombinedOutput. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the command fails to run or doesn't complete successfully, the +// error is of type *ExitError. Other error types may be +// returned for I/O problems. +func (s *Session) Run(cmd string) error { + err := s.Start(cmd) + if err != nil { + return err + } + return s.Wait() +} + +// Output runs cmd on the remote host and returns its standard output. +func (s *Session) Output(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + var b bytes.Buffer + s.Stdout = &b + err := s.Run(cmd) + return b.Bytes(), err +} + +type singleWriter struct { + b bytes.Buffer + mu sync.Mutex +} + +func (w *singleWriter) Write(p []byte) (int, error) { + w.mu.Lock() + defer w.mu.Unlock() + return w.b.Write(p) +} + +// CombinedOutput runs cmd on the remote host and returns its combined +// standard output and standard error. +func (s *Session) CombinedOutput(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + var b singleWriter + s.Stdout = &b + s.Stderr = &b + err := s.Run(cmd) + return b.b.Bytes(), err +} + +// Shell starts a login shell on the remote host. A Session only +// accepts one call to Run, Start, Shell, Output, or CombinedOutput. +func (s *Session) Shell() error { + if s.started { + return errors.New("ssh: session already started") + } + + ok, err := s.ch.SendRequest("shell", true, nil) + if err == nil && !ok { + return errors.New("ssh: could not start shell") + } + if err != nil { + return err + } + return s.start() +} + +func (s *Session) start() error { + s.started = true + + type F func(*Session) + for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { + setupFd(s) + } + + s.errors = make(chan error, len(s.copyFuncs)) + for _, fn := range s.copyFuncs { + go func(fn func() error) { + s.errors <- fn() + }(fn) + } + return nil +} + +// Wait waits for the remote command to exit. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the command fails to run or doesn't complete successfully, the +// error is of type *ExitError. Other error types may be +// returned for I/O problems. +func (s *Session) Wait() error { + if !s.started { + return errors.New("ssh: session not started") + } + waitErr := <-s.exitStatus + + if s.stdinPipeWriter != nil { + s.stdinPipeWriter.Close() + } + var copyError error + for _ = range s.copyFuncs { + if err := <-s.errors; err != nil && copyError == nil { + copyError = err + } + } + if waitErr != nil { + return waitErr + } + return copyError +} + +func (s *Session) wait(reqs <-chan *Request) error { + wm := Waitmsg{status: -1} + // Wait for msg channel to be closed before returning. + for msg := range reqs { + switch msg.Type { + case "exit-status": + d := msg.Payload + wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3]) + case "exit-signal": + var sigval struct { + Signal string + CoreDumped bool + Error string + Lang string + } + if err := Unmarshal(msg.Payload, &sigval); err != nil { + return err + } + + // Must sanitize strings? + wm.signal = sigval.Signal + wm.msg = sigval.Error + wm.lang = sigval.Lang + default: + // This handles keepalives and matches + // OpenSSH's behaviour. + if msg.WantReply { + msg.Reply(false, nil) + } + } + } + if wm.status == 0 { + return nil + } + if wm.status == -1 { + // exit-status was never sent from server + if wm.signal == "" { + return errors.New("wait: remote command exited without exit status or exit signal") + } + wm.status = 128 + if _, ok := signals[Signal(wm.signal)]; ok { + wm.status += signals[Signal(wm.signal)] + } + } + return &ExitError{wm} +} + +func (s *Session) stdin() { + if s.stdinpipe { + return + } + var stdin io.Reader + if s.Stdin == nil { + stdin = new(bytes.Buffer) + } else { + r, w := io.Pipe() + go func() { + _, err := io.Copy(w, s.Stdin) + w.CloseWithError(err) + }() + stdin, s.stdinPipeWriter = r, w + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.ch, stdin) + if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { + err = err1 + } + return err + }) +} + +func (s *Session) stdout() { + if s.stdoutpipe { + return + } + if s.Stdout == nil { + s.Stdout = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stdout, s.ch) + return err + }) +} + +func (s *Session) stderr() { + if s.stderrpipe { + return + } + if s.Stderr == nil { + s.Stderr = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stderr, s.ch.Stderr()) + return err + }) +} + +// sessionStdin reroutes Close to CloseWrite. +type sessionStdin struct { + io.Writer + ch Channel +} + +func (s *sessionStdin) Close() error { + return s.ch.CloseWrite() +} + +// StdinPipe returns a pipe that will be connected to the +// remote command's standard input when the command starts. +func (s *Session) StdinPipe() (io.WriteCloser, error) { + if s.Stdin != nil { + return nil, errors.New("ssh: Stdin already set") + } + if s.started { + return nil, errors.New("ssh: StdinPipe after process started") + } + s.stdinpipe = true + return &sessionStdin{s.ch, s.ch}, nil +} + +// StdoutPipe returns a pipe that will be connected to the +// remote command's standard output when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StdoutPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StdoutPipe() (io.Reader, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.started { + return nil, errors.New("ssh: StdoutPipe after process started") + } + s.stdoutpipe = true + return s.ch, nil +} + +// StderrPipe returns a pipe that will be connected to the +// remote command's standard error when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StderrPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StderrPipe() (io.Reader, error) { + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + if s.started { + return nil, errors.New("ssh: StderrPipe after process started") + } + s.stderrpipe = true + return s.ch.Stderr(), nil +} + +// newSession returns a new interactive session on the remote host. +func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { + s := &Session{ + ch: ch, + } + s.exitStatus = make(chan error, 1) + go func() { + s.exitStatus <- s.wait(reqs) + }() + + return s, nil +} + +// An ExitError reports unsuccessful completion of a remote command. +type ExitError struct { + Waitmsg +} + +func (e *ExitError) Error() string { + return e.Waitmsg.String() +} + +// Waitmsg stores the information about an exited remote command +// as reported by Wait. +type Waitmsg struct { + status int + signal string + msg string + lang string +} + +// ExitStatus returns the exit status of the remote command. +func (w Waitmsg) ExitStatus() int { + return w.status +} + +// Signal returns the exit signal of the remote command if +// it was terminated violently. +func (w Waitmsg) Signal() string { + return w.signal +} + +// Msg returns the exit message given by the remote command +func (w Waitmsg) Msg() string { + return w.msg +} + +// Lang returns the language tag. See RFC 3066 +func (w Waitmsg) Lang() string { + return w.lang +} + +func (w Waitmsg) String() string { + return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal) +} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go new file mode 100644 index 000000000..6151241ff --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -0,0 +1,407 @@ +// Copyright 2011 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. + +package ssh + +import ( + "errors" + "fmt" + "io" + "math/rand" + "net" + "strconv" + "strings" + "sync" + "time" +) + +// Listen requests the remote peer open a listening socket on +// addr. Incoming connections will be available by calling Accept on +// the returned net.Listener. The listener must be serviced, or the +// SSH connection may hang. +func (c *Client) Listen(n, addr string) (net.Listener, error) { + laddr, err := net.ResolveTCPAddr(n, addr) + if err != nil { + return nil, err + } + return c.ListenTCP(laddr) +} + +// Automatic port allocation is broken with OpenSSH before 6.0. See +// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In +// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, +// rather than the actual port number. This means you can never open +// two different listeners with auto allocated ports. We work around +// this by trying explicit ports until we succeed. + +const openSSHPrefix = "OpenSSH_" + +var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) + +// isBrokenOpenSSHVersion returns true if the given version string +// specifies a version of OpenSSH that is known to have a bug in port +// forwarding. +func isBrokenOpenSSHVersion(versionStr string) bool { + i := strings.Index(versionStr, openSSHPrefix) + if i < 0 { + return false + } + i += len(openSSHPrefix) + j := i + for ; j < len(versionStr); j++ { + if versionStr[j] < '0' || versionStr[j] > '9' { + break + } + } + version, _ := strconv.Atoi(versionStr[i:j]) + return version < 6 +} + +// autoPortListenWorkaround simulates automatic port allocation by +// trying random ports repeatedly. +func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { + var sshListener net.Listener + var err error + const tries = 10 + for i := 0; i < tries; i++ { + addr := *laddr + addr.Port = 1024 + portRandomizer.Intn(60000) + sshListener, err = c.ListenTCP(&addr) + if err == nil { + laddr.Port = addr.Port + return sshListener, err + } + } + return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) +} + +// RFC 4254 7.1 +type channelForwardMsg struct { + addr string + rport uint32 +} + +// ListenTCP requests the remote peer open a listening socket +// on laddr. Incoming connections will be available by calling +// Accept on the returned net.Listener. +func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { + if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { + return c.autoPortListenWorkaround(laddr) + } + + m := channelForwardMsg{ + laddr.IP.String(), + uint32(laddr.Port), + } + // send message + ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("ssh: tcpip-forward request denied by peer") + } + + // If the original port was 0, then the remote side will + // supply a real port number in the response. + if laddr.Port == 0 { + var p struct { + Port uint32 + } + if err := Unmarshal(resp, &p); err != nil { + return nil, err + } + laddr.Port = int(p.Port) + } + + // Register this forward, using the port number we obtained. + ch := c.forwards.add(*laddr) + + return &tcpListener{laddr, c, ch}, nil +} + +// forwardList stores a mapping between remote +// forward requests and the tcpListeners. +type forwardList struct { + sync.Mutex + entries []forwardEntry +} + +// forwardEntry represents an established mapping of a laddr on a +// remote ssh server to a channel connected to a tcpListener. +type forwardEntry struct { + laddr net.TCPAddr + c chan forward +} + +// forward represents an incoming forwarded tcpip connection. The +// arguments to add/remove/lookup should be address as specified in +// the original forward-request. +type forward struct { + newCh NewChannel // the ssh client channel underlying this forward + raddr *net.TCPAddr // the raddr of the incoming connection +} + +func (l *forwardList) add(addr net.TCPAddr) chan forward { + l.Lock() + defer l.Unlock() + f := forwardEntry{ + addr, + make(chan forward, 1), + } + l.entries = append(l.entries, f) + return f.c +} + +// See RFC 4254, section 7.2 +type forwardedTCPPayload struct { + Addr string + Port uint32 + OriginAddr string + OriginPort uint32 +} + +// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. +func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { + if port == 0 || port > 65535 { + return nil, fmt.Errorf("ssh: port number out of range: %d", port) + } + ip := net.ParseIP(string(addr)) + if ip == nil { + return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) + } + return &net.TCPAddr{IP: ip, Port: int(port)}, nil +} + +func (l *forwardList) handleChannels(in <-chan NewChannel) { + for ch := range in { + var payload forwardedTCPPayload + if err := Unmarshal(ch.ExtraData(), &payload); err != nil { + ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) + continue + } + + // RFC 4254 section 7.2 specifies that incoming + // addresses should list the address, in string + // format. It is implied that this should be an IP + // address, as it would be impossible to connect to it + // otherwise. + laddr, err := parseTCPAddr(payload.Addr, payload.Port) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + + if ok := l.forward(*laddr, *raddr, ch); !ok { + // Section 7.2, implementations MUST reject spurious incoming + // connections. + ch.Reject(Prohibited, "no forward for address") + continue + } + } +} + +// remove removes the forward entry, and the channel feeding its +// listener. +func (l *forwardList) remove(addr net.TCPAddr) { + l.Lock() + defer l.Unlock() + for i, f := range l.entries { + if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port { + l.entries = append(l.entries[:i], l.entries[i+1:]...) + close(f.c) + return + } + } +} + +// closeAll closes and clears all forwards. +func (l *forwardList) closeAll() { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + close(f.c) + } + l.entries = nil +} + +func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port { + f.c <- forward{ch, &raddr} + return true + } + } + return false +} + +type tcpListener struct { + laddr *net.TCPAddr + + conn *Client + in <-chan forward +} + +// Accept waits for and returns the next connection to the listener. +func (l *tcpListener) Accept() (net.Conn, error) { + s, ok := <-l.in + if !ok { + return nil, io.EOF + } + ch, incoming, err := s.newCh.Accept() + if err != nil { + return nil, err + } + go DiscardRequests(incoming) + + return &tcpChanConn{ + Channel: ch, + laddr: l.laddr, + raddr: s.raddr, + }, nil +} + +// Close closes the listener. +func (l *tcpListener) Close() error { + m := channelForwardMsg{ + l.laddr.IP.String(), + uint32(l.laddr.Port), + } + + // this also closes the listener. + l.conn.forwards.remove(*l.laddr) + ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) + if err == nil && !ok { + err = errors.New("ssh: cancel-tcpip-forward failed") + } + return err +} + +// Addr returns the listener's network address. +func (l *tcpListener) Addr() net.Addr { + return l.laddr +} + +// Dial initiates a connection to the addr from the remote host. +// The resulting connection has a zero LocalAddr() and RemoteAddr(). +func (c *Client) Dial(n, addr string) (net.Conn, error) { + // Parse the address into host and numeric port. + host, portString, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + port, err := strconv.ParseUint(portString, 10, 16) + if err != nil { + return nil, err + } + // Use a zero address for local and remote address. + zeroAddr := &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port)) + if err != nil { + return nil, err + } + return &tcpChanConn{ + Channel: ch, + laddr: zeroAddr, + raddr: zeroAddr, + }, nil +} + +// DialTCP connects to the remote address raddr on the network net, +// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used +// as the local address for the connection. +func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { + if laddr == nil { + laddr = &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + } + ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) + if err != nil { + return nil, err + } + return &tcpChanConn{ + Channel: ch, + laddr: laddr, + raddr: raddr, + }, nil +} + +// RFC 4254 7.2 +type channelOpenDirectMsg struct { + raddr string + rport uint32 + laddr string + lport uint32 +} + +func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { + msg := channelOpenDirectMsg{ + raddr: raddr, + rport: uint32(rport), + laddr: laddr, + lport: uint32(lport), + } + ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) + if err != nil { + return nil, err + } + go DiscardRequests(in) + return ch, err +} + +type tcpChan struct { + Channel // the backing channel +} + +// tcpChanConn fulfills the net.Conn interface without +// the tcpChan having to hold laddr or raddr directly. +type tcpChanConn struct { + Channel + laddr, raddr net.Addr +} + +// LocalAddr returns the local network address. +func (t *tcpChanConn) LocalAddr() net.Addr { + return t.laddr +} + +// RemoteAddr returns the remote network address. +func (t *tcpChanConn) RemoteAddr() net.Addr { + return t.raddr +} + +// SetDeadline sets the read and write deadlines associated +// with the connection. +func (t *tcpChanConn) SetDeadline(deadline time.Time) error { + if err := t.SetReadDeadline(deadline); err != nil { + return err + } + return t.SetWriteDeadline(deadline) +} + +// SetReadDeadline sets the read deadline. +// A zero value for t means Read will not time out. +// After the deadline, the error from Read will implement net.Error +// with Timeout() == true. +func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { + return errors.New("ssh: tcpChan: deadline not supported") +} + +// SetWriteDeadline exists to satisfy the net.Conn interface +// but is not implemented by this type. It always returns an error. +func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { + return errors.New("ssh: tcpChan: deadline not supported") +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go new file mode 100644 index 000000000..741eeb13f --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -0,0 +1,892 @@ +// Copyright 2011 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. + +package terminal + +import ( + "bytes" + "io" + "sync" + "unicode/utf8" +) + +// EscapeCodes contains escape sequences that can be written to the terminal in +// order to achieve different styles of text. +type EscapeCodes struct { + // Foreground colors + Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte + + // Reset all attributes + Reset []byte +} + +var vt100EscapeCodes = EscapeCodes{ + Black: []byte{keyEscape, '[', '3', '0', 'm'}, + Red: []byte{keyEscape, '[', '3', '1', 'm'}, + Green: []byte{keyEscape, '[', '3', '2', 'm'}, + Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, + Blue: []byte{keyEscape, '[', '3', '4', 'm'}, + Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, + Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, + White: []byte{keyEscape, '[', '3', '7', 'm'}, + + Reset: []byte{keyEscape, '[', '0', 'm'}, +} + +// Terminal contains the state for running a VT100 terminal that is capable of +// reading lines of input. +type Terminal struct { + // AutoCompleteCallback, if non-null, is called for each keypress with + // the full input line and the current position of the cursor (in + // bytes, as an index into |line|). If it returns ok=false, the key + // press is processed normally. Otherwise it returns a replacement line + // and the new cursor position. + AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) + + // Escape contains a pointer to the escape codes for this terminal. + // It's always a valid pointer, although the escape codes themselves + // may be empty if the terminal doesn't support them. + Escape *EscapeCodes + + // lock protects the terminal and the state in this object from + // concurrent processing of a key press and a Write() call. + lock sync.Mutex + + c io.ReadWriter + prompt []rune + + // line is the current line being entered. + line []rune + // pos is the logical position of the cursor in line + pos int + // echo is true if local echo is enabled + echo bool + // pasteActive is true iff there is a bracketed paste operation in + // progress. + pasteActive bool + + // cursorX contains the current X value of the cursor where the left + // edge is 0. cursorY contains the row number where the first row of + // the current line is 0. + cursorX, cursorY int + // maxLine is the greatest value of cursorY so far. + maxLine int + + termWidth, termHeight int + + // outBuf contains the terminal data to be sent. + outBuf []byte + // remainder contains the remainder of any partial key sequences after + // a read. It aliases into inBuf. + remainder []byte + inBuf [256]byte + + // history contains previously entered commands so that they can be + // accessed with the up and down keys. + history stRingBuffer + // historyIndex stores the currently accessed history entry, where zero + // means the immediately previous entry. + historyIndex int + // When navigating up and down the history it's possible to return to + // the incomplete, initial line. That value is stored in + // historyPending. + historyPending string +} + +// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is +// a local terminal, that terminal must first have been put into raw mode. +// prompt is a string that is written at the start of each input line (i.e. +// "> "). +func NewTerminal(c io.ReadWriter, prompt string) *Terminal { + return &Terminal{ + Escape: &vt100EscapeCodes, + c: c, + prompt: []rune(prompt), + termWidth: 80, + termHeight: 24, + echo: true, + historyIndex: -1, + } +} + +const ( + keyCtrlD = 4 + keyCtrlU = 21 + keyEnter = '\r' + keyEscape = 27 + keyBackspace = 127 + keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota + keyUp + keyDown + keyLeft + keyRight + keyAltLeft + keyAltRight + keyHome + keyEnd + keyDeleteWord + keyDeleteLine + keyClearScreen + keyPasteStart + keyPasteEnd +) + +var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} +var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} + +// bytesToKey tries to parse a key sequence from b. If successful, it returns +// the key and the remainder of the input. Otherwise it returns utf8.RuneError. +func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { + if len(b) == 0 { + return utf8.RuneError, nil + } + + if !pasteActive { + switch b[0] { + case 1: // ^A + return keyHome, b[1:] + case 5: // ^E + return keyEnd, b[1:] + case 8: // ^H + return keyBackspace, b[1:] + case 11: // ^K + return keyDeleteLine, b[1:] + case 12: // ^L + return keyClearScreen, b[1:] + case 23: // ^W + return keyDeleteWord, b[1:] + } + } + + if b[0] != keyEscape { + if !utf8.FullRune(b) { + return utf8.RuneError, b + } + r, l := utf8.DecodeRune(b) + return r, b[l:] + } + + if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { + switch b[2] { + case 'A': + return keyUp, b[3:] + case 'B': + return keyDown, b[3:] + case 'C': + return keyRight, b[3:] + case 'D': + return keyLeft, b[3:] + case 'H': + return keyHome, b[3:] + case 'F': + return keyEnd, b[3:] + } + } + + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { + switch b[5] { + case 'C': + return keyAltRight, b[6:] + case 'D': + return keyAltLeft, b[6:] + } + } + + if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { + return keyPasteStart, b[6:] + } + + if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { + return keyPasteEnd, b[6:] + } + + // If we get here then we have a key that we don't recognise, or a + // partial sequence. It's not clear how one should find the end of a + // sequence without knowing them all, but it seems that [a-zA-Z~] only + // appears at the end of a sequence. + for i, c := range b[0:] { + if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { + return keyUnknown, b[i+1:] + } + } + + return utf8.RuneError, b +} + +// queue appends data to the end of t.outBuf +func (t *Terminal) queue(data []rune) { + t.outBuf = append(t.outBuf, []byte(string(data))...) +} + +var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} +var space = []rune{' '} + +func isPrintable(key rune) bool { + isInSurrogateArea := key >= 0xd800 && key <= 0xdbff + return key >= 32 && !isInSurrogateArea +} + +// moveCursorToPos appends data to t.outBuf which will move the cursor to the +// given, logical position in the text. +func (t *Terminal) moveCursorToPos(pos int) { + if !t.echo { + return + } + + x := visualLength(t.prompt) + pos + y := x / t.termWidth + x = x % t.termWidth + + up := 0 + if y < t.cursorY { + up = t.cursorY - y + } + + down := 0 + if y > t.cursorY { + down = y - t.cursorY + } + + left := 0 + if x < t.cursorX { + left = t.cursorX - x + } + + right := 0 + if x > t.cursorX { + right = x - t.cursorX + } + + t.cursorX = x + t.cursorY = y + t.move(up, down, left, right) +} + +func (t *Terminal) move(up, down, left, right int) { + movement := make([]rune, 3*(up+down+left+right)) + m := movement + for i := 0; i < up; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'A' + m = m[3:] + } + for i := 0; i < down; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'B' + m = m[3:] + } + for i := 0; i < left; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'D' + m = m[3:] + } + for i := 0; i < right; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'C' + m = m[3:] + } + + t.queue(movement) +} + +func (t *Terminal) clearLineToRight() { + op := []rune{keyEscape, '[', 'K'} + t.queue(op) +} + +const maxLineLength = 4096 + +func (t *Terminal) setLine(newLine []rune, newPos int) { + if t.echo { + t.moveCursorToPos(0) + t.writeLine(newLine) + for i := len(newLine); i < len(t.line); i++ { + t.writeLine(space) + } + t.moveCursorToPos(newPos) + } + t.line = newLine + t.pos = newPos +} + +func (t *Terminal) advanceCursor(places int) { + t.cursorX += places + t.cursorY += t.cursorX / t.termWidth + if t.cursorY > t.maxLine { + t.maxLine = t.cursorY + } + t.cursorX = t.cursorX % t.termWidth + + if places > 0 && t.cursorX == 0 { + // Normally terminals will advance the current position + // when writing a character. But that doesn't happen + // for the last character in a line. However, when + // writing a character (except a new line) that causes + // a line wrap, the position will be advanced two + // places. + // + // So, if we are stopping at the end of a line, we + // need to write a newline so that our cursor can be + // advanced to the next line. + t.outBuf = append(t.outBuf, '\n') + } +} + +func (t *Terminal) eraseNPreviousChars(n int) { + if n == 0 { + return + } + + if t.pos < n { + n = t.pos + } + t.pos -= n + t.moveCursorToPos(t.pos) + + copy(t.line[t.pos:], t.line[n+t.pos:]) + t.line = t.line[:len(t.line)-n] + if t.echo { + t.writeLine(t.line[t.pos:]) + for i := 0; i < n; i++ { + t.queue(space) + } + t.advanceCursor(n) + t.moveCursorToPos(t.pos) + } +} + +// countToLeftWord returns then number of characters from the cursor to the +// start of the previous word. +func (t *Terminal) countToLeftWord() int { + if t.pos == 0 { + return 0 + } + + pos := t.pos - 1 + for pos > 0 { + if t.line[pos] != ' ' { + break + } + pos-- + } + for pos > 0 { + if t.line[pos] == ' ' { + pos++ + break + } + pos-- + } + + return t.pos - pos +} + +// countToRightWord returns then number of characters from the cursor to the +// start of the next word. +func (t *Terminal) countToRightWord() int { + pos := t.pos + for pos < len(t.line) { + if t.line[pos] == ' ' { + break + } + pos++ + } + for pos < len(t.line) { + if t.line[pos] != ' ' { + break + } + pos++ + } + return pos - t.pos +} + +// visualLength returns the number of visible glyphs in s. +func visualLength(runes []rune) int { + inEscapeSeq := false + length := 0 + + for _, r := range runes { + switch { + case inEscapeSeq: + if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { + inEscapeSeq = false + } + case r == '\x1b': + inEscapeSeq = true + default: + length++ + } + } + + return length +} + +// handleKey processes the given key and, optionally, returns a line of text +// that the user has entered. +func (t *Terminal) handleKey(key rune) (line string, ok bool) { + if t.pasteActive && key != keyEnter { + t.addKeyToLine(key) + return + } + + switch key { + case keyBackspace: + if t.pos == 0 { + return + } + t.eraseNPreviousChars(1) + case keyAltLeft: + // move left by a word. + t.pos -= t.countToLeftWord() + t.moveCursorToPos(t.pos) + case keyAltRight: + // move right by a word. + t.pos += t.countToRightWord() + t.moveCursorToPos(t.pos) + case keyLeft: + if t.pos == 0 { + return + } + t.pos-- + t.moveCursorToPos(t.pos) + case keyRight: + if t.pos == len(t.line) { + return + } + t.pos++ + t.moveCursorToPos(t.pos) + case keyHome: + if t.pos == 0 { + return + } + t.pos = 0 + t.moveCursorToPos(t.pos) + case keyEnd: + if t.pos == len(t.line) { + return + } + t.pos = len(t.line) + t.moveCursorToPos(t.pos) + case keyUp: + entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) + if !ok { + return "", false + } + if t.historyIndex == -1 { + t.historyPending = string(t.line) + } + t.historyIndex++ + runes := []rune(entry) + t.setLine(runes, len(runes)) + case keyDown: + switch t.historyIndex { + case -1: + return + case 0: + runes := []rune(t.historyPending) + t.setLine(runes, len(runes)) + t.historyIndex-- + default: + entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) + if ok { + t.historyIndex-- + runes := []rune(entry) + t.setLine(runes, len(runes)) + } + } + case keyEnter: + t.moveCursorToPos(len(t.line)) + t.queue([]rune("\r\n")) + line = string(t.line) + ok = true + t.line = t.line[:0] + t.pos = 0 + t.cursorX = 0 + t.cursorY = 0 + t.maxLine = 0 + case keyDeleteWord: + // Delete zero or more spaces and then one or more characters. + t.eraseNPreviousChars(t.countToLeftWord()) + case keyDeleteLine: + // Delete everything from the current cursor position to the + // end of line. + for i := t.pos; i < len(t.line); i++ { + t.queue(space) + t.advanceCursor(1) + } + t.line = t.line[:t.pos] + t.moveCursorToPos(t.pos) + case keyCtrlD: + // Erase the character under the current position. + // The EOF case when the line is empty is handled in + // readLine(). + if t.pos < len(t.line) { + t.pos++ + t.eraseNPreviousChars(1) + } + case keyCtrlU: + t.eraseNPreviousChars(t.pos) + case keyClearScreen: + // Erases the screen and moves the cursor to the home position. + t.queue([]rune("\x1b[2J\x1b[H")) + t.queue(t.prompt) + t.cursorX, t.cursorY = 0, 0 + t.advanceCursor(visualLength(t.prompt)) + t.setLine(t.line, t.pos) + default: + if t.AutoCompleteCallback != nil { + prefix := string(t.line[:t.pos]) + suffix := string(t.line[t.pos:]) + + t.lock.Unlock() + newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) + t.lock.Lock() + + if completeOk { + t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) + return + } + } + if !isPrintable(key) { + return + } + if len(t.line) == maxLineLength { + return + } + t.addKeyToLine(key) + } + return +} + +// addKeyToLine inserts the given key at the current position in the current +// line. +func (t *Terminal) addKeyToLine(key rune) { + if len(t.line) == cap(t.line) { + newLine := make([]rune, len(t.line), 2*(1+len(t.line))) + copy(newLine, t.line) + t.line = newLine + } + t.line = t.line[:len(t.line)+1] + copy(t.line[t.pos+1:], t.line[t.pos:]) + t.line[t.pos] = key + if t.echo { + t.writeLine(t.line[t.pos:]) + } + t.pos++ + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) writeLine(line []rune) { + for len(line) != 0 { + remainingOnLine := t.termWidth - t.cursorX + todo := len(line) + if todo > remainingOnLine { + todo = remainingOnLine + } + t.queue(line[:todo]) + t.advanceCursor(visualLength(line[:todo])) + line = line[todo:] + } +} + +func (t *Terminal) Write(buf []byte) (n int, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + if t.cursorX == 0 && t.cursorY == 0 { + // This is the easy case: there's nothing on the screen that we + // have to move out of the way. + return t.c.Write(buf) + } + + // We have a prompt and possibly user input on the screen. We + // have to clear it first. + t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) + t.cursorX = 0 + t.clearLineToRight() + + for t.cursorY > 0 { + t.move(1 /* up */, 0, 0, 0) + t.cursorY-- + t.clearLineToRight() + } + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + + if n, err = t.c.Write(buf); err != nil { + return + } + + t.writeLine(t.prompt) + if t.echo { + t.writeLine(t.line) + } + + t.moveCursorToPos(t.pos) + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + return +} + +// ReadPassword temporarily changes the prompt and reads a password, without +// echo, from the terminal. +func (t *Terminal) ReadPassword(prompt string) (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + oldPrompt := t.prompt + t.prompt = []rune(prompt) + t.echo = false + + line, err = t.readLine() + + t.prompt = oldPrompt + t.echo = true + + return +} + +// ReadLine returns a line of input from the terminal. +func (t *Terminal) ReadLine() (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + return t.readLine() +} + +func (t *Terminal) readLine() (line string, err error) { + // t.lock must be held at this point + + if t.cursorX == 0 && t.cursorY == 0 { + t.writeLine(t.prompt) + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + } + + lineIsPasted := t.pasteActive + + for { + rest := t.remainder + lineOk := false + for !lineOk { + var key rune + key, rest = bytesToKey(rest, t.pasteActive) + if key == utf8.RuneError { + break + } + if !t.pasteActive { + if key == keyCtrlD { + if len(t.line) == 0 { + return "", io.EOF + } + } + if key == keyPasteStart { + t.pasteActive = true + if len(t.line) == 0 { + lineIsPasted = true + } + continue + } + } else if key == keyPasteEnd { + t.pasteActive = false + continue + } + if !t.pasteActive { + lineIsPasted = false + } + line, lineOk = t.handleKey(key) + } + if len(rest) > 0 { + n := copy(t.inBuf[:], rest) + t.remainder = t.inBuf[:n] + } else { + t.remainder = nil + } + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + if lineOk { + if t.echo { + t.historyIndex = -1 + t.history.Add(line) + } + if lineIsPasted { + err = ErrPasteIndicator + } + return + } + + // t.remainder is a slice at the beginning of t.inBuf + // containing a partial key sequence + readBuf := t.inBuf[len(t.remainder):] + var n int + + t.lock.Unlock() + n, err = t.c.Read(readBuf) + t.lock.Lock() + + if err != nil { + return + } + + t.remainder = t.inBuf[:n+len(t.remainder)] + } + + panic("unreachable") // for Go 1.0. +} + +// SetPrompt sets the prompt to be used when reading subsequent lines. +func (t *Terminal) SetPrompt(prompt string) { + t.lock.Lock() + defer t.lock.Unlock() + + t.prompt = []rune(prompt) +} + +func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { + // Move cursor to column zero at the start of the line. + t.move(t.cursorY, 0, t.cursorX, 0) + t.cursorX, t.cursorY = 0, 0 + t.clearLineToRight() + for t.cursorY < numPrevLines { + // Move down a line + t.move(0, 1, 0, 0) + t.cursorY++ + t.clearLineToRight() + } + // Move back to beginning. + t.move(t.cursorY, 0, 0, 0) + t.cursorX, t.cursorY = 0, 0 + + t.queue(t.prompt) + t.advanceCursor(visualLength(t.prompt)) + t.writeLine(t.line) + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) SetSize(width, height int) error { + t.lock.Lock() + defer t.lock.Unlock() + + if width == 0 { + width = 1 + } + + oldWidth := t.termWidth + t.termWidth, t.termHeight = width, height + + switch { + case width == oldWidth: + // If the width didn't change then nothing else needs to be + // done. + return nil + case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: + // If there is nothing on current line and no prompt printed, + // just do nothing + return nil + case width < oldWidth: + // Some terminals (e.g. xterm) will truncate lines that were + // too long when shinking. Others, (e.g. gnome-terminal) will + // attempt to wrap them. For the former, repainting t.maxLine + // works great, but that behaviour goes badly wrong in the case + // of the latter because they have doubled every full line. + + // We assume that we are working on a terminal that wraps lines + // and adjust the cursor position based on every previous line + // wrapping and turning into two. This causes the prompt on + // xterms to move upwards, which isn't great, but it avoids a + // huge mess with gnome-terminal. + if t.cursorX >= t.termWidth { + t.cursorX = t.termWidth - 1 + } + t.cursorY *= 2 + t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) + case width > oldWidth: + // If the terminal expands then our position calculations will + // be wrong in the future because we think the cursor is + // |t.pos| chars into the string, but there will be a gap at + // the end of any wrapped line. + // + // But the position will actually be correct until we move, so + // we can move back to the beginning and repaint everything. + t.clearAndRepaintLinePlusNPrevious(t.maxLine) + } + + _, err := t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + return err +} + +type pasteIndicatorError struct{} + +func (pasteIndicatorError) Error() string { + return "terminal: ErrPasteIndicator not correctly handled" +} + +// ErrPasteIndicator may be returned from ReadLine as the error, in addition +// to valid line data. It indicates that bracketed paste mode is enabled and +// that the returned line consists only of pasted data. Programs may wish to +// interpret pasted data more literally than typed data. +var ErrPasteIndicator = pasteIndicatorError{} + +// SetBracketedPasteMode requests that the terminal bracket paste operations +// with markers. Not all terminals support this but, if it is supported, then +// enabling this mode will stop any autocomplete callback from running due to +// pastes. Additionally, any lines that are completely pasted will be returned +// from ReadLine with the error set to ErrPasteIndicator. +func (t *Terminal) SetBracketedPasteMode(on bool) { + if on { + io.WriteString(t.c, "\x1b[?2004h") + } else { + io.WriteString(t.c, "\x1b[?2004l") + } +} + +// stRingBuffer is a ring buffer of strings. +type stRingBuffer struct { + // entries contains max elements. + entries []string + max int + // head contains the index of the element most recently added to the ring. + head int + // size contains the number of elements in the ring. + size int +} + +func (s *stRingBuffer) Add(a string) { + if s.entries == nil { + const defaultNumEntries = 100 + s.entries = make([]string, defaultNumEntries) + s.max = defaultNumEntries + } + + s.head = (s.head + 1) % s.max + s.entries[s.head] = a + if s.size < s.max { + s.size++ + } +} + +// NthPreviousEntry returns the value passed to the nth previous call to Add. +// If n is zero then the immediately prior value is returned, if one, then the +// next most recent, and so on. If such an element doesn't exist then ok is +// false. +func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { + if n >= s.size { + return "", false + } + index := s.head - n + if index < 0 { + index += s.max + } + return s.entries[index], true +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go new file mode 100644 index 000000000..0763c9a97 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go @@ -0,0 +1,128 @@ +// Copyright 2011 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. + +// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "io" + "syscall" + "unsafe" +) + +// State contains the state of a terminal. +type State struct { + termios syscall.Termios +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var oldState State + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + return nil, err + } + + newState := oldState.termios + newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF + newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + return nil, err + } + + return &oldState, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + var oldState State + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + return nil, err + } + + return &oldState, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) + return err +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + var dimensions [4]uint16 + + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { + return -1, -1, err + } + return int(dimensions[1]), int(dimensions[0]), nil +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + var oldState syscall.Termios + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { + return nil, err + } + + newState := oldState + newState.Lflag &^= syscall.ECHO + newState.Lflag |= syscall.ICANON | syscall.ISIG + newState.Iflag |= syscall.ICRNL + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + return nil, err + } + + defer func() { + syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) + }() + + var buf [16]byte + var ret []byte + for { + n, err := syscall.Read(fd, buf[:]) + if err != nil { + return nil, err + } + if n == 0 { + if len(ret) == 0 { + return nil, io.EOF + } + break + } + if buf[n-1] == '\n' { + n-- + } + ret = append(ret, buf[:n]...) + if n < len(buf) { + break + } + } + + return ret, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go new file mode 100644 index 000000000..9c1ffd145 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go @@ -0,0 +1,12 @@ +// Copyright 2013 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. + +// +build darwin dragonfly freebsd netbsd openbsd + +package terminal + +import "syscall" + +const ioctlReadTermios = syscall.TIOCGETA +const ioctlWriteTermios = syscall.TIOCSETA diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go new file mode 100644 index 000000000..5883b22d7 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go @@ -0,0 +1,11 @@ +// Copyright 2013 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. + +package terminal + +// These constants are declared here, rather than importing +// them from the syscall package as some syscall packages, even +// on linux, for example gccgo, do not declare them. +const ioctlReadTermios = 0x5401 // syscall.TCGETS +const ioctlWriteTermios = 0x5402 // syscall.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go new file mode 100644 index 000000000..2dd6c3d97 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -0,0 +1,174 @@ +// Copyright 2011 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. + +// +build windows + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "io" + "syscall" + "unsafe" +) + +const ( + enableLineInput = 2 + enableEchoInput = 4 + enableProcessedInput = 1 + enableWindowInput = 8 + enableMouseInput = 16 + enableInsertMode = 32 + enableQuickEditMode = 64 + enableExtendedFlags = 128 + enableAutoPosition = 256 + enableProcessedOutput = 1 + enableWrapAtEolOutput = 2 +) + +var kernel32 = syscall.NewLazyDLL("kernel32.dll") + +var ( + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") +) + +type ( + short int16 + word uint16 + + coord struct { + x short + y short + } + smallRect struct { + left short + top short + right short + bottom short + } + consoleScreenBufferInfo struct { + size coord + cursorPosition coord + attributes word + window smallRect + maximumWindowSize coord + } +) + +type State struct { + mode uint32 +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var st uint32 + _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) + if e != 0 { + return nil, error(e) + } + st &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) + _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) + if e != 0 { + return nil, error(e) + } + return &State{st}, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + var st uint32 + _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) + if e != 0 { + return nil, error(e) + } + return &State{st}, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) + return err +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + var info consoleScreenBufferInfo + _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) + if e != 0 { + return 0, 0, error(e) + } + return int(info.size.x), int(info.size.y), nil +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + var st uint32 + _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) + if e != 0 { + return nil, error(e) + } + old := st + + st &^= (enableEchoInput) + st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) + _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) + if e != 0 { + return nil, error(e) + } + + defer func() { + syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) + }() + + var buf [16]byte + var ret []byte + for { + n, err := syscall.Read(syscall.Handle(fd), buf[:]) + if err != nil { + return nil, err + } + if n == 0 { + if len(ret) == 0 { + return nil, io.EOF + } + break + } + if buf[n-1] == '\n' { + n-- + } + if n > 0 && buf[n-1] == '\r' { + n-- + } + ret = append(ret, buf[:n]...) + if n < len(buf) { + break + } + } + + return ret, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/test/doc.go b/vendor/golang.org/x/crypto/ssh/test/doc.go new file mode 100644 index 000000000..29ad65e96 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/doc.go @@ -0,0 +1,7 @@ +// Copyright 2012 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. + +// This package contains integration tests for the +// golang.org/x/crypto/ssh package. +package test diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go new file mode 100644 index 000000000..8351d378e --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -0,0 +1,332 @@ +// Copyright 2011 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. + +package ssh + +import ( + "bufio" + "errors" + "io" +) + +const ( + gcmCipherID = "aes128-gcm@openssh.com" + aes128cbcID = "aes128-cbc" +) + +// packetConn represents a transport that implements packet based +// operations. +type packetConn interface { + // Encrypt and send a packet of data to the remote peer. + writePacket(packet []byte) error + + // Read a packet from the connection + readPacket() ([]byte, error) + + // Close closes the write-side of the connection. + Close() error +} + +// transport is the keyingTransport that implements the SSH packet +// protocol. +type transport struct { + reader connectionState + writer connectionState + + bufReader *bufio.Reader + bufWriter *bufio.Writer + rand io.Reader + + io.Closer + + // Initial H used for the session ID. Once assigned this does + // not change, even during subsequent key exchanges. + sessionID []byte +} + +// getSessionID returns the ID of the SSH connection. The return value +// should not be modified. +func (t *transport) getSessionID() []byte { + if t.sessionID == nil { + panic("session ID not set yet") + } + return t.sessionID +} + +// packetCipher represents a combination of SSH encryption/MAC +// protocol. A single instance should be used for one direction only. +type packetCipher interface { + // writePacket encrypts the packet and writes it to w. The + // contents of the packet are generally scrambled. + writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error + + // readPacket reads and decrypts a packet of data. The + // returned packet may be overwritten by future calls of + // readPacket. + readPacket(seqnum uint32, r io.Reader) ([]byte, error) +} + +// connectionState represents one side (read or write) of the +// connection. This is necessary because each direction has its own +// keys, and can even have its own algorithms +type connectionState struct { + packetCipher + seqNum uint32 + dir direction + pendingKeyChange chan packetCipher +} + +// prepareKeyChange sets up key material for a keychange. The key changes in +// both directions are triggered by reading and writing a msgNewKey packet +// respectively. +func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { + if t.sessionID == nil { + t.sessionID = kexResult.H + } + + kexResult.SessionID = t.sessionID + + if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { + return err + } else { + t.reader.pendingKeyChange <- ciph + } + + if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil { + return err + } else { + t.writer.pendingKeyChange <- ciph + } + + return nil +} + +// Read and decrypt next packet. +func (t *transport) readPacket() ([]byte, error) { + return t.reader.readPacket(t.bufReader) +} + +func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { + packet, err := s.packetCipher.readPacket(s.seqNum, r) + s.seqNum++ + if err == nil && len(packet) == 0 { + err = errors.New("ssh: zero length packet") + } + + if len(packet) > 0 && packet[0] == msgNewKeys { + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + return nil, errors.New("ssh: got bogus newkeys message.") + } + } + + // The packet may point to an internal buffer, so copy the + // packet out here. + fresh := make([]byte, len(packet)) + copy(fresh, packet) + + return fresh, err +} + +func (t *transport) writePacket(packet []byte) error { + return t.writer.writePacket(t.bufWriter, t.rand, packet) +} + +func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { + changeKeys := len(packet) > 0 && packet[0] == msgNewKeys + + err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) + if err != nil { + return err + } + if err = w.Flush(); err != nil { + return err + } + s.seqNum++ + if changeKeys { + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + panic("ssh: no key material for msgNewKeys") + } + } + return err +} + +func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { + t := &transport{ + bufReader: bufio.NewReader(rwc), + bufWriter: bufio.NewWriter(rwc), + rand: rand, + reader: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + writer: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + Closer: rwc, + } + if isClient { + t.reader.dir = serverKeys + t.writer.dir = clientKeys + } else { + t.reader.dir = clientKeys + t.writer.dir = serverKeys + } + + return t +} + +type direction struct { + ivTag []byte + keyTag []byte + macKeyTag []byte +} + +var ( + serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} + clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} +) + +// generateKeys generates key material for IV, MAC and encryption. +func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { + cipherMode := cipherModes[algs.Cipher] + macMode := macModes[algs.MAC] + + iv = make([]byte, cipherMode.ivSize) + key = make([]byte, cipherMode.keySize) + macKey = make([]byte, macMode.keySize) + + generateKeyMaterial(iv, d.ivTag, kex) + generateKeyMaterial(key, d.keyTag, kex) + generateKeyMaterial(macKey, d.macKeyTag, kex) + return +} + +// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as +// described in RFC 4253, section 6.4. direction should either be serverKeys +// (to setup server->client keys) or clientKeys (for client->server keys). +func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { + iv, key, macKey := generateKeys(d, algs, kex) + + if algs.Cipher == gcmCipherID { + return newGCMCipher(iv, key, macKey) + } + + if algs.Cipher == aes128cbcID { + return newAESCBCCipher(iv, key, macKey, algs) + } + + c := &streamPacketCipher{ + mac: macModes[algs.MAC].new(macKey), + } + c.macResult = make([]byte, c.mac.Size()) + + var err error + c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) + if err != nil { + return nil, err + } + + return c, nil +} + +// generateKeyMaterial fills out with key material generated from tag, K, H +// and sessionId, as specified in RFC 4253, section 7.2. +func generateKeyMaterial(out, tag []byte, r *kexResult) { + var digestsSoFar []byte + + h := r.Hash.New() + for len(out) > 0 { + h.Reset() + h.Write(r.K) + h.Write(r.H) + + if len(digestsSoFar) == 0 { + h.Write(tag) + h.Write(r.SessionID) + } else { + h.Write(digestsSoFar) + } + + digest := h.Sum(nil) + n := copy(out, digest) + out = out[n:] + if len(out) > 0 { + digestsSoFar = append(digestsSoFar, digest...) + } + } +} + +const packageVersion = "SSH-2.0-Go" + +// Sends and receives a version line. The versionLine string should +// be US ASCII, start with "SSH-2.0-", and should not include a +// newline. exchangeVersions returns the other side's version line. +func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { + // Contrary to the RFC, we do not ignore lines that don't + // start with "SSH-2.0-" to make the library usable with + // nonconforming servers. + for _, c := range versionLine { + // The spec disallows non US-ASCII chars, and + // specifically forbids null chars. + if c < 32 { + return nil, errors.New("ssh: junk character in version line") + } + } + if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { + return + } + + them, err = readVersion(rw) + return them, err +} + +// maxVersionStringBytes is the maximum number of bytes that we'll +// accept as a version string. RFC 4253 section 4.2 limits this at 255 +// chars +const maxVersionStringBytes = 255 + +// Read version string as specified by RFC 4253, section 4.2. +func readVersion(r io.Reader) ([]byte, error) { + versionString := make([]byte, 0, 64) + var ok bool + var buf [1]byte + + for len(versionString) < maxVersionStringBytes { + _, err := io.ReadFull(r, buf[:]) + if err != nil { + return nil, err + } + // The RFC says that the version should be terminated with \r\n + // but several SSH servers actually only send a \n. + if buf[0] == '\n' { + ok = true + break + } + + // non ASCII chars are disallowed, but we are lenient, + // since Go doesn't use null-terminated strings. + + // The RFC allows a comment after a space, however, + // all of it (version and comments) goes into the + // session hash. + versionString = append(versionString, buf[0]) + } + + if !ok { + return nil, errors.New("ssh: overflow reading version string") + } + + // There might be a '\r' on the end which we should remove. + if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { + versionString = versionString[:len(versionString)-1] + } + return versionString, nil +} diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/golang.org/x/net/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/golang.org/x/net/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go new file mode 100644 index 000000000..11bd8d34e --- /dev/null +++ b/vendor/golang.org/x/net/context/context.go @@ -0,0 +1,447 @@ +// Copyright 2014 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. + +// Package context defines the Context type, which carries deadlines, +// cancelation signals, and other request-scoped values across API boundaries +// and between processes. +// +// Incoming requests to a server should create a Context, and outgoing calls to +// servers should accept a Context. The chain of function calls between must +// propagate the Context, optionally replacing it with a modified copy created +// using WithDeadline, WithTimeout, WithCancel, or WithValue. +// +// Programs that use Contexts should follow these rules to keep interfaces +// consistent across packages and enable static analysis tools to check context +// propagation: +// +// Do not store Contexts inside a struct type; instead, pass a Context +// explicitly to each function that needs it. The Context should be the first +// parameter, typically named ctx: +// +// func DoSomething(ctx context.Context, arg Arg) error { +// // ... use ctx ... +// } +// +// Do not pass a nil Context, even if a function permits it. Pass context.TODO +// if you are unsure about which Context to use. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +// +// The same Context may be passed to functions running in different goroutines; +// Contexts are safe for simultaneous use by multiple goroutines. +// +// See http://blog.golang.org/context for example code for a server that uses +// Contexts. +package context + +import ( + "errors" + "fmt" + "sync" + "time" +) + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out <-chan Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See http://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancelation. + Done() <-chan struct{} + + // Err returns a non-nil error value after Done is closed. Err returns + // Canceled if the context was canceled or DeadlineExceeded if the + // context's deadline passed. No other values for Err are defined. + // After Done is closed, successive calls to Err return the same value. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stores using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "golang.org/x/net/context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key = 0 + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = errors.New("context canceled") + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = errors.New("context deadline exceeded") + +// An emptyCtx is never canceled, has no values, and has no deadline. It is not +// struct{}, since vars of this type must have distinct addresses. +type emptyCtx int + +func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (*emptyCtx) Done() <-chan struct{} { + return nil +} + +func (*emptyCtx) Err() error { + return nil +} + +func (*emptyCtx) Value(key interface{}) interface{} { + return nil +} + +func (e *emptyCtx) String() string { + switch e { + case background: + return "context.Background" + case todo: + return "context.TODO" + } + return "unknown empty Context" +} + +var ( + background = new(emptyCtx) + todo = new(emptyCtx) +) + +// Background returns a non-nil, empty Context. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +func Background() Context { + return background +} + +// TODO returns a non-nil, empty Context. Code should use context.TODO when +// it's unclear which Context to use or it is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). TODO is recognized by static analysis tools that determine +// whether Contexts are propagated correctly in a program. +func TODO() Context { + return todo +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + c := newCancelCtx(parent) + propagateCancel(parent, &c) + return &c, func() { c.cancel(true, Canceled) } +} + +// newCancelCtx returns an initialized cancelCtx. +func newCancelCtx(parent Context) cancelCtx { + return cancelCtx{ + Context: parent, + done: make(chan struct{}), + } +} + +// propagateCancel arranges for child to be canceled when parent is. +func propagateCancel(parent Context, child canceler) { + if parent.Done() == nil { + return // parent is never canceled + } + if p, ok := parentCancelCtx(parent); ok { + p.mu.Lock() + if p.err != nil { + // parent has already been canceled + child.cancel(false, p.err) + } else { + if p.children == nil { + p.children = make(map[canceler]bool) + } + p.children[child] = true + } + p.mu.Unlock() + } else { + go func() { + select { + case <-parent.Done(): + child.cancel(false, parent.Err()) + case <-child.Done(): + } + }() + } +} + +// parentCancelCtx follows a chain of parent references until it finds a +// *cancelCtx. This function understands how each of the concrete types in this +// package represents its parent. +func parentCancelCtx(parent Context) (*cancelCtx, bool) { + for { + switch c := parent.(type) { + case *cancelCtx: + return c, true + case *timerCtx: + return &c.cancelCtx, true + case *valueCtx: + parent = c.Context + default: + return nil, false + } + } +} + +// removeChild removes a context from its parent. +func removeChild(parent Context, child canceler) { + p, ok := parentCancelCtx(parent) + if !ok { + return + } + p.mu.Lock() + if p.children != nil { + delete(p.children, child) + } + p.mu.Unlock() +} + +// A canceler is a context type that can be canceled directly. The +// implementations are *cancelCtx and *timerCtx. +type canceler interface { + cancel(removeFromParent bool, err error) + Done() <-chan struct{} +} + +// A cancelCtx can be canceled. When canceled, it also cancels any children +// that implement canceler. +type cancelCtx struct { + Context + + done chan struct{} // closed by the first cancel call. + + mu sync.Mutex + children map[canceler]bool // set to nil by the first cancel call + err error // set to non-nil by the first cancel call +} + +func (c *cancelCtx) Done() <-chan struct{} { + return c.done +} + +func (c *cancelCtx) Err() error { + c.mu.Lock() + defer c.mu.Unlock() + return c.err +} + +func (c *cancelCtx) String() string { + return fmt.Sprintf("%v.WithCancel", c.Context) +} + +// cancel closes c.done, cancels each of c's children, and, if +// removeFromParent is true, removes c from its parent's children. +func (c *cancelCtx) cancel(removeFromParent bool, err error) { + if err == nil { + panic("context: internal error: missing cancel error") + } + c.mu.Lock() + if c.err != nil { + c.mu.Unlock() + return // already canceled + } + c.err = err + close(c.done) + for child := range c.children { + // NOTE: acquiring the child's lock while holding parent's lock. + child.cancel(false, err) + } + c.children = nil + c.mu.Unlock() + + if removeFromParent { + removeChild(c.Context, c) + } +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { + // The current deadline is already sooner than the new one. + return WithCancel(parent) + } + c := &timerCtx{ + cancelCtx: newCancelCtx(parent), + deadline: deadline, + } + propagateCancel(parent, c) + d := deadline.Sub(time.Now()) + if d <= 0 { + c.cancel(true, DeadlineExceeded) // deadline has already passed + return c, func() { c.cancel(true, Canceled) } + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err == nil { + c.timer = time.AfterFunc(d, func() { + c.cancel(true, DeadlineExceeded) + }) + } + return c, func() { c.cancel(true, Canceled) } +} + +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then +// delegating to cancelCtx.cancel. +type timerCtx struct { + cancelCtx + timer *time.Timer // Under cancelCtx.mu. + + deadline time.Time +} + +func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { + return c.deadline, true +} + +func (c *timerCtx) String() string { + return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) +} + +func (c *timerCtx) cancel(removeFromParent bool, err error) { + c.cancelCtx.cancel(false, err) + if removeFromParent { + // Remove this timerCtx from its parent cancelCtx's children. + removeChild(c.cancelCtx.Context, c) + } + c.mu.Lock() + if c.timer != nil { + c.timer.Stop() + c.timer = nil + } + c.mu.Unlock() +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return &valueCtx{parent, key, val} +} + +// A valueCtx carries a key-value pair. It implements Value for that key and +// delegates all other calls to the embedded Context. +type valueCtx struct { + Context + key, val interface{} +} + +func (c *valueCtx) String() string { + return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) +} + +func (c *valueCtx) Value(key interface{}) interface{} { + if c.key == key { + return c.val + } + return c.Context.Value(key) +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go b/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go new file mode 100644 index 000000000..e3170e333 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// +build go1.5 + +package ctxhttp + +import "net/http" + +func canceler(client *http.Client, req *http.Request) func() { + // TODO(djd): Respect any existing value of req.Cancel. + ch := make(chan struct{}) + req.Cancel = ch + + return func() { + close(ch) + } +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go b/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go new file mode 100644 index 000000000..56bcbadb8 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go @@ -0,0 +1,23 @@ +// Copyright 2015 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. + +// +build !go1.5 + +package ctxhttp + +import "net/http" + +type requestCanceler interface { + CancelRequest(*http.Request) +} + +func canceler(client *http.Client, req *http.Request) func() { + rc, ok := client.Transport.(requestCanceler) + if !ok { + return func() {} + } + return func() { + rc.CancelRequest(req) + } +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go new file mode 100644 index 000000000..26a5e19ac --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -0,0 +1,140 @@ +// Copyright 2015 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. + +// Package ctxhttp provides helper functions for performing context-aware HTTP requests. +package ctxhttp + +import ( + "io" + "net/http" + "net/url" + "strings" + + "golang.org/x/net/context" +) + +func nop() {} + +var ( + testHookContextDoneBeforeHeaders = nop + testHookDoReturned = nop + testHookDidBodyClose = nop +) + +// Do sends an HTTP request with the provided http.Client and returns an HTTP response. +// If the client is nil, http.DefaultClient is used. +// If the context is canceled or times out, ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + + // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go. + cancel := canceler(client, req) + + type responseAndError struct { + resp *http.Response + err error + } + result := make(chan responseAndError, 1) + + go func() { + resp, err := client.Do(req) + testHookDoReturned() + result <- responseAndError{resp, err} + }() + + var resp *http.Response + + select { + case <-ctx.Done(): + testHookContextDoneBeforeHeaders() + cancel() + // Clean up after the goroutine calling client.Do: + go func() { + if r := <-result; r.resp != nil { + testHookDidBodyClose() + r.resp.Body.Close() + } + }() + return nil, ctx.Err() + case r := <-result: + var err error + resp, err = r.resp, r.err + if err != nil { + return resp, err + } + } + + c := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + cancel() + case <-c: + // The response's Body is closed. + } + }() + resp.Body = ¬ifyingReader{resp.Body, c} + + return resp, nil +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} + +// notifyingReader is an io.ReadCloser that closes the notify channel after +// Close is called or a Read fails on the underlying ReadCloser. +type notifyingReader struct { + io.ReadCloser + notify chan<- struct{} +} + +func (r *notifyingReader) Read(p []byte) (int, error) { + n, err := r.ReadCloser.Read(p) + if err != nil && r.notify != nil { + close(r.notify) + r.notify = nil + } + return n, err +} + +func (r *notifyingReader) Close() error { + err := r.ReadCloser.Close() + if r.notify != nil { + close(r.notify) + r.notify = nil + } + return err +} diff --git a/vendor/golang.org/x/net/html/atom/atom.go b/vendor/golang.org/x/net/html/atom/atom.go new file mode 100644 index 000000000..227404bda --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/atom.go @@ -0,0 +1,78 @@ +// Copyright 2012 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. + +// Package atom provides integer codes (also known as atoms) for a fixed set of +// frequently occurring HTML strings: tag names and attribute keys such as "p" +// and "id". +// +// Sharing an atom's name between all elements with the same tag can result in +// fewer string allocations when tokenizing and parsing HTML. Integer +// comparisons are also generally faster than string comparisons. +// +// The value of an atom's particular code is not guaranteed to stay the same +// between versions of this package. Neither is any ordering guaranteed: +// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to +// be dense. The only guarantees are that e.g. looking up "div" will yield +// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. +package atom + +// Atom is an integer code for a string. The zero value maps to "". +type Atom uint32 + +// String returns the atom's name. +func (a Atom) String() string { + start := uint32(a >> 8) + n := uint32(a & 0xff) + if start+n > uint32(len(atomText)) { + return "" + } + return atomText[start : start+n] +} + +func (a Atom) string() string { + return atomText[a>>8 : a>>8+a&0xff] +} + +// fnv computes the FNV hash with an arbitrary starting value h. +func fnv(h uint32, s []byte) uint32 { + for i := range s { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +func match(s string, t []byte) bool { + for i, c := range t { + if s[i] != c { + return false + } + } + return true +} + +// Lookup returns the atom whose name is s. It returns zero if there is no +// such atom. The lookup is case sensitive. +func Lookup(s []byte) Atom { + if len(s) == 0 || len(s) > maxAtomLen { + return 0 + } + h := fnv(hash0, s) + if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { + return a + } + if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { + return a + } + return 0 +} + +// String returns a string whose contents are equal to s. In that sense, it is +// equivalent to string(s) but may be more efficient. +func String(s []byte) string { + if a := Lookup(s); a != 0 { + return a.String() + } + return string(s) +} diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go new file mode 100644 index 000000000..6bfa86601 --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -0,0 +1,648 @@ +// Copyright 2012 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. + +// +build ignore + +package main + +// This program generates table.go and table_test.go. +// Invoke as +// +// go run gen.go |gofmt >table.go +// go run gen.go -test |gofmt >table_test.go + +import ( + "flag" + "fmt" + "math/rand" + "os" + "sort" + "strings" +) + +// identifier converts s to a Go exported identifier. +// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". +func identifier(s string) string { + b := make([]byte, 0, len(s)) + cap := true + for _, c := range s { + if c == '-' { + cap = true + continue + } + if cap && 'a' <= c && c <= 'z' { + c -= 'a' - 'A' + } + cap = false + b = append(b, byte(c)) + } + return string(b) +} + +var test = flag.Bool("test", false, "generate table_test.go") + +func main() { + flag.Parse() + + var all []string + all = append(all, elements...) + all = append(all, attributes...) + all = append(all, eventHandlers...) + all = append(all, extra...) + sort.Strings(all) + + if *test { + fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n") + fmt.Printf("package atom\n\n") + fmt.Printf("var testAtomList = []string{\n") + for _, s := range all { + fmt.Printf("\t%q,\n", s) + } + fmt.Printf("}\n") + return + } + + // uniq - lists have dups + // compute max len too + maxLen := 0 + w := 0 + for _, s := range all { + if w == 0 || all[w-1] != s { + if maxLen < len(s) { + maxLen = len(s) + } + all[w] = s + w++ + } + } + all = all[:w] + + // Find hash that minimizes table size. + var best *table + for i := 0; i < 1000000; i++ { + if best != nil && 1<<(best.k-1) < len(all) { + break + } + h := rand.Uint32() + for k := uint(0); k <= 16; k++ { + if best != nil && k >= best.k { + break + } + var t table + if t.init(h, k, all) { + best = &t + break + } + } + } + if best == nil { + fmt.Fprintf(os.Stderr, "failed to construct string table\n") + os.Exit(1) + } + + // Lay out strings, using overlaps when possible. + layout := append([]string{}, all...) + + // Remove strings that are substrings of other strings + for changed := true; changed; { + changed = false + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i != j && t != "" && strings.Contains(s, t) { + changed = true + layout[j] = "" + } + } + } + } + + // Join strings where one suffix matches another prefix. + for { + // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], + // maximizing overlap length k. + besti := -1 + bestj := -1 + bestk := 0 + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i == j { + continue + } + for k := bestk + 1; k <= len(s) && k <= len(t); k++ { + if s[len(s)-k:] == t[:k] { + besti = i + bestj = j + bestk = k + } + } + } + } + if bestk > 0 { + layout[besti] += layout[bestj][bestk:] + layout[bestj] = "" + continue + } + break + } + + text := strings.Join(layout, "") + + atom := map[string]uint32{} + for _, s := range all { + off := strings.Index(text, s) + if off < 0 { + panic("lost string " + s) + } + atom[s] = uint32(off<<8 | len(s)) + } + + // Generate the Go code. + fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n") + fmt.Printf("package atom\n\nconst (\n") + for _, s := range all { + fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s]) + } + fmt.Printf(")\n\n") + + fmt.Printf("const hash0 = %#x\n\n", best.h0) + fmt.Printf("const maxAtomLen = %d\n\n", maxLen) + + fmt.Printf("var table = [1<<%d]Atom{\n", best.k) + for i, s := range best.tab { + if s == "" { + continue + } + fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s) + } + fmt.Printf("}\n") + datasize := (1 << best.k) * 4 + + fmt.Printf("const atomText =\n") + textsize := len(text) + for len(text) > 60 { + fmt.Printf("\t%q +\n", text[:60]) + text = text[60:] + } + fmt.Printf("\t%q\n\n", text) + + fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) +} + +type byLen []string + +func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } +func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x byLen) Len() int { return len(x) } + +// fnv computes the FNV hash with an arbitrary starting value h. +func fnv(h uint32, s string) uint32 { + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// A table represents an attempt at constructing the lookup table. +// The lookup table uses cuckoo hashing, meaning that each string +// can be found in one of two positions. +type table struct { + h0 uint32 + k uint + mask uint32 + tab []string +} + +// hash returns the two hashes for s. +func (t *table) hash(s string) (h1, h2 uint32) { + h := fnv(t.h0, s) + h1 = h & t.mask + h2 = (h >> 16) & t.mask + return +} + +// init initializes the table with the given parameters. +// h0 is the initial hash value, +// k is the number of bits of hash value to use, and +// x is the list of strings to store in the table. +// init returns false if the table cannot be constructed. +func (t *table) init(h0 uint32, k uint, x []string) bool { + t.h0 = h0 + t.k = k + t.tab = make([]string, 1< len(t.tab) { + return false + } + s := t.tab[i] + h1, h2 := t.hash(s) + j := h1 + h2 - i + if t.tab[j] != "" && !t.push(j, depth+1) { + return false + } + t.tab[j] = s + return true +} + +// The lists of element names and attribute keys were taken from +// https://html.spec.whatwg.org/multipage/indices.html#index +// as of the "HTML Living Standard - Last Updated 21 February 2015" version. + +var elements = []string{ + "a", + "abbr", + "address", + "area", + "article", + "aside", + "audio", + "b", + "base", + "bdi", + "bdo", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "cite", + "code", + "col", + "colgroup", + "command", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "map", + "mark", + "menu", + "menuitem", + "meta", + "meter", + "nav", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "small", + "source", + "span", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "u", + "ul", + "var", + "video", + "wbr", +} + +// https://html.spec.whatwg.org/multipage/indices.html#attributes-3 + +var attributes = []string{ + "abbr", + "accept", + "accept-charset", + "accesskey", + "action", + "alt", + "async", + "autocomplete", + "autofocus", + "autoplay", + "challenge", + "charset", + "checked", + "cite", + "class", + "cols", + "colspan", + "command", + "content", + "contenteditable", + "contextmenu", + "controls", + "coords", + "crossorigin", + "data", + "datetime", + "default", + "defer", + "dir", + "dirname", + "disabled", + "download", + "draggable", + "dropzone", + "enctype", + "for", + "form", + "formaction", + "formenctype", + "formmethod", + "formnovalidate", + "formtarget", + "headers", + "height", + "hidden", + "high", + "href", + "hreflang", + "http-equiv", + "icon", + "id", + "inputmode", + "ismap", + "itemid", + "itemprop", + "itemref", + "itemscope", + "itemtype", + "keytype", + "kind", + "label", + "lang", + "list", + "loop", + "low", + "manifest", + "max", + "maxlength", + "media", + "mediagroup", + "method", + "min", + "minlength", + "multiple", + "muted", + "name", + "novalidate", + "open", + "optimum", + "pattern", + "ping", + "placeholder", + "poster", + "preload", + "radiogroup", + "readonly", + "rel", + "required", + "reversed", + "rows", + "rowspan", + "sandbox", + "spellcheck", + "scope", + "scoped", + "seamless", + "selected", + "shape", + "size", + "sizes", + "sortable", + "sorted", + "span", + "src", + "srcdoc", + "srclang", + "start", + "step", + "style", + "tabindex", + "target", + "title", + "translate", + "type", + "typemustmatch", + "usemap", + "value", + "width", + "wrap", +} + +var eventHandlers = []string{ + "onabort", + "onautocomplete", + "onautocompleteerror", + "onafterprint", + "onbeforeprint", + "onbeforeunload", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncuechange", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "onhashchange", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onlanguagechange", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadstart", + "onmessage", + "onmousedown", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onoffline", + "ononline", + "onpagehide", + "onpageshow", + "onpause", + "onplay", + "onplaying", + "onpopstate", + "onprogress", + "onratechange", + "onreset", + "onresize", + "onscroll", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onsort", + "onstalled", + "onstorage", + "onsubmit", + "onsuspend", + "ontimeupdate", + "ontoggle", + "onunload", + "onvolumechange", + "onwaiting", +} + +// extra are ad-hoc values not covered by any of the lists above. +var extra = []string{ + "align", + "annotation", + "annotation-xml", + "applet", + "basefont", + "bgsound", + "big", + "blink", + "center", + "color", + "desc", + "face", + "font", + "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. + "foreignobject", + "frame", + "frameset", + "image", + "isindex", + "listing", + "malignmark", + "marquee", + "math", + "mglyph", + "mi", + "mn", + "mo", + "ms", + "mtext", + "nobr", + "noembed", + "noframes", + "plaintext", + "prompt", + "public", + "spacer", + "strike", + "svg", + "system", + "tt", + "xmp", +} diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go new file mode 100644 index 000000000..2605ba310 --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/table.go @@ -0,0 +1,713 @@ +// generated by go run gen.go; DO NOT EDIT + +package atom + +const ( + A Atom = 0x1 + Abbr Atom = 0x4 + Accept Atom = 0x2106 + AcceptCharset Atom = 0x210e + Accesskey Atom = 0x3309 + Action Atom = 0x1f606 + Address Atom = 0x4f307 + Align Atom = 0x1105 + Alt Atom = 0x4503 + Annotation Atom = 0x1670a + AnnotationXml Atom = 0x1670e + Applet Atom = 0x2b306 + Area Atom = 0x2fa04 + Article Atom = 0x38807 + Aside Atom = 0x8305 + Async Atom = 0x7b05 + Audio Atom = 0xa605 + Autocomplete Atom = 0x1fc0c + Autofocus Atom = 0xb309 + Autoplay Atom = 0xce08 + B Atom = 0x101 + Base Atom = 0xd604 + Basefont Atom = 0xd608 + Bdi Atom = 0x1a03 + Bdo Atom = 0xe703 + Bgsound Atom = 0x11807 + Big Atom = 0x12403 + Blink Atom = 0x12705 + Blockquote Atom = 0x12c0a + Body Atom = 0x2f04 + Br Atom = 0x202 + Button Atom = 0x13606 + Canvas Atom = 0x7f06 + Caption Atom = 0x1bb07 + Center Atom = 0x5b506 + Challenge Atom = 0x21f09 + Charset Atom = 0x2807 + Checked Atom = 0x32807 + Cite Atom = 0x3c804 + Class Atom = 0x4de05 + Code Atom = 0x14904 + Col Atom = 0x15003 + Colgroup Atom = 0x15008 + Color Atom = 0x15d05 + Cols Atom = 0x16204 + Colspan Atom = 0x16207 + Command Atom = 0x17507 + Content Atom = 0x42307 + Contenteditable Atom = 0x4230f + Contextmenu Atom = 0x3310b + Controls Atom = 0x18808 + Coords Atom = 0x19406 + Crossorigin Atom = 0x19f0b + Data Atom = 0x44a04 + Datalist Atom = 0x44a08 + Datetime Atom = 0x23c08 + Dd Atom = 0x26702 + Default Atom = 0x8607 + Defer Atom = 0x14b05 + Del Atom = 0x3ef03 + Desc Atom = 0x4db04 + Details Atom = 0x4807 + Dfn Atom = 0x6103 + Dialog Atom = 0x1b06 + Dir Atom = 0x6903 + Dirname Atom = 0x6907 + Disabled Atom = 0x10c08 + Div Atom = 0x11303 + Dl Atom = 0x11e02 + Download Atom = 0x40008 + Draggable Atom = 0x17b09 + Dropzone Atom = 0x39108 + Dt Atom = 0x50902 + Em Atom = 0x6502 + Embed Atom = 0x6505 + Enctype Atom = 0x21107 + Face Atom = 0x5b304 + Fieldset Atom = 0x1b008 + Figcaption Atom = 0x1b80a + Figure Atom = 0x1cc06 + Font Atom = 0xda04 + Footer Atom = 0x8d06 + For Atom = 0x1d803 + ForeignObject Atom = 0x1d80d + Foreignobject Atom = 0x1e50d + Form Atom = 0x1f204 + Formaction Atom = 0x1f20a + Formenctype Atom = 0x20d0b + Formmethod Atom = 0x2280a + Formnovalidate Atom = 0x2320e + Formtarget Atom = 0x2470a + Frame Atom = 0x9a05 + Frameset Atom = 0x9a08 + H1 Atom = 0x26e02 + H2 Atom = 0x29402 + H3 Atom = 0x2a702 + H4 Atom = 0x2e902 + H5 Atom = 0x2f302 + H6 Atom = 0x50b02 + Head Atom = 0x2d504 + Header Atom = 0x2d506 + Headers Atom = 0x2d507 + Height Atom = 0x25106 + Hgroup Atom = 0x25906 + Hidden Atom = 0x26506 + High Atom = 0x26b04 + Hr Atom = 0x27002 + Href Atom = 0x27004 + Hreflang Atom = 0x27008 + Html Atom = 0x25504 + HttpEquiv Atom = 0x2780a + I Atom = 0x601 + Icon Atom = 0x42204 + Id Atom = 0x8502 + Iframe Atom = 0x29606 + Image Atom = 0x29c05 + Img Atom = 0x2a103 + Input Atom = 0x3e805 + Inputmode Atom = 0x3e809 + Ins Atom = 0x1a803 + Isindex Atom = 0x2a907 + Ismap Atom = 0x2b005 + Itemid Atom = 0x33c06 + Itemprop Atom = 0x3c908 + Itemref Atom = 0x5ad07 + Itemscope Atom = 0x2b909 + Itemtype Atom = 0x2c308 + Kbd Atom = 0x1903 + Keygen Atom = 0x3906 + Keytype Atom = 0x53707 + Kind Atom = 0x10904 + Label Atom = 0xf005 + Lang Atom = 0x27404 + Legend Atom = 0x18206 + Li Atom = 0x1202 + Link Atom = 0x12804 + List Atom = 0x44e04 + Listing Atom = 0x44e07 + Loop Atom = 0xf404 + Low Atom = 0x11f03 + Malignmark Atom = 0x100a + Manifest Atom = 0x5f108 + Map Atom = 0x2b203 + Mark Atom = 0x1604 + Marquee Atom = 0x2cb07 + Math Atom = 0x2d204 + Max Atom = 0x2e103 + Maxlength Atom = 0x2e109 + Media Atom = 0x6e05 + Mediagroup Atom = 0x6e0a + Menu Atom = 0x33804 + Menuitem Atom = 0x33808 + Meta Atom = 0x45d04 + Meter Atom = 0x24205 + Method Atom = 0x22c06 + Mglyph Atom = 0x2a206 + Mi Atom = 0x2eb02 + Min Atom = 0x2eb03 + Minlength Atom = 0x2eb09 + Mn Atom = 0x23502 + Mo Atom = 0x3ed02 + Ms Atom = 0x2bc02 + Mtext Atom = 0x2f505 + Multiple Atom = 0x30308 + Muted Atom = 0x30b05 + Name Atom = 0x6c04 + Nav Atom = 0x3e03 + Nobr Atom = 0x5704 + Noembed Atom = 0x6307 + Noframes Atom = 0x9808 + Noscript Atom = 0x3d208 + Novalidate Atom = 0x2360a + Object Atom = 0x1ec06 + Ol Atom = 0xc902 + Onabort Atom = 0x13a07 + Onafterprint Atom = 0x1c00c + Onautocomplete Atom = 0x1fa0e + Onautocompleteerror Atom = 0x1fa13 + Onbeforeprint Atom = 0x6040d + Onbeforeunload Atom = 0x4e70e + Onblur Atom = 0xaa06 + Oncancel Atom = 0xe908 + Oncanplay Atom = 0x28509 + Oncanplaythrough Atom = 0x28510 + Onchange Atom = 0x3a708 + Onclick Atom = 0x31007 + Onclose Atom = 0x31707 + Oncontextmenu Atom = 0x32f0d + Oncuechange Atom = 0x3420b + Ondblclick Atom = 0x34d0a + Ondrag Atom = 0x35706 + Ondragend Atom = 0x35709 + Ondragenter Atom = 0x3600b + Ondragleave Atom = 0x36b0b + Ondragover Atom = 0x3760a + Ondragstart Atom = 0x3800b + Ondrop Atom = 0x38f06 + Ondurationchange Atom = 0x39f10 + Onemptied Atom = 0x39609 + Onended Atom = 0x3af07 + Onerror Atom = 0x3b607 + Onfocus Atom = 0x3bd07 + Onhashchange Atom = 0x3da0c + Oninput Atom = 0x3e607 + Oninvalid Atom = 0x3f209 + Onkeydown Atom = 0x3fb09 + Onkeypress Atom = 0x4080a + Onkeyup Atom = 0x41807 + Onlanguagechange Atom = 0x43210 + Onload Atom = 0x44206 + Onloadeddata Atom = 0x4420c + Onloadedmetadata Atom = 0x45510 + Onloadstart Atom = 0x46b0b + Onmessage Atom = 0x47609 + Onmousedown Atom = 0x47f0b + Onmousemove Atom = 0x48a0b + Onmouseout Atom = 0x4950a + Onmouseover Atom = 0x4a20b + Onmouseup Atom = 0x4ad09 + Onmousewheel Atom = 0x4b60c + Onoffline Atom = 0x4c209 + Ononline Atom = 0x4cb08 + Onpagehide Atom = 0x4d30a + Onpageshow Atom = 0x4fe0a + Onpause Atom = 0x50d07 + Onplay Atom = 0x51706 + Onplaying Atom = 0x51709 + Onpopstate Atom = 0x5200a + Onprogress Atom = 0x52a0a + Onratechange Atom = 0x53e0c + Onreset Atom = 0x54a07 + Onresize Atom = 0x55108 + Onscroll Atom = 0x55f08 + Onseeked Atom = 0x56708 + Onseeking Atom = 0x56f09 + Onselect Atom = 0x57808 + Onshow Atom = 0x58206 + Onsort Atom = 0x58b06 + Onstalled Atom = 0x59509 + Onstorage Atom = 0x59e09 + Onsubmit Atom = 0x5a708 + Onsuspend Atom = 0x5bb09 + Ontimeupdate Atom = 0xdb0c + Ontoggle Atom = 0x5c408 + Onunload Atom = 0x5cc08 + Onvolumechange Atom = 0x5d40e + Onwaiting Atom = 0x5e209 + Open Atom = 0x3cf04 + Optgroup Atom = 0xf608 + Optimum Atom = 0x5eb07 + Option Atom = 0x60006 + Output Atom = 0x49c06 + P Atom = 0xc01 + Param Atom = 0xc05 + Pattern Atom = 0x5107 + Ping Atom = 0x7704 + Placeholder Atom = 0xc30b + Plaintext Atom = 0xfd09 + Poster Atom = 0x15706 + Pre Atom = 0x25e03 + Preload Atom = 0x25e07 + Progress Atom = 0x52c08 + Prompt Atom = 0x5fa06 + Public Atom = 0x41e06 + Q Atom = 0x13101 + Radiogroup Atom = 0x30a + Readonly Atom = 0x2fb08 + Rel Atom = 0x25f03 + Required Atom = 0x1d008 + Reversed Atom = 0x5a08 + Rows Atom = 0x9204 + Rowspan Atom = 0x9207 + Rp Atom = 0x1c602 + Rt Atom = 0x13f02 + Ruby Atom = 0xaf04 + S Atom = 0x2c01 + Samp Atom = 0x4e04 + Sandbox Atom = 0xbb07 + Scope Atom = 0x2bd05 + Scoped Atom = 0x2bd06 + Script Atom = 0x3d406 + Seamless Atom = 0x31c08 + Section Atom = 0x4e207 + Select Atom = 0x57a06 + Selected Atom = 0x57a08 + Shape Atom = 0x4f905 + Size Atom = 0x55504 + Sizes Atom = 0x55505 + Small Atom = 0x18f05 + Sortable Atom = 0x58d08 + Sorted Atom = 0x19906 + Source Atom = 0x1aa06 + Spacer Atom = 0x2db06 + Span Atom = 0x9504 + Spellcheck Atom = 0x3230a + Src Atom = 0x3c303 + Srcdoc Atom = 0x3c306 + Srclang Atom = 0x41107 + Start Atom = 0x38605 + Step Atom = 0x5f704 + Strike Atom = 0x53306 + Strong Atom = 0x55906 + Style Atom = 0x61105 + Sub Atom = 0x5a903 + Summary Atom = 0x61607 + Sup Atom = 0x61d03 + Svg Atom = 0x62003 + System Atom = 0x62306 + Tabindex Atom = 0x46308 + Table Atom = 0x42d05 + Target Atom = 0x24b06 + Tbody Atom = 0x2e05 + Td Atom = 0x4702 + Template Atom = 0x62608 + Textarea Atom = 0x2f608 + Tfoot Atom = 0x8c05 + Th Atom = 0x22e02 + Thead Atom = 0x2d405 + Time Atom = 0xdd04 + Title Atom = 0xa105 + Tr Atom = 0x10502 + Track Atom = 0x10505 + Translate Atom = 0x14009 + Tt Atom = 0x5302 + Type Atom = 0x21404 + Typemustmatch Atom = 0x2140d + U Atom = 0xb01 + Ul Atom = 0x8a02 + Usemap Atom = 0x51106 + Value Atom = 0x4005 + Var Atom = 0x11503 + Video Atom = 0x28105 + Wbr Atom = 0x12103 + Width Atom = 0x50705 + Wrap Atom = 0x58704 + Xmp Atom = 0xc103 +) + +const hash0 = 0xc17da63e + +const maxAtomLen = 19 + +var table = [1 << 9]Atom{ + 0x1: 0x48a0b, // onmousemove + 0x2: 0x5e209, // onwaiting + 0x3: 0x1fa13, // onautocompleteerror + 0x4: 0x5fa06, // prompt + 0x7: 0x5eb07, // optimum + 0x8: 0x1604, // mark + 0xa: 0x5ad07, // itemref + 0xb: 0x4fe0a, // onpageshow + 0xc: 0x57a06, // select + 0xd: 0x17b09, // draggable + 0xe: 0x3e03, // nav + 0xf: 0x17507, // command + 0x11: 0xb01, // u + 0x14: 0x2d507, // headers + 0x15: 0x44a08, // datalist + 0x17: 0x4e04, // samp + 0x1a: 0x3fb09, // onkeydown + 0x1b: 0x55f08, // onscroll + 0x1c: 0x15003, // col + 0x20: 0x3c908, // itemprop + 0x21: 0x2780a, // http-equiv + 0x22: 0x61d03, // sup + 0x24: 0x1d008, // required + 0x2b: 0x25e07, // preload + 0x2c: 0x6040d, // onbeforeprint + 0x2d: 0x3600b, // ondragenter + 0x2e: 0x50902, // dt + 0x2f: 0x5a708, // onsubmit + 0x30: 0x27002, // hr + 0x31: 0x32f0d, // oncontextmenu + 0x33: 0x29c05, // image + 0x34: 0x50d07, // onpause + 0x35: 0x25906, // hgroup + 0x36: 0x7704, // ping + 0x37: 0x57808, // onselect + 0x3a: 0x11303, // div + 0x3b: 0x1fa0e, // onautocomplete + 0x40: 0x2eb02, // mi + 0x41: 0x31c08, // seamless + 0x42: 0x2807, // charset + 0x43: 0x8502, // id + 0x44: 0x5200a, // onpopstate + 0x45: 0x3ef03, // del + 0x46: 0x2cb07, // marquee + 0x47: 0x3309, // accesskey + 0x49: 0x8d06, // footer + 0x4a: 0x44e04, // list + 0x4b: 0x2b005, // ismap + 0x51: 0x33804, // menu + 0x52: 0x2f04, // body + 0x55: 0x9a08, // frameset + 0x56: 0x54a07, // onreset + 0x57: 0x12705, // blink + 0x58: 0xa105, // title + 0x59: 0x38807, // article + 0x5b: 0x22e02, // th + 0x5d: 0x13101, // q + 0x5e: 0x3cf04, // open + 0x5f: 0x2fa04, // area + 0x61: 0x44206, // onload + 0x62: 0xda04, // font + 0x63: 0xd604, // base + 0x64: 0x16207, // colspan + 0x65: 0x53707, // keytype + 0x66: 0x11e02, // dl + 0x68: 0x1b008, // fieldset + 0x6a: 0x2eb03, // min + 0x6b: 0x11503, // var + 0x6f: 0x2d506, // header + 0x70: 0x13f02, // rt + 0x71: 0x15008, // colgroup + 0x72: 0x23502, // mn + 0x74: 0x13a07, // onabort + 0x75: 0x3906, // keygen + 0x76: 0x4c209, // onoffline + 0x77: 0x21f09, // challenge + 0x78: 0x2b203, // map + 0x7a: 0x2e902, // h4 + 0x7b: 0x3b607, // onerror + 0x7c: 0x2e109, // maxlength + 0x7d: 0x2f505, // mtext + 0x7e: 0xbb07, // sandbox + 0x7f: 0x58b06, // onsort + 0x80: 0x100a, // malignmark + 0x81: 0x45d04, // meta + 0x82: 0x7b05, // async + 0x83: 0x2a702, // h3 + 0x84: 0x26702, // dd + 0x85: 0x27004, // href + 0x86: 0x6e0a, // mediagroup + 0x87: 0x19406, // coords + 0x88: 0x41107, // srclang + 0x89: 0x34d0a, // ondblclick + 0x8a: 0x4005, // value + 0x8c: 0xe908, // oncancel + 0x8e: 0x3230a, // spellcheck + 0x8f: 0x9a05, // frame + 0x91: 0x12403, // big + 0x94: 0x1f606, // action + 0x95: 0x6903, // dir + 0x97: 0x2fb08, // readonly + 0x99: 0x42d05, // table + 0x9a: 0x61607, // summary + 0x9b: 0x12103, // wbr + 0x9c: 0x30a, // radiogroup + 0x9d: 0x6c04, // name + 0x9f: 0x62306, // system + 0xa1: 0x15d05, // color + 0xa2: 0x7f06, // canvas + 0xa3: 0x25504, // html + 0xa5: 0x56f09, // onseeking + 0xac: 0x4f905, // shape + 0xad: 0x25f03, // rel + 0xae: 0x28510, // oncanplaythrough + 0xaf: 0x3760a, // ondragover + 0xb0: 0x62608, // template + 0xb1: 0x1d80d, // foreignObject + 0xb3: 0x9204, // rows + 0xb6: 0x44e07, // listing + 0xb7: 0x49c06, // output + 0xb9: 0x3310b, // contextmenu + 0xbb: 0x11f03, // low + 0xbc: 0x1c602, // rp + 0xbd: 0x5bb09, // onsuspend + 0xbe: 0x13606, // button + 0xbf: 0x4db04, // desc + 0xc1: 0x4e207, // section + 0xc2: 0x52a0a, // onprogress + 0xc3: 0x59e09, // onstorage + 0xc4: 0x2d204, // math + 0xc5: 0x4503, // alt + 0xc7: 0x8a02, // ul + 0xc8: 0x5107, // pattern + 0xc9: 0x4b60c, // onmousewheel + 0xca: 0x35709, // ondragend + 0xcb: 0xaf04, // ruby + 0xcc: 0xc01, // p + 0xcd: 0x31707, // onclose + 0xce: 0x24205, // meter + 0xcf: 0x11807, // bgsound + 0xd2: 0x25106, // height + 0xd4: 0x101, // b + 0xd5: 0x2c308, // itemtype + 0xd8: 0x1bb07, // caption + 0xd9: 0x10c08, // disabled + 0xdb: 0x33808, // menuitem + 0xdc: 0x62003, // svg + 0xdd: 0x18f05, // small + 0xde: 0x44a04, // data + 0xe0: 0x4cb08, // ononline + 0xe1: 0x2a206, // mglyph + 0xe3: 0x6505, // embed + 0xe4: 0x10502, // tr + 0xe5: 0x46b0b, // onloadstart + 0xe7: 0x3c306, // srcdoc + 0xeb: 0x5c408, // ontoggle + 0xed: 0xe703, // bdo + 0xee: 0x4702, // td + 0xef: 0x8305, // aside + 0xf0: 0x29402, // h2 + 0xf1: 0x52c08, // progress + 0xf2: 0x12c0a, // blockquote + 0xf4: 0xf005, // label + 0xf5: 0x601, // i + 0xf7: 0x9207, // rowspan + 0xfb: 0x51709, // onplaying + 0xfd: 0x2a103, // img + 0xfe: 0xf608, // optgroup + 0xff: 0x42307, // content + 0x101: 0x53e0c, // onratechange + 0x103: 0x3da0c, // onhashchange + 0x104: 0x4807, // details + 0x106: 0x40008, // download + 0x109: 0x14009, // translate + 0x10b: 0x4230f, // contenteditable + 0x10d: 0x36b0b, // ondragleave + 0x10e: 0x2106, // accept + 0x10f: 0x57a08, // selected + 0x112: 0x1f20a, // formaction + 0x113: 0x5b506, // center + 0x115: 0x45510, // onloadedmetadata + 0x116: 0x12804, // link + 0x117: 0xdd04, // time + 0x118: 0x19f0b, // crossorigin + 0x119: 0x3bd07, // onfocus + 0x11a: 0x58704, // wrap + 0x11b: 0x42204, // icon + 0x11d: 0x28105, // video + 0x11e: 0x4de05, // class + 0x121: 0x5d40e, // onvolumechange + 0x122: 0xaa06, // onblur + 0x123: 0x2b909, // itemscope + 0x124: 0x61105, // style + 0x127: 0x41e06, // public + 0x129: 0x2320e, // formnovalidate + 0x12a: 0x58206, // onshow + 0x12c: 0x51706, // onplay + 0x12d: 0x3c804, // cite + 0x12e: 0x2bc02, // ms + 0x12f: 0xdb0c, // ontimeupdate + 0x130: 0x10904, // kind + 0x131: 0x2470a, // formtarget + 0x135: 0x3af07, // onended + 0x136: 0x26506, // hidden + 0x137: 0x2c01, // s + 0x139: 0x2280a, // formmethod + 0x13a: 0x3e805, // input + 0x13c: 0x50b02, // h6 + 0x13d: 0xc902, // ol + 0x13e: 0x3420b, // oncuechange + 0x13f: 0x1e50d, // foreignobject + 0x143: 0x4e70e, // onbeforeunload + 0x144: 0x2bd05, // scope + 0x145: 0x39609, // onemptied + 0x146: 0x14b05, // defer + 0x147: 0xc103, // xmp + 0x148: 0x39f10, // ondurationchange + 0x149: 0x1903, // kbd + 0x14c: 0x47609, // onmessage + 0x14d: 0x60006, // option + 0x14e: 0x2eb09, // minlength + 0x14f: 0x32807, // checked + 0x150: 0xce08, // autoplay + 0x152: 0x202, // br + 0x153: 0x2360a, // novalidate + 0x156: 0x6307, // noembed + 0x159: 0x31007, // onclick + 0x15a: 0x47f0b, // onmousedown + 0x15b: 0x3a708, // onchange + 0x15e: 0x3f209, // oninvalid + 0x15f: 0x2bd06, // scoped + 0x160: 0x18808, // controls + 0x161: 0x30b05, // muted + 0x162: 0x58d08, // sortable + 0x163: 0x51106, // usemap + 0x164: 0x1b80a, // figcaption + 0x165: 0x35706, // ondrag + 0x166: 0x26b04, // high + 0x168: 0x3c303, // src + 0x169: 0x15706, // poster + 0x16b: 0x1670e, // annotation-xml + 0x16c: 0x5f704, // step + 0x16d: 0x4, // abbr + 0x16e: 0x1b06, // dialog + 0x170: 0x1202, // li + 0x172: 0x3ed02, // mo + 0x175: 0x1d803, // for + 0x176: 0x1a803, // ins + 0x178: 0x55504, // size + 0x179: 0x43210, // onlanguagechange + 0x17a: 0x8607, // default + 0x17b: 0x1a03, // bdi + 0x17c: 0x4d30a, // onpagehide + 0x17d: 0x6907, // dirname + 0x17e: 0x21404, // type + 0x17f: 0x1f204, // form + 0x181: 0x28509, // oncanplay + 0x182: 0x6103, // dfn + 0x183: 0x46308, // tabindex + 0x186: 0x6502, // em + 0x187: 0x27404, // lang + 0x189: 0x39108, // dropzone + 0x18a: 0x4080a, // onkeypress + 0x18b: 0x23c08, // datetime + 0x18c: 0x16204, // cols + 0x18d: 0x1, // a + 0x18e: 0x4420c, // onloadeddata + 0x190: 0xa605, // audio + 0x192: 0x2e05, // tbody + 0x193: 0x22c06, // method + 0x195: 0xf404, // loop + 0x196: 0x29606, // iframe + 0x198: 0x2d504, // head + 0x19e: 0x5f108, // manifest + 0x19f: 0xb309, // autofocus + 0x1a0: 0x14904, // code + 0x1a1: 0x55906, // strong + 0x1a2: 0x30308, // multiple + 0x1a3: 0xc05, // param + 0x1a6: 0x21107, // enctype + 0x1a7: 0x5b304, // face + 0x1a8: 0xfd09, // plaintext + 0x1a9: 0x26e02, // h1 + 0x1aa: 0x59509, // onstalled + 0x1ad: 0x3d406, // script + 0x1ae: 0x2db06, // spacer + 0x1af: 0x55108, // onresize + 0x1b0: 0x4a20b, // onmouseover + 0x1b1: 0x5cc08, // onunload + 0x1b2: 0x56708, // onseeked + 0x1b4: 0x2140d, // typemustmatch + 0x1b5: 0x1cc06, // figure + 0x1b6: 0x4950a, // onmouseout + 0x1b7: 0x25e03, // pre + 0x1b8: 0x50705, // width + 0x1b9: 0x19906, // sorted + 0x1bb: 0x5704, // nobr + 0x1be: 0x5302, // tt + 0x1bf: 0x1105, // align + 0x1c0: 0x3e607, // oninput + 0x1c3: 0x41807, // onkeyup + 0x1c6: 0x1c00c, // onafterprint + 0x1c7: 0x210e, // accept-charset + 0x1c8: 0x33c06, // itemid + 0x1c9: 0x3e809, // inputmode + 0x1cb: 0x53306, // strike + 0x1cc: 0x5a903, // sub + 0x1cd: 0x10505, // track + 0x1ce: 0x38605, // start + 0x1d0: 0xd608, // basefont + 0x1d6: 0x1aa06, // source + 0x1d7: 0x18206, // legend + 0x1d8: 0x2d405, // thead + 0x1da: 0x8c05, // tfoot + 0x1dd: 0x1ec06, // object + 0x1de: 0x6e05, // media + 0x1df: 0x1670a, // annotation + 0x1e0: 0x20d0b, // formenctype + 0x1e2: 0x3d208, // noscript + 0x1e4: 0x55505, // sizes + 0x1e5: 0x1fc0c, // autocomplete + 0x1e6: 0x9504, // span + 0x1e7: 0x9808, // noframes + 0x1e8: 0x24b06, // target + 0x1e9: 0x38f06, // ondrop + 0x1ea: 0x2b306, // applet + 0x1ec: 0x5a08, // reversed + 0x1f0: 0x2a907, // isindex + 0x1f3: 0x27008, // hreflang + 0x1f5: 0x2f302, // h5 + 0x1f6: 0x4f307, // address + 0x1fa: 0x2e103, // max + 0x1fb: 0xc30b, // placeholder + 0x1fc: 0x2f608, // textarea + 0x1fe: 0x4ad09, // onmouseup + 0x1ff: 0x3800b, // ondragstart +} + +const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" + + "genavaluealtdetailsampatternobreversedfnoembedirnamediagroup" + + "ingasyncanvasidefaultfooterowspanoframesetitleaudionblurubya" + + "utofocusandboxmplaceholderautoplaybasefontimeupdatebdoncance" + + "labelooptgrouplaintextrackindisabledivarbgsoundlowbrbigblink" + + "blockquotebuttonabortranslatecodefercolgroupostercolorcolspa" + + "nnotation-xmlcommandraggablegendcontrolsmallcoordsortedcross" + + "originsourcefieldsetfigcaptionafterprintfigurequiredforeignO" + + "bjectforeignobjectformactionautocompleteerrorformenctypemust" + + "matchallengeformmethodformnovalidatetimeterformtargetheightm" + + "lhgroupreloadhiddenhigh1hreflanghttp-equivideoncanplaythroug" + + "h2iframeimageimglyph3isindexismappletitemscopeditemtypemarqu" + + "eematheaderspacermaxlength4minlength5mtextareadonlymultiplem" + + "utedonclickoncloseamlesspellcheckedoncontextmenuitemidoncuec" + + "hangeondblclickondragendondragenterondragleaveondragoverondr" + + "agstarticleondropzonemptiedondurationchangeonendedonerroronf" + + "ocusrcdocitempropenoscriptonhashchangeoninputmodeloninvalido" + + "nkeydownloadonkeypressrclangonkeyupublicontenteditableonlang" + + "uagechangeonloadeddatalistingonloadedmetadatabindexonloadsta" + + "rtonmessageonmousedownonmousemoveonmouseoutputonmouseoveronm" + + "ouseuponmousewheelonofflineononlineonpagehidesclassectionbef" + + "oreunloaddresshapeonpageshowidth6onpausemaponplayingonpopsta" + + "teonprogresstrikeytypeonratechangeonresetonresizestrongonscr" + + "ollonseekedonseekingonselectedonshowraponsortableonstalledon" + + "storageonsubmitemrefacenteronsuspendontoggleonunloadonvolume" + + "changeonwaitingoptimumanifestepromptoptionbeforeprintstylesu" + + "mmarysupsvgsystemplate" diff --git a/vendor/golang.org/x/net/html/charset/charset.go b/vendor/golang.org/x/net/html/charset/charset.go new file mode 100644 index 000000000..449607253 --- /dev/null +++ b/vendor/golang.org/x/net/html/charset/charset.go @@ -0,0 +1,257 @@ +// Copyright 2013 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. + +// Package charset provides common text encodings for HTML documents. +// +// The mapping from encoding labels to encodings is defined at +// https://encoding.spec.whatwg.org/. +package charset + +import ( + "bytes" + "fmt" + "io" + "mime" + "strings" + "unicode/utf8" + + "golang.org/x/net/html" + "golang.org/x/text/encoding" + "golang.org/x/text/encoding/charmap" + "golang.org/x/text/encoding/htmlindex" + "golang.org/x/text/transform" +) + +// Lookup returns the encoding with the specified label, and its canonical +// name. It returns nil and the empty string if label is not one of the +// standard encodings for HTML. Matching is case-insensitive and ignores +// leading and trailing whitespace. Encoders will use HTML escape sequences for +// runes that are not supported by the character set. +func Lookup(label string) (e encoding.Encoding, name string) { + e, err := htmlindex.Get(label) + if err != nil { + return nil, "" + } + name, _ = htmlindex.Name(e) + return &htmlEncoding{e}, name +} + +type htmlEncoding struct{ encoding.Encoding } + +func (h *htmlEncoding) NewEncoder() *encoding.Encoder { + // HTML requires a non-terminating legacy encoder. We use HTML escapes to + // substitute unsupported code points. + return encoding.HTMLEscapeUnsupported(h.Encoding.NewEncoder()) +} + +// DetermineEncoding determines the encoding of an HTML document by examining +// up to the first 1024 bytes of content and the declared Content-Type. +// +// See http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#determining-the-character-encoding +func DetermineEncoding(content []byte, contentType string) (e encoding.Encoding, name string, certain bool) { + if len(content) > 1024 { + content = content[:1024] + } + + for _, b := range boms { + if bytes.HasPrefix(content, b.bom) { + e, name = Lookup(b.enc) + return e, name, true + } + } + + if _, params, err := mime.ParseMediaType(contentType); err == nil { + if cs, ok := params["charset"]; ok { + if e, name = Lookup(cs); e != nil { + return e, name, true + } + } + } + + if len(content) > 0 { + e, name = prescan(content) + if e != nil { + return e, name, false + } + } + + // Try to detect UTF-8. + // First eliminate any partial rune at the end. + for i := len(content) - 1; i >= 0 && i > len(content)-4; i-- { + b := content[i] + if b < 0x80 { + break + } + if utf8.RuneStart(b) { + content = content[:i] + break + } + } + hasHighBit := false + for _, c := range content { + if c >= 0x80 { + hasHighBit = true + break + } + } + if hasHighBit && utf8.Valid(content) { + return encoding.Nop, "utf-8", false + } + + // TODO: change default depending on user's locale? + return charmap.Windows1252, "windows-1252", false +} + +// NewReader returns an io.Reader that converts the content of r to UTF-8. +// It calls DetermineEncoding to find out what r's encoding is. +func NewReader(r io.Reader, contentType string) (io.Reader, error) { + preview := make([]byte, 1024) + n, err := io.ReadFull(r, preview) + switch { + case err == io.ErrUnexpectedEOF: + preview = preview[:n] + r = bytes.NewReader(preview) + case err != nil: + return nil, err + default: + r = io.MultiReader(bytes.NewReader(preview), r) + } + + if e, _, _ := DetermineEncoding(preview, contentType); e != encoding.Nop { + r = transform.NewReader(r, e.NewDecoder()) + } + return r, nil +} + +// NewReaderLabel returns a reader that converts from the specified charset to +// UTF-8. It uses Lookup to find the encoding that corresponds to label, and +// returns an error if Lookup returns nil. It is suitable for use as +// encoding/xml.Decoder's CharsetReader function. +func NewReaderLabel(label string, input io.Reader) (io.Reader, error) { + e, _ := Lookup(label) + if e == nil { + return nil, fmt.Errorf("unsupported charset: %q", label) + } + return transform.NewReader(input, e.NewDecoder()), nil +} + +func prescan(content []byte) (e encoding.Encoding, name string) { + z := html.NewTokenizer(bytes.NewReader(content)) + for { + switch z.Next() { + case html.ErrorToken: + return nil, "" + + case html.StartTagToken, html.SelfClosingTagToken: + tagName, hasAttr := z.TagName() + if !bytes.Equal(tagName, []byte("meta")) { + continue + } + attrList := make(map[string]bool) + gotPragma := false + + const ( + dontKnow = iota + doNeedPragma + doNotNeedPragma + ) + needPragma := dontKnow + + name = "" + e = nil + for hasAttr { + var key, val []byte + key, val, hasAttr = z.TagAttr() + ks := string(key) + if attrList[ks] { + continue + } + attrList[ks] = true + for i, c := range val { + if 'A' <= c && c <= 'Z' { + val[i] = c + 0x20 + } + } + + switch ks { + case "http-equiv": + if bytes.Equal(val, []byte("content-type")) { + gotPragma = true + } + + case "content": + if e == nil { + name = fromMetaElement(string(val)) + if name != "" { + e, name = Lookup(name) + if e != nil { + needPragma = doNeedPragma + } + } + } + + case "charset": + e, name = Lookup(string(val)) + needPragma = doNotNeedPragma + } + } + + if needPragma == dontKnow || needPragma == doNeedPragma && !gotPragma { + continue + } + + if strings.HasPrefix(name, "utf-16") { + name = "utf-8" + e = encoding.Nop + } + + if e != nil { + return e, name + } + } + } +} + +func fromMetaElement(s string) string { + for s != "" { + csLoc := strings.Index(s, "charset") + if csLoc == -1 { + return "" + } + s = s[csLoc+len("charset"):] + s = strings.TrimLeft(s, " \t\n\f\r") + if !strings.HasPrefix(s, "=") { + continue + } + s = s[1:] + s = strings.TrimLeft(s, " \t\n\f\r") + if s == "" { + return "" + } + if q := s[0]; q == '"' || q == '\'' { + s = s[1:] + closeQuote := strings.IndexRune(s, rune(q)) + if closeQuote == -1 { + return "" + } + return s[:closeQuote] + } + + end := strings.IndexAny(s, "; \t\n\f\r") + if end == -1 { + end = len(s) + } + return s[:end] + } + return "" +} + +var boms = []struct { + bom []byte + enc string +}{ + {[]byte{0xfe, 0xff}, "utf-16be"}, + {[]byte{0xff, 0xfe}, "utf-16le"}, + {[]byte{0xef, 0xbb, 0xbf}, "utf-8"}, +} diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go new file mode 100644 index 000000000..52f651ff6 --- /dev/null +++ b/vendor/golang.org/x/net/html/const.go @@ -0,0 +1,102 @@ +// Copyright 2011 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. + +package html + +// Section 12.2.3.2 of the HTML5 specification says "The following elements +// have varying levels of special parsing rules". +// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements +var isSpecialElementMap = map[string]bool{ + "address": true, + "applet": true, + "area": true, + "article": true, + "aside": true, + "base": true, + "basefont": true, + "bgsound": true, + "blockquote": true, + "body": true, + "br": true, + "button": true, + "caption": true, + "center": true, + "col": true, + "colgroup": true, + "dd": true, + "details": true, + "dir": true, + "div": true, + "dl": true, + "dt": true, + "embed": true, + "fieldset": true, + "figcaption": true, + "figure": true, + "footer": true, + "form": true, + "frame": true, + "frameset": true, + "h1": true, + "h2": true, + "h3": true, + "h4": true, + "h5": true, + "h6": true, + "head": true, + "header": true, + "hgroup": true, + "hr": true, + "html": true, + "iframe": true, + "img": true, + "input": true, + "isindex": true, + "li": true, + "link": true, + "listing": true, + "marquee": true, + "menu": true, + "meta": true, + "nav": true, + "noembed": true, + "noframes": true, + "noscript": true, + "object": true, + "ol": true, + "p": true, + "param": true, + "plaintext": true, + "pre": true, + "script": true, + "section": true, + "select": true, + "source": true, + "style": true, + "summary": true, + "table": true, + "tbody": true, + "td": true, + "template": true, + "textarea": true, + "tfoot": true, + "th": true, + "thead": true, + "title": true, + "tr": true, + "track": true, + "ul": true, + "wbr": true, + "xmp": true, +} + +func isSpecialElement(element *Node) bool { + switch element.Namespace { + case "", "html": + return isSpecialElementMap[element.Data] + case "svg": + return element.Data == "foreignObject" + } + return false +} diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go new file mode 100644 index 000000000..b453fe1e4 --- /dev/null +++ b/vendor/golang.org/x/net/html/doc.go @@ -0,0 +1,106 @@ +// Copyright 2010 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. + +/* +Package html implements an HTML5-compliant tokenizer and parser. + +Tokenization is done by creating a Tokenizer for an io.Reader r. It is the +caller's responsibility to ensure that r provides UTF-8 encoded HTML. + + z := html.NewTokenizer(r) + +Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), +which parses the next token and returns its type, or an error: + + for { + tt := z.Next() + if tt == html.ErrorToken { + // ... + return ... + } + // Process the current token. + } + +There are two APIs for retrieving the current token. The high-level API is to +call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs +allow optionally calling Raw after Next but before Token, Text, TagName, or +TagAttr. In EBNF notation, the valid call sequence per token is: + + Next {Raw} [ Token | Text | TagName {TagAttr} ] + +Token returns an independent data structure that completely describes a token. +Entities (such as "<") are unescaped, tag names and attribute keys are +lower-cased, and attributes are collected into a []Attribute. For example: + + for { + if z.Next() == html.ErrorToken { + // Returning io.EOF indicates success. + return z.Err() + } + emitToken(z.Token()) + } + +The low-level API performs fewer allocations and copies, but the contents of +the []byte values returned by Text, TagName and TagAttr may change on the next +call to Next. For example, to extract an HTML page's anchor text: + + depth := 0 + for { + tt := z.Next() + switch tt { + case ErrorToken: + return z.Err() + case TextToken: + if depth > 0 { + // emitBytes should copy the []byte it receives, + // if it doesn't process it immediately. + emitBytes(z.Text()) + } + case StartTagToken, EndTagToken: + tn, _ := z.TagName() + if len(tn) == 1 && tn[0] == 'a' { + if tt == StartTagToken { + depth++ + } else { + depth-- + } + } + } + } + +Parsing is done by calling Parse with an io.Reader, which returns the root of +the parse tree (the document element) as a *Node. It is the caller's +responsibility to ensure that the Reader provides UTF-8 encoded HTML. For +example, to process each anchor node in depth-first order: + + doc, err := html.Parse(r) + if err != nil { + // ... + } + var f func(*html.Node) + f = func(n *html.Node) { + if n.Type == html.ElementNode && n.Data == "a" { + // Do something with n... + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + f(c) + } + } + f(doc) + +The relevant specifications include: +https://html.spec.whatwg.org/multipage/syntax.html and +https://html.spec.whatwg.org/multipage/syntax.html#tokenization +*/ +package html + +// The tokenization algorithm implemented by this package is not a line-by-line +// transliteration of the relatively verbose state-machine in the WHATWG +// specification. A more direct approach is used instead, where the program +// counter implies the state, such as whether it is tokenizing a tag or a text +// node. Specification compliance is verified by checking expected and actual +// outputs over a test suite rather than aiming for algorithmic fidelity. + +// TODO(nigeltao): Does a DOM API belong in this package or a separate one? +// TODO(nigeltao): How does parsing interact with a JavaScript engine? diff --git a/vendor/golang.org/x/net/html/doctype.go b/vendor/golang.org/x/net/html/doctype.go new file mode 100644 index 000000000..c484e5a94 --- /dev/null +++ b/vendor/golang.org/x/net/html/doctype.go @@ -0,0 +1,156 @@ +// Copyright 2011 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. + +package html + +import ( + "strings" +) + +// parseDoctype parses the data from a DoctypeToken into a name, +// public identifier, and system identifier. It returns a Node whose Type +// is DoctypeNode, whose Data is the name, and which has attributes +// named "system" and "public" for the two identifiers if they were present. +// quirks is whether the document should be parsed in "quirks mode". +func parseDoctype(s string) (n *Node, quirks bool) { + n = &Node{Type: DoctypeNode} + + // Find the name. + space := strings.IndexAny(s, whitespace) + if space == -1 { + space = len(s) + } + n.Data = s[:space] + // The comparison to "html" is case-sensitive. + if n.Data != "html" { + quirks = true + } + n.Data = strings.ToLower(n.Data) + s = strings.TrimLeft(s[space:], whitespace) + + if len(s) < 6 { + // It can't start with "PUBLIC" or "SYSTEM". + // Ignore the rest of the string. + return n, quirks || s != "" + } + + key := strings.ToLower(s[:6]) + s = s[6:] + for key == "public" || key == "system" { + s = strings.TrimLeft(s, whitespace) + if s == "" { + break + } + quote := s[0] + if quote != '"' && quote != '\'' { + break + } + s = s[1:] + q := strings.IndexRune(s, rune(quote)) + var id string + if q == -1 { + id = s + s = "" + } else { + id = s[:q] + s = s[q+1:] + } + n.Attr = append(n.Attr, Attribute{Key: key, Val: id}) + if key == "public" { + key = "system" + } else { + key = "" + } + } + + if key != "" || s != "" { + quirks = true + } else if len(n.Attr) > 0 { + if n.Attr[0].Key == "public" { + public := strings.ToLower(n.Attr[0].Val) + switch public { + case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html": + quirks = true + default: + for _, q := range quirkyIDs { + if strings.HasPrefix(public, q) { + quirks = true + break + } + } + } + // The following two public IDs only cause quirks mode if there is no system ID. + if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") || + strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) { + quirks = true + } + } + if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && + strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { + quirks = true + } + } + + return n, quirks +} + +// quirkyIDs is a list of public doctype identifiers that cause a document +// to be interpreted in quirks mode. The identifiers should be in lower case. +var quirkyIDs = []string{ + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//", +} diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go new file mode 100644 index 000000000..a50c04c60 --- /dev/null +++ b/vendor/golang.org/x/net/html/entity.go @@ -0,0 +1,2253 @@ +// Copyright 2010 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. + +package html + +// All entities that do not end with ';' are 6 or fewer bytes long. +const longestEntityWithoutSemicolon = 6 + +// entity is a map from HTML entity names to their values. The semicolon matters: +// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references +// lists both "amp" and "amp;" as two separate entries. +// +// Note that the HTML5 list is larger than the HTML4 list at +// http://www.w3.org/TR/html4/sgml/entities.html +var entity = map[string]rune{ + "AElig;": '\U000000C6', + "AMP;": '\U00000026', + "Aacute;": '\U000000C1', + "Abreve;": '\U00000102', + "Acirc;": '\U000000C2', + "Acy;": '\U00000410', + "Afr;": '\U0001D504', + "Agrave;": '\U000000C0', + "Alpha;": '\U00000391', + "Amacr;": '\U00000100', + "And;": '\U00002A53', + "Aogon;": '\U00000104', + "Aopf;": '\U0001D538', + "ApplyFunction;": '\U00002061', + "Aring;": '\U000000C5', + "Ascr;": '\U0001D49C', + "Assign;": '\U00002254', + "Atilde;": '\U000000C3', + "Auml;": '\U000000C4', + "Backslash;": '\U00002216', + "Barv;": '\U00002AE7', + "Barwed;": '\U00002306', + "Bcy;": '\U00000411', + "Because;": '\U00002235', + "Bernoullis;": '\U0000212C', + "Beta;": '\U00000392', + "Bfr;": '\U0001D505', + "Bopf;": '\U0001D539', + "Breve;": '\U000002D8', + "Bscr;": '\U0000212C', + "Bumpeq;": '\U0000224E', + "CHcy;": '\U00000427', + "COPY;": '\U000000A9', + "Cacute;": '\U00000106', + "Cap;": '\U000022D2', + "CapitalDifferentialD;": '\U00002145', + "Cayleys;": '\U0000212D', + "Ccaron;": '\U0000010C', + "Ccedil;": '\U000000C7', + "Ccirc;": '\U00000108', + "Cconint;": '\U00002230', + "Cdot;": '\U0000010A', + "Cedilla;": '\U000000B8', + "CenterDot;": '\U000000B7', + "Cfr;": '\U0000212D', + "Chi;": '\U000003A7', + "CircleDot;": '\U00002299', + "CircleMinus;": '\U00002296', + "CirclePlus;": '\U00002295', + "CircleTimes;": '\U00002297', + "ClockwiseContourIntegral;": '\U00002232', + "CloseCurlyDoubleQuote;": '\U0000201D', + "CloseCurlyQuote;": '\U00002019', + "Colon;": '\U00002237', + "Colone;": '\U00002A74', + "Congruent;": '\U00002261', + "Conint;": '\U0000222F', + "ContourIntegral;": '\U0000222E', + "Copf;": '\U00002102', + "Coproduct;": '\U00002210', + "CounterClockwiseContourIntegral;": '\U00002233', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', +} + +// HTML entities that are two unicode codepoints. +var entity2 = map[string][2]rune{ + // TODO(nigeltao): Handle replacements that are wider than their names. + // "nLt;": {'\u226A', '\u20D2'}, + // "nGt;": {'\u226B', '\u20D2'}, + "NotEqualTilde;": {'\u2242', '\u0338'}, + "NotGreaterFullEqual;": {'\u2267', '\u0338'}, + "NotGreaterGreater;": {'\u226B', '\u0338'}, + "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'}, + "NotHumpDownHump;": {'\u224E', '\u0338'}, + "NotHumpEqual;": {'\u224F', '\u0338'}, + "NotLeftTriangleBar;": {'\u29CF', '\u0338'}, + "NotLessLess;": {'\u226A', '\u0338'}, + "NotLessSlantEqual;": {'\u2A7D', '\u0338'}, + "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'}, + "NotNestedLessLess;": {'\u2AA1', '\u0338'}, + "NotPrecedesEqual;": {'\u2AAF', '\u0338'}, + "NotRightTriangleBar;": {'\u29D0', '\u0338'}, + "NotSquareSubset;": {'\u228F', '\u0338'}, + "NotSquareSuperset;": {'\u2290', '\u0338'}, + "NotSubset;": {'\u2282', '\u20D2'}, + "NotSucceedsEqual;": {'\u2AB0', '\u0338'}, + "NotSucceedsTilde;": {'\u227F', '\u0338'}, + "NotSuperset;": {'\u2283', '\u20D2'}, + "ThickSpace;": {'\u205F', '\u200A'}, + "acE;": {'\u223E', '\u0333'}, + "bne;": {'\u003D', '\u20E5'}, + "bnequiv;": {'\u2261', '\u20E5'}, + "caps;": {'\u2229', '\uFE00'}, + "cups;": {'\u222A', '\uFE00'}, + "fjlig;": {'\u0066', '\u006A'}, + "gesl;": {'\u22DB', '\uFE00'}, + "gvertneqq;": {'\u2269', '\uFE00'}, + "gvnE;": {'\u2269', '\uFE00'}, + "lates;": {'\u2AAD', '\uFE00'}, + "lesg;": {'\u22DA', '\uFE00'}, + "lvertneqq;": {'\u2268', '\uFE00'}, + "lvnE;": {'\u2268', '\uFE00'}, + "nGg;": {'\u22D9', '\u0338'}, + "nGtv;": {'\u226B', '\u0338'}, + "nLl;": {'\u22D8', '\u0338'}, + "nLtv;": {'\u226A', '\u0338'}, + "nang;": {'\u2220', '\u20D2'}, + "napE;": {'\u2A70', '\u0338'}, + "napid;": {'\u224B', '\u0338'}, + "nbump;": {'\u224E', '\u0338'}, + "nbumpe;": {'\u224F', '\u0338'}, + "ncongdot;": {'\u2A6D', '\u0338'}, + "nedot;": {'\u2250', '\u0338'}, + "nesim;": {'\u2242', '\u0338'}, + "ngE;": {'\u2267', '\u0338'}, + "ngeqq;": {'\u2267', '\u0338'}, + "ngeqslant;": {'\u2A7E', '\u0338'}, + "nges;": {'\u2A7E', '\u0338'}, + "nlE;": {'\u2266', '\u0338'}, + "nleqq;": {'\u2266', '\u0338'}, + "nleqslant;": {'\u2A7D', '\u0338'}, + "nles;": {'\u2A7D', '\u0338'}, + "notinE;": {'\u22F9', '\u0338'}, + "notindot;": {'\u22F5', '\u0338'}, + "nparsl;": {'\u2AFD', '\u20E5'}, + "npart;": {'\u2202', '\u0338'}, + "npre;": {'\u2AAF', '\u0338'}, + "npreceq;": {'\u2AAF', '\u0338'}, + "nrarrc;": {'\u2933', '\u0338'}, + "nrarrw;": {'\u219D', '\u0338'}, + "nsce;": {'\u2AB0', '\u0338'}, + "nsubE;": {'\u2AC5', '\u0338'}, + "nsubset;": {'\u2282', '\u20D2'}, + "nsubseteqq;": {'\u2AC5', '\u0338'}, + "nsucceq;": {'\u2AB0', '\u0338'}, + "nsupE;": {'\u2AC6', '\u0338'}, + "nsupset;": {'\u2283', '\u20D2'}, + "nsupseteqq;": {'\u2AC6', '\u0338'}, + "nvap;": {'\u224D', '\u20D2'}, + "nvge;": {'\u2265', '\u20D2'}, + "nvgt;": {'\u003E', '\u20D2'}, + "nvle;": {'\u2264', '\u20D2'}, + "nvlt;": {'\u003C', '\u20D2'}, + "nvltrie;": {'\u22B4', '\u20D2'}, + "nvrtrie;": {'\u22B5', '\u20D2'}, + "nvsim;": {'\u223C', '\u20D2'}, + "race;": {'\u223D', '\u0331'}, + "smtes;": {'\u2AAC', '\uFE00'}, + "sqcaps;": {'\u2293', '\uFE00'}, + "sqcups;": {'\u2294', '\uFE00'}, + "varsubsetneq;": {'\u228A', '\uFE00'}, + "varsubsetneqq;": {'\u2ACB', '\uFE00'}, + "varsupsetneq;": {'\u228B', '\uFE00'}, + "varsupsetneqq;": {'\u2ACC', '\uFE00'}, + "vnsub;": {'\u2282', '\u20D2'}, + "vnsup;": {'\u2283', '\u20D2'}, + "vsubnE;": {'\u2ACB', '\uFE00'}, + "vsubne;": {'\u228A', '\uFE00'}, + "vsupnE;": {'\u2ACC', '\uFE00'}, + "vsupne;": {'\u228B', '\uFE00'}, +} diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go new file mode 100644 index 000000000..d85613962 --- /dev/null +++ b/vendor/golang.org/x/net/html/escape.go @@ -0,0 +1,258 @@ +// Copyright 2010 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. + +package html + +import ( + "bytes" + "strings" + "unicode/utf8" +) + +// These replacements permit compatibility with old numeric entities that +// assumed Windows-1252 encoding. +// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference +var replacementTable = [...]rune{ + '\u20AC', // First entry is what 0x80 should be replaced with. + '\u0081', + '\u201A', + '\u0192', + '\u201E', + '\u2026', + '\u2020', + '\u2021', + '\u02C6', + '\u2030', + '\u0160', + '\u2039', + '\u0152', + '\u008D', + '\u017D', + '\u008F', + '\u0090', + '\u2018', + '\u2019', + '\u201C', + '\u201D', + '\u2022', + '\u2013', + '\u2014', + '\u02DC', + '\u2122', + '\u0161', + '\u203A', + '\u0153', + '\u009D', + '\u017E', + '\u0178', // Last entry is 0x9F. + // 0x00->'\uFFFD' is handled programmatically. + // 0x0D->'\u000D' is a no-op. +} + +// unescapeEntity reads an entity like "<" from b[src:] and writes the +// corresponding "<" to b[dst:], returning the incremented dst and src cursors. +// Precondition: b[src] == '&' && dst <= src. +// attribute should be true if parsing an attribute value. +func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) { + // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference + + // i starts at 1 because we already know that s[0] == '&'. + i, s := 1, b[src:] + + if len(s) <= 1 { + b[dst] = b[src] + return dst + 1, src + 1 + } + + if s[i] == '#' { + if len(s) <= 3 { // We need to have at least "&#.". + b[dst] = b[src] + return dst + 1, src + 1 + } + i++ + c := s[i] + hex := false + if c == 'x' || c == 'X' { + hex = true + i++ + } + + x := '\x00' + for i < len(s) { + c = s[i] + i++ + if hex { + if '0' <= c && c <= '9' { + x = 16*x + rune(c) - '0' + continue + } else if 'a' <= c && c <= 'f' { + x = 16*x + rune(c) - 'a' + 10 + continue + } else if 'A' <= c && c <= 'F' { + x = 16*x + rune(c) - 'A' + 10 + continue + } + } else if '0' <= c && c <= '9' { + x = 10*x + rune(c) - '0' + continue + } + if c != ';' { + i-- + } + break + } + + if i <= 3 { // No characters matched. + b[dst] = b[src] + return dst + 1, src + 1 + } + + if 0x80 <= x && x <= 0x9F { + // Replace characters from Windows-1252 with UTF-8 equivalents. + x = replacementTable[x-0x80] + } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF { + // Replace invalid characters with the replacement character. + x = '\uFFFD' + } + + return dst + utf8.EncodeRune(b[dst:], x), src + i + } + + // Consume the maximum number of characters possible, with the + // consumed characters matching one of the named references. + + for i < len(s) { + c := s[i] + i++ + // Lower-cased characters are more common in entities, so we check for them first. + if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { + continue + } + if c != ';' { + i-- + } + break + } + + entityName := string(s[1:i]) + if entityName == "" { + // No-op. + } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' { + // No-op. + } else if x := entity[entityName]; x != 0 { + return dst + utf8.EncodeRune(b[dst:], x), src + i + } else if x := entity2[entityName]; x[0] != 0 { + dst1 := dst + utf8.EncodeRune(b[dst:], x[0]) + return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i + } else if !attribute { + maxLen := len(entityName) - 1 + if maxLen > longestEntityWithoutSemicolon { + maxLen = longestEntityWithoutSemicolon + } + for j := maxLen; j > 1; j-- { + if x := entity[entityName[:j]]; x != 0 { + return dst + utf8.EncodeRune(b[dst:], x), src + j + 1 + } + } + } + + dst1, src1 = dst+i, src+i + copy(b[dst:dst1], b[src:src1]) + return dst1, src1 +} + +// unescape unescapes b's entities in-place, so that "a<b" becomes "a': + esc = ">" + case '"': + // """ is shorter than """. + esc = """ + case '\r': + esc = " " + default: + panic("unrecognized escape character") + } + s = s[i+1:] + if _, err := w.WriteString(esc); err != nil { + return err + } + i = strings.IndexAny(s, escapedChars) + } + _, err := w.WriteString(s) + return err +} + +// EscapeString escapes special characters like "<" to become "<". It +// escapes only five such characters: <, >, &, ' and ". +// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't +// always true. +func EscapeString(s string) string { + if strings.IndexAny(s, escapedChars) == -1 { + return s + } + var buf bytes.Buffer + escape(&buf, s) + return buf.String() +} + +// UnescapeString unescapes entities like "<" to become "<". It unescapes a +// larger range of entities than EscapeString escapes. For example, "á" +// unescapes to "á", as does "á" and "&xE1;". +// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't +// always true. +func UnescapeString(s string) string { + for _, c := range s { + if c == '&' { + return string(unescape([]byte(s), false)) + } + } + return s +} diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go new file mode 100644 index 000000000..d3b384409 --- /dev/null +++ b/vendor/golang.org/x/net/html/foreign.go @@ -0,0 +1,226 @@ +// Copyright 2011 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. + +package html + +import ( + "strings" +) + +func adjustAttributeNames(aa []Attribute, nameMap map[string]string) { + for i := range aa { + if newName, ok := nameMap[aa[i].Key]; ok { + aa[i].Key = newName + } + } +} + +func adjustForeignAttributes(aa []Attribute) { + for i, a := range aa { + if a.Key == "" || a.Key[0] != 'x' { + continue + } + switch a.Key { + case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", + "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink": + j := strings.Index(a.Key, ":") + aa[i].Namespace = a.Key[:j] + aa[i].Key = a.Key[j+1:] + } + } +} + +func htmlIntegrationPoint(n *Node) bool { + if n.Type != ElementNode { + return false + } + switch n.Namespace { + case "math": + if n.Data == "annotation-xml" { + for _, a := range n.Attr { + if a.Key == "encoding" { + val := strings.ToLower(a.Val) + if val == "text/html" || val == "application/xhtml+xml" { + return true + } + } + } + } + case "svg": + switch n.Data { + case "desc", "foreignObject", "title": + return true + } + } + return false +} + +func mathMLTextIntegrationPoint(n *Node) bool { + if n.Namespace != "math" { + return false + } + switch n.Data { + case "mi", "mo", "mn", "ms", "mtext": + return true + } + return false +} + +// Section 12.2.5.5. +var breakout = map[string]bool{ + "b": true, + "big": true, + "blockquote": true, + "body": true, + "br": true, + "center": true, + "code": true, + "dd": true, + "div": true, + "dl": true, + "dt": true, + "em": true, + "embed": true, + "h1": true, + "h2": true, + "h3": true, + "h4": true, + "h5": true, + "h6": true, + "head": true, + "hr": true, + "i": true, + "img": true, + "li": true, + "listing": true, + "menu": true, + "meta": true, + "nobr": true, + "ol": true, + "p": true, + "pre": true, + "ruby": true, + "s": true, + "small": true, + "span": true, + "strong": true, + "strike": true, + "sub": true, + "sup": true, + "table": true, + "tt": true, + "u": true, + "ul": true, + "var": true, +} + +// Section 12.2.5.5. +var svgTagNameAdjustments = map[string]string{ + "altglyph": "altGlyph", + "altglyphdef": "altGlyphDef", + "altglyphitem": "altGlyphItem", + "animatecolor": "animateColor", + "animatemotion": "animateMotion", + "animatetransform": "animateTransform", + "clippath": "clipPath", + "feblend": "feBlend", + "fecolormatrix": "feColorMatrix", + "fecomponenttransfer": "feComponentTransfer", + "fecomposite": "feComposite", + "feconvolvematrix": "feConvolveMatrix", + "fediffuselighting": "feDiffuseLighting", + "fedisplacementmap": "feDisplacementMap", + "fedistantlight": "feDistantLight", + "feflood": "feFlood", + "fefunca": "feFuncA", + "fefuncb": "feFuncB", + "fefuncg": "feFuncG", + "fefuncr": "feFuncR", + "fegaussianblur": "feGaussianBlur", + "feimage": "feImage", + "femerge": "feMerge", + "femergenode": "feMergeNode", + "femorphology": "feMorphology", + "feoffset": "feOffset", + "fepointlight": "fePointLight", + "fespecularlighting": "feSpecularLighting", + "fespotlight": "feSpotLight", + "fetile": "feTile", + "feturbulence": "feTurbulence", + "foreignobject": "foreignObject", + "glyphref": "glyphRef", + "lineargradient": "linearGradient", + "radialgradient": "radialGradient", + "textpath": "textPath", +} + +// Section 12.2.5.1 +var mathMLAttributeAdjustments = map[string]string{ + "definitionurl": "definitionURL", +} + +var svgAttributeAdjustments = map[string]string{ + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan", +} diff --git a/vendor/golang.org/x/net/html/node.go b/vendor/golang.org/x/net/html/node.go new file mode 100644 index 000000000..26b657aec --- /dev/null +++ b/vendor/golang.org/x/net/html/node.go @@ -0,0 +1,193 @@ +// Copyright 2011 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. + +package html + +import ( + "golang.org/x/net/html/atom" +) + +// A NodeType is the type of a Node. +type NodeType uint32 + +const ( + ErrorNode NodeType = iota + TextNode + DocumentNode + ElementNode + CommentNode + DoctypeNode + scopeMarkerNode +) + +// Section 12.2.3.3 says "scope markers are inserted when entering applet +// elements, buttons, object elements, marquees, table cells, and table +// captions, and are used to prevent formatting from 'leaking'". +var scopeMarker = Node{Type: scopeMarkerNode} + +// A Node consists of a NodeType and some Data (tag name for element nodes, +// content for text) and are part of a tree of Nodes. Element nodes may also +// have a Namespace and contain a slice of Attributes. Data is unescaped, so +// that it looks like "a 0 { + return (*s)[i-1] + } + return nil +} + +// index returns the index of the top-most occurrence of n in the stack, or -1 +// if n is not present. +func (s *nodeStack) index(n *Node) int { + for i := len(*s) - 1; i >= 0; i-- { + if (*s)[i] == n { + return i + } + } + return -1 +} + +// insert inserts a node at the given index. +func (s *nodeStack) insert(i int, n *Node) { + (*s) = append(*s, nil) + copy((*s)[i+1:], (*s)[i:]) + (*s)[i] = n +} + +// remove removes a node from the stack. It is a no-op if n is not present. +func (s *nodeStack) remove(n *Node) { + i := s.index(n) + if i == -1 { + return + } + copy((*s)[i:], (*s)[i+1:]) + j := len(*s) - 1 + (*s)[j] = nil + *s = (*s)[:j] +} diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go new file mode 100644 index 000000000..be4b2bf5a --- /dev/null +++ b/vendor/golang.org/x/net/html/parse.go @@ -0,0 +1,2094 @@ +// Copyright 2010 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. + +package html + +import ( + "errors" + "fmt" + "io" + "strings" + + a "golang.org/x/net/html/atom" +) + +// A parser implements the HTML5 parsing algorithm: +// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction +type parser struct { + // tokenizer provides the tokens for the parser. + tokenizer *Tokenizer + // tok is the most recently read token. + tok Token + // Self-closing tags like


    are treated as start tags, except that + // hasSelfClosingToken is set while they are being processed. + hasSelfClosingToken bool + // doc is the document root element. + doc *Node + // The stack of open elements (section 12.2.3.2) and active formatting + // elements (section 12.2.3.3). + oe, afe nodeStack + // Element pointers (section 12.2.3.4). + head, form *Node + // Other parsing state flags (section 12.2.3.5). + scripting, framesetOK bool + // im is the current insertion mode. + im insertionMode + // originalIM is the insertion mode to go back to after completing a text + // or inTableText insertion mode. + originalIM insertionMode + // fosterParenting is whether new elements should be inserted according to + // the foster parenting rules (section 12.2.5.3). + fosterParenting bool + // quirks is whether the parser is operating in "quirks mode." + quirks bool + // fragment is whether the parser is parsing an HTML fragment. + fragment bool + // context is the context element when parsing an HTML fragment + // (section 12.4). + context *Node +} + +func (p *parser) top() *Node { + if n := p.oe.top(); n != nil { + return n + } + return p.doc +} + +// Stop tags for use in popUntil. These come from section 12.2.3.2. +var ( + defaultScopeStopTags = map[string][]a.Atom{ + "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template}, + "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext}, + "svg": {a.Desc, a.ForeignObject, a.Title}, + } +) + +type scope int + +const ( + defaultScope scope = iota + listItemScope + buttonScope + tableScope + tableRowScope + tableBodyScope + selectScope +) + +// popUntil pops the stack of open elements at the highest element whose tag +// is in matchTags, provided there is no higher element in the scope's stop +// tags (as defined in section 12.2.3.2). It returns whether or not there was +// such an element. If there was not, popUntil leaves the stack unchanged. +// +// For example, the set of stop tags for table scope is: "html", "table". If +// the stack was: +// ["html", "body", "font", "table", "b", "i", "u"] +// then popUntil(tableScope, "font") would return false, but +// popUntil(tableScope, "i") would return true and the stack would become: +// ["html", "body", "font", "table", "b"] +// +// If an element's tag is in both the stop tags and matchTags, then the stack +// will be popped and the function returns true (provided, of course, there was +// no higher element in the stack that was also in the stop tags). For example, +// popUntil(tableScope, "table") returns true and leaves: +// ["html", "body", "font"] +func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool { + if i := p.indexOfElementInScope(s, matchTags...); i != -1 { + p.oe = p.oe[:i] + return true + } + return false +} + +// indexOfElementInScope returns the index in p.oe of the highest element whose +// tag is in matchTags that is in scope. If no matching element is in scope, it +// returns -1. +func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int { + for i := len(p.oe) - 1; i >= 0; i-- { + tagAtom := p.oe[i].DataAtom + if p.oe[i].Namespace == "" { + for _, t := range matchTags { + if t == tagAtom { + return i + } + } + switch s { + case defaultScope: + // No-op. + case listItemScope: + if tagAtom == a.Ol || tagAtom == a.Ul { + return -1 + } + case buttonScope: + if tagAtom == a.Button { + return -1 + } + case tableScope: + if tagAtom == a.Html || tagAtom == a.Table { + return -1 + } + case selectScope: + if tagAtom != a.Optgroup && tagAtom != a.Option { + return -1 + } + default: + panic("unreachable") + } + } + switch s { + case defaultScope, listItemScope, buttonScope: + for _, t := range defaultScopeStopTags[p.oe[i].Namespace] { + if t == tagAtom { + return -1 + } + } + } + } + return -1 +} + +// elementInScope is like popUntil, except that it doesn't modify the stack of +// open elements. +func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool { + return p.indexOfElementInScope(s, matchTags...) != -1 +} + +// clearStackToContext pops elements off the stack of open elements until a +// scope-defined element is found. +func (p *parser) clearStackToContext(s scope) { + for i := len(p.oe) - 1; i >= 0; i-- { + tagAtom := p.oe[i].DataAtom + switch s { + case tableScope: + if tagAtom == a.Html || tagAtom == a.Table { + p.oe = p.oe[:i+1] + return + } + case tableRowScope: + if tagAtom == a.Html || tagAtom == a.Tr { + p.oe = p.oe[:i+1] + return + } + case tableBodyScope: + if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead { + p.oe = p.oe[:i+1] + return + } + default: + panic("unreachable") + } + } +} + +// generateImpliedEndTags pops nodes off the stack of open elements as long as +// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt. +// If exceptions are specified, nodes with that name will not be popped off. +func (p *parser) generateImpliedEndTags(exceptions ...string) { + var i int +loop: + for i = len(p.oe) - 1; i >= 0; i-- { + n := p.oe[i] + if n.Type == ElementNode { + switch n.DataAtom { + case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt: + for _, except := range exceptions { + if n.Data == except { + break loop + } + } + continue + } + } + break + } + + p.oe = p.oe[:i+1] +} + +// addChild adds a child node n to the top element, and pushes n onto the stack +// of open elements if it is an element node. +func (p *parser) addChild(n *Node) { + if p.shouldFosterParent() { + p.fosterParent(n) + } else { + p.top().AppendChild(n) + } + + if n.Type == ElementNode { + p.oe = append(p.oe, n) + } +} + +// shouldFosterParent returns whether the next node to be added should be +// foster parented. +func (p *parser) shouldFosterParent() bool { + if p.fosterParenting { + switch p.top().DataAtom { + case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr: + return true + } + } + return false +} + +// fosterParent adds a child node according to the foster parenting rules. +// Section 12.2.5.3, "foster parenting". +func (p *parser) fosterParent(n *Node) { + var table, parent, prev *Node + var i int + for i = len(p.oe) - 1; i >= 0; i-- { + if p.oe[i].DataAtom == a.Table { + table = p.oe[i] + break + } + } + + if table == nil { + // The foster parent is the html element. + parent = p.oe[0] + } else { + parent = table.Parent + } + if parent == nil { + parent = p.oe[i-1] + } + + if table != nil { + prev = table.PrevSibling + } else { + prev = parent.LastChild + } + if prev != nil && prev.Type == TextNode && n.Type == TextNode { + prev.Data += n.Data + return + } + + parent.InsertBefore(n, table) +} + +// addText adds text to the preceding node if it is a text node, or else it +// calls addChild with a new text node. +func (p *parser) addText(text string) { + if text == "" { + return + } + + if p.shouldFosterParent() { + p.fosterParent(&Node{ + Type: TextNode, + Data: text, + }) + return + } + + t := p.top() + if n := t.LastChild; n != nil && n.Type == TextNode { + n.Data += text + return + } + p.addChild(&Node{ + Type: TextNode, + Data: text, + }) +} + +// addElement adds a child element based on the current token. +func (p *parser) addElement() { + p.addChild(&Node{ + Type: ElementNode, + DataAtom: p.tok.DataAtom, + Data: p.tok.Data, + Attr: p.tok.Attr, + }) +} + +// Section 12.2.3.3. +func (p *parser) addFormattingElement() { + tagAtom, attr := p.tok.DataAtom, p.tok.Attr + p.addElement() + + // Implement the Noah's Ark clause, but with three per family instead of two. + identicalElements := 0 +findIdenticalElements: + for i := len(p.afe) - 1; i >= 0; i-- { + n := p.afe[i] + if n.Type == scopeMarkerNode { + break + } + if n.Type != ElementNode { + continue + } + if n.Namespace != "" { + continue + } + if n.DataAtom != tagAtom { + continue + } + if len(n.Attr) != len(attr) { + continue + } + compareAttributes: + for _, t0 := range n.Attr { + for _, t1 := range attr { + if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val { + // Found a match for this attribute, continue with the next attribute. + continue compareAttributes + } + } + // If we get here, there is no attribute that matches a. + // Therefore the element is not identical to the new one. + continue findIdenticalElements + } + + identicalElements++ + if identicalElements >= 3 { + p.afe.remove(n) + } + } + + p.afe = append(p.afe, p.top()) +} + +// Section 12.2.3.3. +func (p *parser) clearActiveFormattingElements() { + for { + n := p.afe.pop() + if len(p.afe) == 0 || n.Type == scopeMarkerNode { + return + } + } +} + +// Section 12.2.3.3. +func (p *parser) reconstructActiveFormattingElements() { + n := p.afe.top() + if n == nil { + return + } + if n.Type == scopeMarkerNode || p.oe.index(n) != -1 { + return + } + i := len(p.afe) - 1 + for n.Type != scopeMarkerNode && p.oe.index(n) == -1 { + if i == 0 { + i = -1 + break + } + i-- + n = p.afe[i] + } + for { + i++ + clone := p.afe[i].clone() + p.addChild(clone) + p.afe[i] = clone + if i == len(p.afe)-1 { + break + } + } +} + +// Section 12.2.4. +func (p *parser) acknowledgeSelfClosingTag() { + p.hasSelfClosingToken = false +} + +// An insertion mode (section 12.2.3.1) is the state transition function from +// a particular state in the HTML5 parser's state machine. It updates the +// parser's fields depending on parser.tok (where ErrorToken means EOF). +// It returns whether the token was consumed. +type insertionMode func(*parser) bool + +// setOriginalIM sets the insertion mode to return to after completing a text or +// inTableText insertion mode. +// Section 12.2.3.1, "using the rules for". +func (p *parser) setOriginalIM() { + if p.originalIM != nil { + panic("html: bad parser state: originalIM was set twice") + } + p.originalIM = p.im +} + +// Section 12.2.3.1, "reset the insertion mode". +func (p *parser) resetInsertionMode() { + for i := len(p.oe) - 1; i >= 0; i-- { + n := p.oe[i] + if i == 0 && p.context != nil { + n = p.context + } + + switch n.DataAtom { + case a.Select: + p.im = inSelectIM + case a.Td, a.Th: + p.im = inCellIM + case a.Tr: + p.im = inRowIM + case a.Tbody, a.Thead, a.Tfoot: + p.im = inTableBodyIM + case a.Caption: + p.im = inCaptionIM + case a.Colgroup: + p.im = inColumnGroupIM + case a.Table: + p.im = inTableIM + case a.Head: + p.im = inBodyIM + case a.Body: + p.im = inBodyIM + case a.Frameset: + p.im = inFramesetIM + case a.Html: + p.im = beforeHeadIM + default: + continue + } + return + } + p.im = inBodyIM +} + +const whitespace = " \t\r\n\f" + +// Section 12.2.5.4.1. +func initialIM(p *parser) bool { + switch p.tok.Type { + case TextToken: + p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) + if len(p.tok.Data) == 0 { + // It was all whitespace, so ignore it. + return true + } + case CommentToken: + p.doc.AppendChild(&Node{ + Type: CommentNode, + Data: p.tok.Data, + }) + return true + case DoctypeToken: + n, quirks := parseDoctype(p.tok.Data) + p.doc.AppendChild(n) + p.quirks = quirks + p.im = beforeHTMLIM + return true + } + p.quirks = true + p.im = beforeHTMLIM + return false +} + +// Section 12.2.5.4.2. +func beforeHTMLIM(p *parser) bool { + switch p.tok.Type { + case DoctypeToken: + // Ignore the token. + return true + case TextToken: + p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) + if len(p.tok.Data) == 0 { + // It was all whitespace, so ignore it. + return true + } + case StartTagToken: + if p.tok.DataAtom == a.Html { + p.addElement() + p.im = beforeHeadIM + return true + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Head, a.Body, a.Html, a.Br: + p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) + return false + default: + // Ignore the token. + return true + } + case CommentToken: + p.doc.AppendChild(&Node{ + Type: CommentNode, + Data: p.tok.Data, + }) + return true + } + p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) + return false +} + +// Section 12.2.5.4.3. +func beforeHeadIM(p *parser) bool { + switch p.tok.Type { + case TextToken: + p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) + if len(p.tok.Data) == 0 { + // It was all whitespace, so ignore it. + return true + } + case StartTagToken: + switch p.tok.DataAtom { + case a.Head: + p.addElement() + p.head = p.top() + p.im = inHeadIM + return true + case a.Html: + return inBodyIM(p) + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Head, a.Body, a.Html, a.Br: + p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) + return false + default: + // Ignore the token. + return true + } + case CommentToken: + p.addChild(&Node{ + Type: CommentNode, + Data: p.tok.Data, + }) + return true + case DoctypeToken: + // Ignore the token. + return true + } + + p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) + return false +} + +// Section 12.2.5.4.4. +func inHeadIM(p *parser) bool { + switch p.tok.Type { + case TextToken: + s := strings.TrimLeft(p.tok.Data, whitespace) + if len(s) < len(p.tok.Data) { + // Add the initial whitespace to the current node. + p.addText(p.tok.Data[:len(p.tok.Data)-len(s)]) + if s == "" { + return true + } + p.tok.Data = s + } + case StartTagToken: + switch p.tok.DataAtom { + case a.Html: + return inBodyIM(p) + case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta: + p.addElement() + p.oe.pop() + p.acknowledgeSelfClosingTag() + return true + case a.Script, a.Title, a.Noscript, a.Noframes, a.Style: + p.addElement() + p.setOriginalIM() + p.im = textIM + return true + case a.Head: + // Ignore the token. + return true + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Head: + n := p.oe.pop() + if n.DataAtom != a.Head { + panic("html: bad parser state: element not found, in the in-head insertion mode") + } + p.im = afterHeadIM + return true + case a.Body, a.Html, a.Br: + p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) + return false + default: + // Ignore the token. + return true + } + case CommentToken: + p.addChild(&Node{ + Type: CommentNode, + Data: p.tok.Data, + }) + return true + case DoctypeToken: + // Ignore the token. + return true + } + + p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) + return false +} + +// Section 12.2.5.4.6. +func afterHeadIM(p *parser) bool { + switch p.tok.Type { + case TextToken: + s := strings.TrimLeft(p.tok.Data, whitespace) + if len(s) < len(p.tok.Data) { + // Add the initial whitespace to the current node. + p.addText(p.tok.Data[:len(p.tok.Data)-len(s)]) + if s == "" { + return true + } + p.tok.Data = s + } + case StartTagToken: + switch p.tok.DataAtom { + case a.Html: + return inBodyIM(p) + case a.Body: + p.addElement() + p.framesetOK = false + p.im = inBodyIM + return true + case a.Frameset: + p.addElement() + p.im = inFramesetIM + return true + case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: + p.oe = append(p.oe, p.head) + defer p.oe.remove(p.head) + return inHeadIM(p) + case a.Head: + // Ignore the token. + return true + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Body, a.Html, a.Br: + // Drop down to creating an implied tag. + default: + // Ignore the token. + return true + } + case CommentToken: + p.addChild(&Node{ + Type: CommentNode, + Data: p.tok.Data, + }) + return true + case DoctypeToken: + // Ignore the token. + return true + } + + p.parseImpliedToken(StartTagToken, a.Body, a.Body.String()) + p.framesetOK = true + return false +} + +// copyAttributes copies attributes of src not found on dst to dst. +func copyAttributes(dst *Node, src Token) { + if len(src.Attr) == 0 { + return + } + attr := map[string]string{} + for _, t := range dst.Attr { + attr[t.Key] = t.Val + } + for _, t := range src.Attr { + if _, ok := attr[t.Key]; !ok { + dst.Attr = append(dst.Attr, t) + attr[t.Key] = t.Val + } + } +} + +// Section 12.2.5.4.7. +func inBodyIM(p *parser) bool { + switch p.tok.Type { + case TextToken: + d := p.tok.Data + switch n := p.oe.top(); n.DataAtom { + case a.Pre, a.Listing: + if n.FirstChild == nil { + // Ignore a newline at the start of a
     block.
    +				if d != "" && d[0] == '\r' {
    +					d = d[1:]
    +				}
    +				if d != "" && d[0] == '\n' {
    +					d = d[1:]
    +				}
    +			}
    +		}
    +		d = strings.Replace(d, "\x00", "", -1)
    +		if d == "" {
    +			return true
    +		}
    +		p.reconstructActiveFormattingElements()
    +		p.addText(d)
    +		if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
    +			// There were non-whitespace characters inserted.
    +			p.framesetOK = false
    +		}
    +	case StartTagToken:
    +		switch p.tok.DataAtom {
    +		case a.Html:
    +			copyAttributes(p.oe[0], p.tok)
    +		case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
    +			return inHeadIM(p)
    +		case a.Body:
    +			if len(p.oe) >= 2 {
    +				body := p.oe[1]
    +				if body.Type == ElementNode && body.DataAtom == a.Body {
    +					p.framesetOK = false
    +					copyAttributes(body, p.tok)
    +				}
    +			}
    +		case a.Frameset:
    +			if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
    +				// Ignore the token.
    +				return true
    +			}
    +			body := p.oe[1]
    +			if body.Parent != nil {
    +				body.Parent.RemoveChild(body)
    +			}
    +			p.oe = p.oe[:1]
    +			p.addElement()
    +			p.im = inFramesetIM
    +			return true
    +		case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +		case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
    +			p.popUntil(buttonScope, a.P)
    +			switch n := p.top(); n.DataAtom {
    +			case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
    +				p.oe.pop()
    +			}
    +			p.addElement()
    +		case a.Pre, a.Listing:
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +			// The newline, if any, will be dealt with by the TextToken case.
    +			p.framesetOK = false
    +		case a.Form:
    +			if p.form == nil {
    +				p.popUntil(buttonScope, a.P)
    +				p.addElement()
    +				p.form = p.top()
    +			}
    +		case a.Li:
    +			p.framesetOK = false
    +			for i := len(p.oe) - 1; i >= 0; i-- {
    +				node := p.oe[i]
    +				switch node.DataAtom {
    +				case a.Li:
    +					p.oe = p.oe[:i]
    +				case a.Address, a.Div, a.P:
    +					continue
    +				default:
    +					if !isSpecialElement(node) {
    +						continue
    +					}
    +				}
    +				break
    +			}
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +		case a.Dd, a.Dt:
    +			p.framesetOK = false
    +			for i := len(p.oe) - 1; i >= 0; i-- {
    +				node := p.oe[i]
    +				switch node.DataAtom {
    +				case a.Dd, a.Dt:
    +					p.oe = p.oe[:i]
    +				case a.Address, a.Div, a.P:
    +					continue
    +				default:
    +					if !isSpecialElement(node) {
    +						continue
    +					}
    +				}
    +				break
    +			}
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +		case a.Plaintext:
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +		case a.Button:
    +			p.popUntil(defaultScope, a.Button)
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +			p.framesetOK = false
    +		case a.A:
    +			for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
    +				if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
    +					p.inBodyEndTagFormatting(a.A)
    +					p.oe.remove(n)
    +					p.afe.remove(n)
    +					break
    +				}
    +			}
    +			p.reconstructActiveFormattingElements()
    +			p.addFormattingElement()
    +		case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
    +			p.reconstructActiveFormattingElements()
    +			p.addFormattingElement()
    +		case a.Nobr:
    +			p.reconstructActiveFormattingElements()
    +			if p.elementInScope(defaultScope, a.Nobr) {
    +				p.inBodyEndTagFormatting(a.Nobr)
    +				p.reconstructActiveFormattingElements()
    +			}
    +			p.addFormattingElement()
    +		case a.Applet, a.Marquee, a.Object:
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +			p.afe = append(p.afe, &scopeMarker)
    +			p.framesetOK = false
    +		case a.Table:
    +			if !p.quirks {
    +				p.popUntil(buttonScope, a.P)
    +			}
    +			p.addElement()
    +			p.framesetOK = false
    +			p.im = inTableIM
    +			return true
    +		case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +			p.oe.pop()
    +			p.acknowledgeSelfClosingTag()
    +			if p.tok.DataAtom == a.Input {
    +				for _, t := range p.tok.Attr {
    +					if t.Key == "type" {
    +						if strings.ToLower(t.Val) == "hidden" {
    +							// Skip setting framesetOK = false
    +							return true
    +						}
    +					}
    +				}
    +			}
    +			p.framesetOK = false
    +		case a.Param, a.Source, a.Track:
    +			p.addElement()
    +			p.oe.pop()
    +			p.acknowledgeSelfClosingTag()
    +		case a.Hr:
    +			p.popUntil(buttonScope, a.P)
    +			p.addElement()
    +			p.oe.pop()
    +			p.acknowledgeSelfClosingTag()
    +			p.framesetOK = false
    +		case a.Image:
    +			p.tok.DataAtom = a.Img
    +			p.tok.Data = a.Img.String()
    +			return false
    +		case a.Isindex:
    +			if p.form != nil {
    +				// Ignore the token.
    +				return true
    +			}
    +			action := ""
    +			prompt := "This is a searchable index. Enter search keywords: "
    +			attr := []Attribute{{Key: "name", Val: "isindex"}}
    +			for _, t := range p.tok.Attr {
    +				switch t.Key {
    +				case "action":
    +					action = t.Val
    +				case "name":
    +					// Ignore the attribute.
    +				case "prompt":
    +					prompt = t.Val
    +				default:
    +					attr = append(attr, t)
    +				}
    +			}
    +			p.acknowledgeSelfClosingTag()
    +			p.popUntil(buttonScope, a.P)
    +			p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
    +			if action != "" {
    +				p.form.Attr = []Attribute{{Key: "action", Val: action}}
    +			}
    +			p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
    +			p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
    +			p.addText(prompt)
    +			p.addChild(&Node{
    +				Type:     ElementNode,
    +				DataAtom: a.Input,
    +				Data:     a.Input.String(),
    +				Attr:     attr,
    +			})
    +			p.oe.pop()
    +			p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
    +			p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
    +			p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
    +		case a.Textarea:
    +			p.addElement()
    +			p.setOriginalIM()
    +			p.framesetOK = false
    +			p.im = textIM
    +		case a.Xmp:
    +			p.popUntil(buttonScope, a.P)
    +			p.reconstructActiveFormattingElements()
    +			p.framesetOK = false
    +			p.addElement()
    +			p.setOriginalIM()
    +			p.im = textIM
    +		case a.Iframe:
    +			p.framesetOK = false
    +			p.addElement()
    +			p.setOriginalIM()
    +			p.im = textIM
    +		case a.Noembed, a.Noscript:
    +			p.addElement()
    +			p.setOriginalIM()
    +			p.im = textIM
    +		case a.Select:
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +			p.framesetOK = false
    +			p.im = inSelectIM
    +			return true
    +		case a.Optgroup, a.Option:
    +			if p.top().DataAtom == a.Option {
    +				p.oe.pop()
    +			}
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +		case a.Rp, a.Rt:
    +			if p.elementInScope(defaultScope, a.Ruby) {
    +				p.generateImpliedEndTags()
    +			}
    +			p.addElement()
    +		case a.Math, a.Svg:
    +			p.reconstructActiveFormattingElements()
    +			if p.tok.DataAtom == a.Math {
    +				adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
    +			} else {
    +				adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
    +			}
    +			adjustForeignAttributes(p.tok.Attr)
    +			p.addElement()
    +			p.top().Namespace = p.tok.Data
    +			if p.hasSelfClosingToken {
    +				p.oe.pop()
    +				p.acknowledgeSelfClosingTag()
    +			}
    +			return true
    +		case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
    +			// Ignore the token.
    +		default:
    +			p.reconstructActiveFormattingElements()
    +			p.addElement()
    +		}
    +	case EndTagToken:
    +		switch p.tok.DataAtom {
    +		case a.Body:
    +			if p.elementInScope(defaultScope, a.Body) {
    +				p.im = afterBodyIM
    +			}
    +		case a.Html:
    +			if p.elementInScope(defaultScope, a.Body) {
    +				p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
    +				return false
    +			}
    +			return true
    +		case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
    +			p.popUntil(defaultScope, p.tok.DataAtom)
    +		case a.Form:
    +			node := p.form
    +			p.form = nil
    +			i := p.indexOfElementInScope(defaultScope, a.Form)
    +			if node == nil || i == -1 || p.oe[i] != node {
    +				// Ignore the token.
    +				return true
    +			}
    +			p.generateImpliedEndTags()
    +			p.oe.remove(node)
    +		case a.P:
    +			if !p.elementInScope(buttonScope, a.P) {
    +				p.parseImpliedToken(StartTagToken, a.P, a.P.String())
    +			}
    +			p.popUntil(buttonScope, a.P)
    +		case a.Li:
    +			p.popUntil(listItemScope, a.Li)
    +		case a.Dd, a.Dt:
    +			p.popUntil(defaultScope, p.tok.DataAtom)
    +		case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
    +			p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
    +		case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
    +			p.inBodyEndTagFormatting(p.tok.DataAtom)
    +		case a.Applet, a.Marquee, a.Object:
    +			if p.popUntil(defaultScope, p.tok.DataAtom) {
    +				p.clearActiveFormattingElements()
    +			}
    +		case a.Br:
    +			p.tok.Type = StartTagToken
    +			return false
    +		default:
    +			p.inBodyEndTagOther(p.tok.DataAtom)
    +		}
    +	case CommentToken:
    +		p.addChild(&Node{
    +			Type: CommentNode,
    +			Data: p.tok.Data,
    +		})
    +	}
    +
    +	return true
    +}
    +
    +func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
    +	// This is the "adoption agency" algorithm, described at
    +	// https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
    +
    +	// TODO: this is a fairly literal line-by-line translation of that algorithm.
    +	// Once the code successfully parses the comprehensive test suite, we should
    +	// refactor this code to be more idiomatic.
    +
    +	// Steps 1-4. The outer loop.
    +	for i := 0; i < 8; i++ {
    +		// Step 5. Find the formatting element.
    +		var formattingElement *Node
    +		for j := len(p.afe) - 1; j >= 0; j-- {
    +			if p.afe[j].Type == scopeMarkerNode {
    +				break
    +			}
    +			if p.afe[j].DataAtom == tagAtom {
    +				formattingElement = p.afe[j]
    +				break
    +			}
    +		}
    +		if formattingElement == nil {
    +			p.inBodyEndTagOther(tagAtom)
    +			return
    +		}
    +		feIndex := p.oe.index(formattingElement)
    +		if feIndex == -1 {
    +			p.afe.remove(formattingElement)
    +			return
    +		}
    +		if !p.elementInScope(defaultScope, tagAtom) {
    +			// Ignore the tag.
    +			return
    +		}
    +
    +		// Steps 9-10. Find the furthest block.
    +		var furthestBlock *Node
    +		for _, e := range p.oe[feIndex:] {
    +			if isSpecialElement(e) {
    +				furthestBlock = e
    +				break
    +			}
    +		}
    +		if furthestBlock == nil {
    +			e := p.oe.pop()
    +			for e != formattingElement {
    +				e = p.oe.pop()
    +			}
    +			p.afe.remove(e)
    +			return
    +		}
    +
    +		// Steps 11-12. Find the common ancestor and bookmark node.
    +		commonAncestor := p.oe[feIndex-1]
    +		bookmark := p.afe.index(formattingElement)
    +
    +		// Step 13. The inner loop. Find the lastNode to reparent.
    +		lastNode := furthestBlock
    +		node := furthestBlock
    +		x := p.oe.index(node)
    +		// Steps 13.1-13.2
    +		for j := 0; j < 3; j++ {
    +			// Step 13.3.
    +			x--
    +			node = p.oe[x]
    +			// Step 13.4 - 13.5.
    +			if p.afe.index(node) == -1 {
    +				p.oe.remove(node)
    +				continue
    +			}
    +			// Step 13.6.
    +			if node == formattingElement {
    +				break
    +			}
    +			// Step 13.7.
    +			clone := node.clone()
    +			p.afe[p.afe.index(node)] = clone
    +			p.oe[p.oe.index(node)] = clone
    +			node = clone
    +			// Step 13.8.
    +			if lastNode == furthestBlock {
    +				bookmark = p.afe.index(node) + 1
    +			}
    +			// Step 13.9.
    +			if lastNode.Parent != nil {
    +				lastNode.Parent.RemoveChild(lastNode)
    +			}
    +			node.AppendChild(lastNode)
    +			// Step 13.10.
    +			lastNode = node
    +		}
    +
    +		// Step 14. Reparent lastNode to the common ancestor,
    +		// or for misnested table nodes, to the foster parent.
    +		if lastNode.Parent != nil {
    +			lastNode.Parent.RemoveChild(lastNode)
    +		}
    +		switch commonAncestor.DataAtom {
    +		case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
    +			p.fosterParent(lastNode)
    +		default:
    +			commonAncestor.AppendChild(lastNode)
    +		}
    +
    +		// Steps 15-17. Reparent nodes from the furthest block's children
    +		// to a clone of the formatting element.
    +		clone := formattingElement.clone()
    +		reparentChildren(clone, furthestBlock)
    +		furthestBlock.AppendChild(clone)
    +
    +		// Step 18. Fix up the list of active formatting elements.
    +		if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
    +			// Move the bookmark with the rest of the list.
    +			bookmark--
    +		}
    +		p.afe.remove(formattingElement)
    +		p.afe.insert(bookmark, clone)
    +
    +		// Step 19. Fix up the stack of open elements.
    +		p.oe.remove(formattingElement)
    +		p.oe.insert(p.oe.index(furthestBlock)+1, clone)
    +	}
    +}
    +
    +// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
    +// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content
    +// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
    +func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
    +	for i := len(p.oe) - 1; i >= 0; i-- {
    +		if p.oe[i].DataAtom == tagAtom {
    +			p.oe = p.oe[:i]
    +			break
    +		}
    +		if isSpecialElement(p.oe[i]) {
    +			break
    +		}
    +	}
    +}
    +
    +// Section 12.2.5.4.8.
    +func textIM(p *parser) bool {
    +	switch p.tok.Type {
    +	case ErrorToken:
    +		p.oe.pop()
    +	case TextToken:
    +		d := p.tok.Data
    +		if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
    +			// Ignore a newline at the start of a 
    +      
    + + + diff --git a/vendor/google.golang.org/appengine/demos/helloworld/app.yaml b/vendor/google.golang.org/appengine/demos/helloworld/app.yaml new file mode 100644 index 000000000..e0b2eb746 --- /dev/null +++ b/vendor/google.golang.org/appengine/demos/helloworld/app.yaml @@ -0,0 +1,13 @@ +runtime: go +api_version: go1 +vm: true + +manual_scaling: + instances: 1 + +handlers: +- url: /favicon.ico + static_files: favicon.ico + upload: favicon.ico +- url: /.* + script: _go_app diff --git a/vendor/google.golang.org/appengine/demos/helloworld/favicon.ico b/vendor/google.golang.org/appengine/demos/helloworld/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f19c04d270a3865384ce3db41412448692b8cba4 GIT binary patch literal 1150 zcmchVT}YE*6vvO#Ozpx+V3I*aL_(n#kx)ooMSh^NcA;pHT?E=LQZz`!FSHCRr@prN zwT3p)%=s-dmt~u}Ev?O|`zZYCq8qyiy0L=y-}5?0YR${e%Q?^Uob&&^@ADoGkso`+ zVq)QuG~pS#!VCV*}8%$~So~Xo7Z}fn#{=kyT1ep!Zb zv1b!}`L%0%gZ-u8{86F};i`UY4wfg*lK=n! literal 0 HcmV?d00001 diff --git a/vendor/google.golang.org/appengine/demos/helloworld/helloworld.go b/vendor/google.golang.org/appengine/demos/helloworld/helloworld.go new file mode 100644 index 000000000..fcd9b0bba --- /dev/null +++ b/vendor/google.golang.org/appengine/demos/helloworld/helloworld.go @@ -0,0 +1,50 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// This example only works on Managed VMs. +// +build !appengine + +package main + +import ( + "html/template" + "net/http" + "time" + + "google.golang.org/appengine" + "google.golang.org/appengine/log" +) + +var initTime = time.Now() + +func main() { + http.HandleFunc("/", handle) + appengine.Main() +} + +func handle(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + + ctx := appengine.NewContext(r) + log.Infof(ctx, "Serving the front page.") + + tmpl.Execute(w, time.Since(initTime)) +} + +var tmpl = template.Must(template.New("front").Parse(` + + +

    +Hello, World! 세ìƒì•„ 안녕! +

    + +

    +This instance has been running for {{.}}. +

    + + +`)) diff --git a/vendor/google.golang.org/appengine/errors.go b/vendor/google.golang.org/appengine/errors.go new file mode 100644 index 000000000..16d0772e2 --- /dev/null +++ b/vendor/google.golang.org/appengine/errors.go @@ -0,0 +1,46 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// This file provides error functions for common API failure modes. + +package appengine + +import ( + "fmt" + + "google.golang.org/appengine/internal" +) + +// IsOverQuota reports whether err represents an API call failure +// due to insufficient available quota. +func IsOverQuota(err error) bool { + callErr, ok := err.(*internal.CallError) + return ok && callErr.Code == 4 +} + +// MultiError is returned by batch operations when there are errors with +// particular elements. Errors will be in a one-to-one correspondence with +// the input elements; successful elements will have a nil entry. +type MultiError []error + +func (m MultiError) Error() string { + s, n := "", 0 + for _, e := range m { + if e != nil { + if n == 0 { + s = e.Error() + } + n++ + } + } + switch n { + case 0: + return "(0 errors)" + case 1: + return s + case 2: + return s + " (and 1 other error)" + } + return fmt.Sprintf("%s (and %d other errors)", s, n-1) +} diff --git a/vendor/google.golang.org/appengine/file/file.go b/vendor/google.golang.org/appengine/file/file.go new file mode 100644 index 000000000..c3cd58baf --- /dev/null +++ b/vendor/google.golang.org/appengine/file/file.go @@ -0,0 +1,28 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package file provides helper functions for using Google Cloud Storage. +package file + +import ( + "fmt" + + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + aipb "google.golang.org/appengine/internal/app_identity" +) + +// DefaultBucketName returns the name of this application's +// default Google Cloud Storage bucket. +func DefaultBucketName(c context.Context) (string, error) { + req := &aipb.GetDefaultGcsBucketNameRequest{} + res := &aipb.GetDefaultGcsBucketNameResponse{} + + err := internal.Call(c, "app_identity_service", "GetDefaultGcsBucketName", req, res) + if err != nil { + return "", fmt.Errorf("file: no default bucket name returned in RPC response: %v", res) + } + return res.GetDefaultGcsBucketName(), nil +} diff --git a/vendor/google.golang.org/appengine/identity.go b/vendor/google.golang.org/appengine/identity.go new file mode 100644 index 000000000..b8dcf8f36 --- /dev/null +++ b/vendor/google.golang.org/appengine/identity.go @@ -0,0 +1,142 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package appengine + +import ( + "time" + + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/app_identity" + modpb "google.golang.org/appengine/internal/modules" +) + +// AppID returns the application ID for the current application. +// The string will be a plain application ID (e.g. "appid"), with a +// domain prefix for custom domain deployments (e.g. "example.com:appid"). +func AppID(c context.Context) string { return internal.AppID(c) } + +// DefaultVersionHostname returns the standard hostname of the default version +// of the current application (e.g. "my-app.appspot.com"). This is suitable for +// use in constructing URLs. +func DefaultVersionHostname(c context.Context) string { + return internal.DefaultVersionHostname(c) +} + +// ModuleName returns the module name of the current instance. +func ModuleName(c context.Context) string { + return internal.ModuleName(c) +} + +// ModuleHostname returns a hostname of a module instance. +// If module is the empty string, it refers to the module of the current instance. +// If version is empty, it refers to the version of the current instance if valid, +// or the default version of the module of the current instance. +// If instance is empty, ModuleHostname returns the load-balancing hostname. +func ModuleHostname(c context.Context, module, version, instance string) (string, error) { + req := &modpb.GetHostnameRequest{} + if module != "" { + req.Module = &module + } + if version != "" { + req.Version = &version + } + if instance != "" { + req.Instance = &instance + } + res := &modpb.GetHostnameResponse{} + if err := internal.Call(c, "modules", "GetHostname", req, res); err != nil { + return "", err + } + return *res.Hostname, nil +} + +// VersionID returns the version ID for the current application. +// It will be of the form "X.Y", where X is specified in app.yaml, +// and Y is a number generated when each version of the app is uploaded. +// It does not include a module name. +func VersionID(c context.Context) string { return internal.VersionID(c) } + +// InstanceID returns a mostly-unique identifier for this instance. +func InstanceID() string { return internal.InstanceID() } + +// Datacenter returns an identifier for the datacenter that the instance is running in. +func Datacenter(c context.Context) string { return internal.Datacenter(c) } + +// ServerSoftware returns the App Engine release version. +// In production, it looks like "Google App Engine/X.Y.Z". +// In the development appserver, it looks like "Development/X.Y". +func ServerSoftware() string { return internal.ServerSoftware() } + +// RequestID returns a string that uniquely identifies the request. +func RequestID(c context.Context) string { return internal.RequestID(c) } + +// AccessToken generates an OAuth2 access token for the specified scopes on +// behalf of service account of this application. This token will expire after +// the returned time. +func AccessToken(c context.Context, scopes ...string) (token string, expiry time.Time, err error) { + req := &pb.GetAccessTokenRequest{Scope: scopes} + res := &pb.GetAccessTokenResponse{} + + err = internal.Call(c, "app_identity_service", "GetAccessToken", req, res) + if err != nil { + return "", time.Time{}, err + } + return res.GetAccessToken(), time.Unix(res.GetExpirationTime(), 0), nil +} + +// Certificate represents a public certificate for the app. +type Certificate struct { + KeyName string + Data []byte // PEM-encoded X.509 certificate +} + +// PublicCertificates retrieves the public certificates for the app. +// They can be used to verify a signature returned by SignBytes. +func PublicCertificates(c context.Context) ([]Certificate, error) { + req := &pb.GetPublicCertificateForAppRequest{} + res := &pb.GetPublicCertificateForAppResponse{} + if err := internal.Call(c, "app_identity_service", "GetPublicCertificatesForApp", req, res); err != nil { + return nil, err + } + var cs []Certificate + for _, pc := range res.PublicCertificateList { + cs = append(cs, Certificate{ + KeyName: pc.GetKeyName(), + Data: []byte(pc.GetX509CertificatePem()), + }) + } + return cs, nil +} + +// ServiceAccount returns a string representing the service account name, in +// the form of an email address (typically app_id@appspot.gserviceaccount.com). +func ServiceAccount(c context.Context) (string, error) { + req := &pb.GetServiceAccountNameRequest{} + res := &pb.GetServiceAccountNameResponse{} + + err := internal.Call(c, "app_identity_service", "GetServiceAccountName", req, res) + if err != nil { + return "", err + } + return res.GetServiceAccountName(), err +} + +// SignBytes signs bytes using a private key unique to your application. +func SignBytes(c context.Context, bytes []byte) (keyName string, signature []byte, err error) { + req := &pb.SignForAppRequest{BytesToSign: bytes} + res := &pb.SignForAppResponse{} + + if err := internal.Call(c, "app_identity_service", "SignForApp", req, res); err != nil { + return "", nil, err + } + return res.GetKeyName(), res.GetSignatureBytes(), nil +} + +func init() { + internal.RegisterErrorCodeMap("app_identity_service", pb.AppIdentityServiceError_ErrorCode_name) + internal.RegisterErrorCodeMap("modules", modpb.ModulesServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/image/image.go b/vendor/google.golang.org/appengine/image/image.go new file mode 100644 index 000000000..780d53e17 --- /dev/null +++ b/vendor/google.golang.org/appengine/image/image.go @@ -0,0 +1,67 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package image provides image services. +package image + +import ( + "fmt" + "net/url" + + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/image" +) + +type ServingURLOptions struct { + Secure bool // whether the URL should use HTTPS + + // Size must be between zero and 1600. + // If Size is non-zero, a resized version of the image is served, + // and Size is the served image's longest dimension. The aspect ratio is preserved. + // If Crop is true the image is cropped from the center instead of being resized. + Size int + Crop bool +} + +// ServingURL returns a URL that will serve an image from Blobstore. +func ServingURL(c context.Context, key appengine.BlobKey, opts *ServingURLOptions) (*url.URL, error) { + req := &pb.ImagesGetUrlBaseRequest{ + BlobKey: (*string)(&key), + } + if opts != nil && opts.Secure { + req.CreateSecureUrl = &opts.Secure + } + res := &pb.ImagesGetUrlBaseResponse{} + if err := internal.Call(c, "images", "GetUrlBase", req, res); err != nil { + return nil, err + } + + // The URL may have suffixes added to dynamically resize or crop: + // - adding "=s32" will serve the image resized to 32 pixels, preserving the aspect ratio. + // - adding "=s32-c" is the same as "=s32" except it will be cropped. + u := *res.Url + if opts != nil && opts.Size > 0 { + u += fmt.Sprintf("=s%d", opts.Size) + if opts.Crop { + u += "-c" + } + } + return url.Parse(u) +} + +// DeleteServingURL deletes the serving URL for an image. +func DeleteServingURL(c context.Context, key appengine.BlobKey) error { + req := &pb.ImagesDeleteUrlBaseRequest{ + BlobKey: (*string)(&key), + } + res := &pb.ImagesDeleteUrlBaseResponse{} + return internal.Call(c, "images", "DeleteUrlBase", req, res) +} + +func init() { + internal.RegisterErrorCodeMap("images", pb.ImagesServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/internal/aetesting/fake.go b/vendor/google.golang.org/appengine/internal/aetesting/fake.go new file mode 100644 index 000000000..6f5c1977f --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/aetesting/fake.go @@ -0,0 +1,80 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package aetesting provides utilities for testing App Engine packages. +// This is not for testing user applications. +package aetesting + +import ( + "fmt" + "reflect" + "testing" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" +) + +// FakeSingleContext returns a context whose Call invocations will be serviced +// by f, which should be a function that has two arguments of the input and output +// protocol buffer type, and one error return. +func FakeSingleContext(t *testing.T, service, method string, f interface{}) context.Context { + fv := reflect.ValueOf(f) + if fv.Kind() != reflect.Func { + t.Fatal("not a function") + } + ft := fv.Type() + if ft.NumIn() != 2 || ft.NumOut() != 1 { + t.Fatalf("f has %d in and %d out, want 2 in and 1 out", ft.NumIn(), ft.NumOut()) + } + for i := 0; i < 2; i++ { + at := ft.In(i) + if !at.Implements(protoMessageType) { + t.Fatalf("arg %d does not implement proto.Message", i) + } + } + if ft.Out(0) != errorType { + t.Fatalf("f's return is %v, want error", ft.Out(0)) + } + s := &single{ + t: t, + service: service, + method: method, + f: fv, + } + return internal.WithCallOverride(context.Background(), s.call) +} + +var ( + protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() + errorType = reflect.TypeOf((*error)(nil)).Elem() +) + +type single struct { + t *testing.T + service, method string + f reflect.Value +} + +func (s *single) call(ctx context.Context, service, method string, in, out proto.Message) error { + if service == "__go__" { + if method == "GetNamespace" { + return nil // always yield an empty namespace + } + return fmt.Errorf("Unknown API call /%s.%s", service, method) + } + if service != s.service || method != s.method { + s.t.Fatalf("Unexpected call to /%s.%s", service, method) + } + ins := []reflect.Value{ + reflect.ValueOf(in), + reflect.ValueOf(out), + } + outs := s.f.Call(ins) + if outs[0].IsNil() { + return nil + } + return outs[0].Interface().(error) +} diff --git a/vendor/google.golang.org/appengine/internal/api.go b/vendor/google.golang.org/appengine/internal/api.go new file mode 100644 index 000000000..aa139d4d5 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/api.go @@ -0,0 +1,640 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine + +package internal + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "net/url" + "os" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/golang/protobuf/proto" + netcontext "golang.org/x/net/context" + + basepb "google.golang.org/appengine/internal/base" + logpb "google.golang.org/appengine/internal/log" + remotepb "google.golang.org/appengine/internal/remote_api" +) + +const ( + apiPath = "/rpc_http" +) + +var ( + // Incoming headers. + ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket") + dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo") + traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context") + curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") + userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP") + remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr") + + // Outgoing headers. + apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint") + apiEndpointHeaderValue = []string{"app-engine-apis"} + apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method") + apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"} + apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline") + apiContentType = http.CanonicalHeaderKey("Content-Type") + apiContentTypeValue = []string{"application/octet-stream"} + logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count") + + apiHTTPClient = &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: limitDial, + }, + } +) + +func apiURL() *url.URL { + host, port := "appengine.googleapis.internal", "10001" + if h := os.Getenv("API_HOST"); h != "" { + host = h + } + if p := os.Getenv("API_PORT"); p != "" { + port = p + } + return &url.URL{ + Scheme: "http", + Host: host + ":" + port, + Path: apiPath, + } +} + +func handleHTTP(w http.ResponseWriter, r *http.Request) { + c := &context{ + req: r, + outHeader: w.Header(), + apiURL: apiURL(), + } + stopFlushing := make(chan int) + + ctxs.Lock() + ctxs.m[r] = c + ctxs.Unlock() + defer func() { + ctxs.Lock() + delete(ctxs.m, r) + ctxs.Unlock() + }() + + // Patch up RemoteAddr so it looks reasonable. + if addr := r.Header.Get(userIPHeader); addr != "" { + r.RemoteAddr = addr + } else if addr = r.Header.Get(remoteAddrHeader); addr != "" { + r.RemoteAddr = addr + } else { + // Should not normally reach here, but pick a sensible default anyway. + r.RemoteAddr = "127.0.0.1" + } + // The address in the headers will most likely be of these forms: + // 123.123.123.123 + // 2001:db8::1 + // net/http.Request.RemoteAddr is specified to be in "IP:port" form. + if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil { + // Assume the remote address is only a host; add a default port. + r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80") + } + + // Start goroutine responsible for flushing app logs. + // This is done after adding c to ctx.m (and stopped before removing it) + // because flushing logs requires making an API call. + go c.logFlusher(stopFlushing) + + executeRequestSafely(c, r) + c.outHeader = nil // make sure header changes aren't respected any more + + stopFlushing <- 1 // any logging beyond this point will be dropped + + // Flush any pending logs asynchronously. + c.pendingLogs.Lock() + flushes := c.pendingLogs.flushes + if len(c.pendingLogs.lines) > 0 { + flushes++ + } + c.pendingLogs.Unlock() + go c.flushLog(false) + w.Header().Set(logFlushHeader, strconv.Itoa(flushes)) + + // Avoid nil Write call if c.Write is never called. + if c.outCode != 0 { + w.WriteHeader(c.outCode) + } + if c.outBody != nil { + w.Write(c.outBody) + } +} + +func executeRequestSafely(c *context, r *http.Request) { + defer func() { + if x := recover(); x != nil { + logf(c, 4, "%s", renderPanic(x)) // 4 == critical + c.outCode = 500 + } + }() + + http.DefaultServeMux.ServeHTTP(c, r) +} + +func renderPanic(x interface{}) string { + buf := make([]byte, 16<<10) // 16 KB should be plenty + buf = buf[:runtime.Stack(buf, false)] + + // Remove the first few stack frames: + // this func + // the recover closure in the caller + // That will root the stack trace at the site of the panic. + const ( + skipStart = "internal.renderPanic" + skipFrames = 2 + ) + start := bytes.Index(buf, []byte(skipStart)) + p := start + for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ { + p = bytes.IndexByte(buf[p+1:], '\n') + p + 1 + if p < 0 { + break + } + } + if p >= 0 { + // buf[start:p+1] is the block to remove. + // Copy buf[p+1:] over buf[start:] and shrink buf. + copy(buf[start:], buf[p+1:]) + buf = buf[:len(buf)-(p+1-start)] + } + + // Add panic heading. + head := fmt.Sprintf("panic: %v\n\n", x) + if len(head) > len(buf) { + // Extremely unlikely to happen. + return head + } + copy(buf[len(head):], buf) + copy(buf, head) + + return string(buf) +} + +var ctxs = struct { + sync.Mutex + m map[*http.Request]*context + bg *context // background context, lazily initialized + // dec is used by tests to decorate the netcontext.Context returned + // for a given request. This allows tests to add overrides (such as + // WithAppIDOverride) to the context. The map is nil outside tests. + dec map[*http.Request]func(netcontext.Context) netcontext.Context +}{ + m: make(map[*http.Request]*context), +} + +// context represents the context of an in-flight HTTP request. +// It implements the appengine.Context and http.ResponseWriter interfaces. +type context struct { + req *http.Request + + outCode int + outHeader http.Header + outBody []byte + + pendingLogs struct { + sync.Mutex + lines []*logpb.UserAppLogLine + flushes int + } + + apiURL *url.URL +} + +var contextKey = "holds a *context" + +func fromContext(ctx netcontext.Context) *context { + c, _ := ctx.Value(&contextKey).(*context) + return c +} + +func withContext(parent netcontext.Context, c *context) netcontext.Context { + ctx := netcontext.WithValue(parent, &contextKey, c) + if ns := c.req.Header.Get(curNamespaceHeader); ns != "" { + ctx = withNamespace(ctx, ns) + } + return ctx +} + +func toContext(c *context) netcontext.Context { + return withContext(netcontext.Background(), c) +} + +func IncomingHeaders(ctx netcontext.Context) http.Header { + if c := fromContext(ctx); c != nil { + return c.req.Header + } + return nil +} + +func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { + ctxs.Lock() + c := ctxs.m[req] + d := ctxs.dec[req] + ctxs.Unlock() + + if d != nil { + parent = d(parent) + } + + if c == nil { + // Someone passed in an http.Request that is not in-flight. + // We panic here rather than panicking at a later point + // so that stack traces will be more sensible. + log.Panic("appengine: NewContext passed an unknown http.Request") + } + return withContext(parent, c) +} + +func BackgroundContext() netcontext.Context { + ctxs.Lock() + defer ctxs.Unlock() + + if ctxs.bg != nil { + return toContext(ctxs.bg) + } + + // Compute background security ticket. + appID := partitionlessAppID() + escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1) + majVersion := VersionID(nil) + if i := strings.Index(majVersion, "."); i > 0 { + majVersion = majVersion[:i] + } + ticket := fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID()) + + ctxs.bg = &context{ + req: &http.Request{ + Header: http.Header{ + ticketHeader: []string{ticket}, + }, + }, + apiURL: apiURL(), + } + + // TODO(dsymonds): Wire up the shutdown handler to do a final flush. + go ctxs.bg.logFlusher(make(chan int)) + + return toContext(ctxs.bg) +} + +// RegisterTestRequest registers the HTTP request req for testing, such that +// any API calls are sent to the provided URL. It returns a closure to delete +// the registration. +// It should only be used by aetest package. +func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) func() { + c := &context{ + req: req, + apiURL: apiURL, + } + ctxs.Lock() + defer ctxs.Unlock() + if _, ok := ctxs.m[req]; ok { + log.Panic("req already associated with context") + } + if _, ok := ctxs.dec[req]; ok { + log.Panic("req already associated with context") + } + if ctxs.dec == nil { + ctxs.dec = make(map[*http.Request]func(netcontext.Context) netcontext.Context) + } + ctxs.m[req] = c + ctxs.dec[req] = decorate + + return func() { + ctxs.Lock() + delete(ctxs.m, req) + delete(ctxs.dec, req) + ctxs.Unlock() + } +} + +var errTimeout = &CallError{ + Detail: "Deadline exceeded", + Code: int32(remotepb.RpcError_CANCELLED), + Timeout: true, +} + +func (c *context) Header() http.Header { return c.outHeader } + +// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status +// codes do not permit a response body (nor response entity headers such as +// Content-Length, Content-Type, etc). +func bodyAllowedForStatus(status int) bool { + switch { + case status >= 100 && status <= 199: + return false + case status == 204: + return false + case status == 304: + return false + } + return true +} + +func (c *context) Write(b []byte) (int, error) { + if c.outCode == 0 { + c.WriteHeader(http.StatusOK) + } + if len(b) > 0 && !bodyAllowedForStatus(c.outCode) { + return 0, http.ErrBodyNotAllowed + } + c.outBody = append(c.outBody, b...) + return len(b), nil +} + +func (c *context) WriteHeader(code int) { + if c.outCode != 0 { + logf(c, 3, "WriteHeader called multiple times on request.") // error level + return + } + c.outCode = code +} + +func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) { + hreq := &http.Request{ + Method: "POST", + URL: c.apiURL, + Header: http.Header{ + apiEndpointHeader: apiEndpointHeaderValue, + apiMethodHeader: apiMethodHeaderValue, + apiContentType: apiContentTypeValue, + apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)}, + }, + Body: ioutil.NopCloser(bytes.NewReader(body)), + ContentLength: int64(len(body)), + Host: c.apiURL.Host, + } + if info := c.req.Header.Get(dapperHeader); info != "" { + hreq.Header.Set(dapperHeader, info) + } + if info := c.req.Header.Get(traceHeader); info != "" { + hreq.Header.Set(traceHeader, info) + } + + tr := apiHTTPClient.Transport.(*http.Transport) + + var timedOut int32 // atomic; set to 1 if timed out + t := time.AfterFunc(timeout, func() { + atomic.StoreInt32(&timedOut, 1) + tr.CancelRequest(hreq) + }) + defer t.Stop() + defer func() { + // Check if timeout was exceeded. + if atomic.LoadInt32(&timedOut) != 0 { + err = errTimeout + } + }() + + hresp, err := apiHTTPClient.Do(hreq) + if err != nil { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + defer hresp.Body.Close() + hrespBody, err := ioutil.ReadAll(hresp.Body) + if hresp.StatusCode != 200 { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + if err != nil { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge response bad: %v", err), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + return hrespBody, nil +} + +func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + if f, ctx, ok := callOverrideFromContext(ctx); ok { + return f(ctx, service, method, in, out) + } + + // Handle already-done contexts quickly. + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + c := fromContext(ctx) + if c == nil { + // Give a good error message rather than a panic lower down. + return errors.New("not an App Engine context") + } + + // Apply transaction modifications if we're in a transaction. + if t := transactionFromContext(ctx); t != nil { + if t.finished { + return errors.New("transaction context has expired") + } + applyTransaction(in, &t.transaction) + } + + // Default RPC timeout is 60s. + timeout := 60 * time.Second + if deadline, ok := ctx.Deadline(); ok { + timeout = deadline.Sub(time.Now()) + } + + data, err := proto.Marshal(in) + if err != nil { + return err + } + + ticket := c.req.Header.Get(ticketHeader) + req := &remotepb.Request{ + ServiceName: &service, + Method: &method, + Request: data, + RequestId: &ticket, + } + hreqBody, err := proto.Marshal(req) + if err != nil { + return err + } + + hrespBody, err := c.post(hreqBody, timeout) + if err != nil { + return err + } + + res := &remotepb.Response{} + if err := proto.Unmarshal(hrespBody, res); err != nil { + return err + } + if res.RpcError != nil { + ce := &CallError{ + Detail: res.RpcError.GetDetail(), + Code: *res.RpcError.Code, + } + switch remotepb.RpcError_ErrorCode(ce.Code) { + case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED: + ce.Timeout = true + } + return ce + } + if res.ApplicationError != nil { + return &APIError{ + Service: *req.ServiceName, + Detail: res.ApplicationError.GetDetail(), + Code: *res.ApplicationError.Code, + } + } + if res.Exception != nil || res.JavaException != nil { + // This shouldn't happen, but let's be defensive. + return &CallError{ + Detail: "service bridge returned exception", + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + return proto.Unmarshal(res.Response, out) +} + +func (c *context) Request() *http.Request { + return c.req +} + +func (c *context) addLogLine(ll *logpb.UserAppLogLine) { + // Truncate long log lines. + // TODO(dsymonds): Check if this is still necessary. + const lim = 8 << 10 + if len(*ll.Message) > lim { + suffix := fmt.Sprintf("...(length %d)", len(*ll.Message)) + ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix) + } + + c.pendingLogs.Lock() + c.pendingLogs.lines = append(c.pendingLogs.lines, ll) + c.pendingLogs.Unlock() +} + +var logLevelName = map[int64]string{ + 0: "DEBUG", + 1: "INFO", + 2: "WARNING", + 3: "ERROR", + 4: "CRITICAL", +} + +func logf(c *context, level int64, format string, args ...interface{}) { + s := fmt.Sprintf(format, args...) + s = strings.TrimRight(s, "\n") // Remove any trailing newline characters. + c.addLogLine(&logpb.UserAppLogLine{ + TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3), + Level: &level, + Message: &s, + }) + log.Print(logLevelName[level] + ": " + s) +} + +// flushLog attempts to flush any pending logs to the appserver. +// It should not be called concurrently. +func (c *context) flushLog(force bool) (flushed bool) { + c.pendingLogs.Lock() + // Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious. + n, rem := 0, 30<<20 + for ; n < len(c.pendingLogs.lines); n++ { + ll := c.pendingLogs.lines[n] + // Each log line will require about 3 bytes of overhead. + nb := proto.Size(ll) + 3 + if nb > rem { + break + } + rem -= nb + } + lines := c.pendingLogs.lines[:n] + c.pendingLogs.lines = c.pendingLogs.lines[n:] + c.pendingLogs.Unlock() + + if len(lines) == 0 && !force { + // Nothing to flush. + return false + } + + rescueLogs := false + defer func() { + if rescueLogs { + c.pendingLogs.Lock() + c.pendingLogs.lines = append(lines, c.pendingLogs.lines...) + c.pendingLogs.Unlock() + } + }() + + buf, err := proto.Marshal(&logpb.UserAppLogGroup{ + LogLine: lines, + }) + if err != nil { + log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err) + rescueLogs = true + return false + } + + req := &logpb.FlushRequest{ + Logs: buf, + } + res := &basepb.VoidProto{} + c.pendingLogs.Lock() + c.pendingLogs.flushes++ + c.pendingLogs.Unlock() + if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil { + log.Printf("internal.flushLog: Flush RPC: %v", err) + rescueLogs = true + return false + } + return true +} + +const ( + // Log flushing parameters. + flushInterval = 1 * time.Second + forceFlushInterval = 60 * time.Second +) + +func (c *context) logFlusher(stop <-chan int) { + lastFlush := time.Now() + tick := time.NewTicker(flushInterval) + for { + select { + case <-stop: + // Request finished. + tick.Stop() + return + case <-tick.C: + force := time.Now().Sub(lastFlush) > forceFlushInterval + if c.flushLog(force) { + lastFlush = time.Now() + } + } + } +} + +func ContextForTesting(req *http.Request) netcontext.Context { + return toContext(&context{req: req}) +} diff --git a/vendor/google.golang.org/appengine/internal/api_classic.go b/vendor/google.golang.org/appengine/internal/api_classic.go new file mode 100644 index 000000000..1c072e9db --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/api_classic.go @@ -0,0 +1,133 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import ( + "errors" + "net/http" + "time" + + "appengine" + "appengine_internal" + basepb "appengine_internal/base" + + "github.com/golang/protobuf/proto" + netcontext "golang.org/x/net/context" +) + +var contextKey = "holds an appengine.Context" + +func fromContext(ctx netcontext.Context) appengine.Context { + c, _ := ctx.Value(&contextKey).(appengine.Context) + return c +} + +// This is only for classic App Engine adapters. +func ClassicContextFromContext(ctx netcontext.Context) appengine.Context { + return fromContext(ctx) +} + +func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context { + ctx := netcontext.WithValue(parent, &contextKey, c) + + s := &basepb.StringProto{} + c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil) + if ns := s.GetValue(); ns != "" { + ctx = NamespacedContext(ctx, ns) + } + + return ctx +} + +func IncomingHeaders(ctx netcontext.Context) http.Header { + if c := fromContext(ctx); c != nil { + if req, ok := c.Request().(*http.Request); ok { + return req.Header + } + } + return nil +} + +func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { + c := appengine.NewContext(req) + return withContext(parent, c) +} + +func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + if f, ctx, ok := callOverrideFromContext(ctx); ok { + return f(ctx, service, method, in, out) + } + + // Handle already-done contexts quickly. + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + c := fromContext(ctx) + if c == nil { + // Give a good error message rather than a panic lower down. + return errors.New("not an App Engine context") + } + + // Apply transaction modifications if we're in a transaction. + if t := transactionFromContext(ctx); t != nil { + if t.finished { + return errors.New("transaction context has expired") + } + applyTransaction(in, &t.transaction) + } + + var opts *appengine_internal.CallOptions + if d, ok := ctx.Deadline(); ok { + opts = &appengine_internal.CallOptions{ + Timeout: d.Sub(time.Now()), + } + } + + err := c.Call(service, method, in, out, opts) + switch v := err.(type) { + case *appengine_internal.APIError: + return &APIError{ + Service: v.Service, + Detail: v.Detail, + Code: v.Code, + } + case *appengine_internal.CallError: + return &CallError{ + Detail: v.Detail, + Code: v.Code, + Timeout: v.Timeout, + } + } + return err +} + +func handleHTTP(w http.ResponseWriter, r *http.Request) { + panic("handleHTTP called; this should be impossible") +} + +func logf(c appengine.Context, level int64, format string, args ...interface{}) { + var fn func(format string, args ...interface{}) + switch level { + case 0: + fn = c.Debugf + case 1: + fn = c.Infof + case 2: + fn = c.Warningf + case 3: + fn = c.Errorf + case 4: + fn = c.Criticalf + default: + // This shouldn't happen. + fn = c.Criticalf + } + fn(format, args...) +} diff --git a/vendor/google.golang.org/appengine/internal/api_common.go b/vendor/google.golang.org/appengine/internal/api_common.go new file mode 100644 index 000000000..ec5383e66 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/api_common.go @@ -0,0 +1,101 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +import ( + "github.com/golang/protobuf/proto" + netcontext "golang.org/x/net/context" +) + +type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error + +var callOverrideKey = "holds []CallOverrideFunc" + +func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context { + // We avoid appending to any existing call override + // so we don't risk overwriting a popped stack below. + var cofs []CallOverrideFunc + if uf, ok := ctx.Value(&callOverrideKey).([]CallOverrideFunc); ok { + cofs = append(cofs, uf...) + } + cofs = append(cofs, f) + return netcontext.WithValue(ctx, &callOverrideKey, cofs) +} + +func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) { + cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc) + if len(cofs) == 0 { + return nil, nil, false + } + // We found a list of overrides; grab the last, and reconstitute a + // context that will hide it. + f := cofs[len(cofs)-1] + ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1]) + return f, ctx, true +} + +type logOverrideFunc func(level int64, format string, args ...interface{}) + +var logOverrideKey = "holds a logOverrideFunc" + +func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context { + return netcontext.WithValue(ctx, &logOverrideKey, f) +} + +var appIDOverrideKey = "holds a string, being the full app ID" + +func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context { + return netcontext.WithValue(ctx, &appIDOverrideKey, appID) +} + +var namespaceKey = "holds the namespace string" + +func withNamespace(ctx netcontext.Context, ns string) netcontext.Context { + return netcontext.WithValue(ctx, &namespaceKey, ns) +} + +func NamespaceFromContext(ctx netcontext.Context) string { + // If there's no namespace, return the empty string. + ns, _ := ctx.Value(&namespaceKey).(string) + return ns +} + +// FullyQualifiedAppID returns the fully-qualified application ID. +// This may contain a partition prefix (e.g. "s~" for High Replication apps), +// or a domain prefix (e.g. "example.com:"). +func FullyQualifiedAppID(ctx netcontext.Context) string { + if id, ok := ctx.Value(&appIDOverrideKey).(string); ok { + return id + } + return fullyQualifiedAppID(ctx) +} + +func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) { + if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok { + f(level, format, args...) + return + } + logf(fromContext(ctx), level, format, args...) +} + +// NamespacedContext wraps a Context to support namespaces. +func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context { + n := &namespacedContext{ + namespace: namespace, + } + return withNamespace(WithCallOverride(ctx, n.call), namespace) +} + +type namespacedContext struct { + namespace string +} + +func (n *namespacedContext) call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + // Apply any namespace mods. + if mod, ok := NamespaceMods[service]; ok { + mod(in, n.namespace) + } + return Call(ctx, service, method, in, out) +} diff --git a/vendor/google.golang.org/appengine/internal/app_id.go b/vendor/google.golang.org/appengine/internal/app_id.go new file mode 100644 index 000000000..11df8c07b --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/app_id.go @@ -0,0 +1,28 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +import ( + "strings" +) + +func parseFullAppID(appid string) (partition, domain, displayID string) { + if i := strings.Index(appid, "~"); i != -1 { + partition, appid = appid[:i], appid[i+1:] + } + if i := strings.Index(appid, ":"); i != -1 { + domain, appid = appid[:i], appid[i+1:] + } + return partition, domain, appid +} + +// appID returns "appid" or "domain.com:appid". +func appID(fullAppID string) string { + _, dom, dis := parseFullAppID(fullAppID) + if dom != "" { + return dom + ":" + dis + } + return dis +} diff --git a/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go new file mode 100644 index 000000000..87d9701b8 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go @@ -0,0 +1,296 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/app_identity/app_identity_service.proto +// DO NOT EDIT! + +/* +Package app_identity is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/app_identity/app_identity_service.proto + +It has these top-level messages: + AppIdentityServiceError + SignForAppRequest + SignForAppResponse + GetPublicCertificateForAppRequest + PublicCertificate + GetPublicCertificateForAppResponse + GetServiceAccountNameRequest + GetServiceAccountNameResponse + GetAccessTokenRequest + GetAccessTokenResponse + GetDefaultGcsBucketNameRequest + GetDefaultGcsBucketNameResponse +*/ +package app_identity + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type AppIdentityServiceError_ErrorCode int32 + +const ( + AppIdentityServiceError_SUCCESS AppIdentityServiceError_ErrorCode = 0 + AppIdentityServiceError_UNKNOWN_SCOPE AppIdentityServiceError_ErrorCode = 9 + AppIdentityServiceError_BLOB_TOO_LARGE AppIdentityServiceError_ErrorCode = 1000 + AppIdentityServiceError_DEADLINE_EXCEEDED AppIdentityServiceError_ErrorCode = 1001 + AppIdentityServiceError_NOT_A_VALID_APP AppIdentityServiceError_ErrorCode = 1002 + AppIdentityServiceError_UNKNOWN_ERROR AppIdentityServiceError_ErrorCode = 1003 + AppIdentityServiceError_NOT_ALLOWED AppIdentityServiceError_ErrorCode = 1005 + AppIdentityServiceError_NOT_IMPLEMENTED AppIdentityServiceError_ErrorCode = 1006 +) + +var AppIdentityServiceError_ErrorCode_name = map[int32]string{ + 0: "SUCCESS", + 9: "UNKNOWN_SCOPE", + 1000: "BLOB_TOO_LARGE", + 1001: "DEADLINE_EXCEEDED", + 1002: "NOT_A_VALID_APP", + 1003: "UNKNOWN_ERROR", + 1005: "NOT_ALLOWED", + 1006: "NOT_IMPLEMENTED", +} +var AppIdentityServiceError_ErrorCode_value = map[string]int32{ + "SUCCESS": 0, + "UNKNOWN_SCOPE": 9, + "BLOB_TOO_LARGE": 1000, + "DEADLINE_EXCEEDED": 1001, + "NOT_A_VALID_APP": 1002, + "UNKNOWN_ERROR": 1003, + "NOT_ALLOWED": 1005, + "NOT_IMPLEMENTED": 1006, +} + +func (x AppIdentityServiceError_ErrorCode) Enum() *AppIdentityServiceError_ErrorCode { + p := new(AppIdentityServiceError_ErrorCode) + *p = x + return p +} +func (x AppIdentityServiceError_ErrorCode) String() string { + return proto.EnumName(AppIdentityServiceError_ErrorCode_name, int32(x)) +} +func (x *AppIdentityServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(AppIdentityServiceError_ErrorCode_value, data, "AppIdentityServiceError_ErrorCode") + if err != nil { + return err + } + *x = AppIdentityServiceError_ErrorCode(value) + return nil +} + +type AppIdentityServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *AppIdentityServiceError) Reset() { *m = AppIdentityServiceError{} } +func (m *AppIdentityServiceError) String() string { return proto.CompactTextString(m) } +func (*AppIdentityServiceError) ProtoMessage() {} + +type SignForAppRequest struct { + BytesToSign []byte `protobuf:"bytes,1,opt,name=bytes_to_sign" json:"bytes_to_sign,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignForAppRequest) Reset() { *m = SignForAppRequest{} } +func (m *SignForAppRequest) String() string { return proto.CompactTextString(m) } +func (*SignForAppRequest) ProtoMessage() {} + +func (m *SignForAppRequest) GetBytesToSign() []byte { + if m != nil { + return m.BytesToSign + } + return nil +} + +type SignForAppResponse struct { + KeyName *string `protobuf:"bytes,1,opt,name=key_name" json:"key_name,omitempty"` + SignatureBytes []byte `protobuf:"bytes,2,opt,name=signature_bytes" json:"signature_bytes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SignForAppResponse) Reset() { *m = SignForAppResponse{} } +func (m *SignForAppResponse) String() string { return proto.CompactTextString(m) } +func (*SignForAppResponse) ProtoMessage() {} + +func (m *SignForAppResponse) GetKeyName() string { + if m != nil && m.KeyName != nil { + return *m.KeyName + } + return "" +} + +func (m *SignForAppResponse) GetSignatureBytes() []byte { + if m != nil { + return m.SignatureBytes + } + return nil +} + +type GetPublicCertificateForAppRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetPublicCertificateForAppRequest) Reset() { *m = GetPublicCertificateForAppRequest{} } +func (m *GetPublicCertificateForAppRequest) String() string { return proto.CompactTextString(m) } +func (*GetPublicCertificateForAppRequest) ProtoMessage() {} + +type PublicCertificate struct { + KeyName *string `protobuf:"bytes,1,opt,name=key_name" json:"key_name,omitempty"` + X509CertificatePem *string `protobuf:"bytes,2,opt,name=x509_certificate_pem" json:"x509_certificate_pem,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PublicCertificate) Reset() { *m = PublicCertificate{} } +func (m *PublicCertificate) String() string { return proto.CompactTextString(m) } +func (*PublicCertificate) ProtoMessage() {} + +func (m *PublicCertificate) GetKeyName() string { + if m != nil && m.KeyName != nil { + return *m.KeyName + } + return "" +} + +func (m *PublicCertificate) GetX509CertificatePem() string { + if m != nil && m.X509CertificatePem != nil { + return *m.X509CertificatePem + } + return "" +} + +type GetPublicCertificateForAppResponse struct { + PublicCertificateList []*PublicCertificate `protobuf:"bytes,1,rep,name=public_certificate_list" json:"public_certificate_list,omitempty"` + MaxClientCacheTimeInSecond *int64 `protobuf:"varint,2,opt,name=max_client_cache_time_in_second" json:"max_client_cache_time_in_second,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetPublicCertificateForAppResponse) Reset() { *m = GetPublicCertificateForAppResponse{} } +func (m *GetPublicCertificateForAppResponse) String() string { return proto.CompactTextString(m) } +func (*GetPublicCertificateForAppResponse) ProtoMessage() {} + +func (m *GetPublicCertificateForAppResponse) GetPublicCertificateList() []*PublicCertificate { + if m != nil { + return m.PublicCertificateList + } + return nil +} + +func (m *GetPublicCertificateForAppResponse) GetMaxClientCacheTimeInSecond() int64 { + if m != nil && m.MaxClientCacheTimeInSecond != nil { + return *m.MaxClientCacheTimeInSecond + } + return 0 +} + +type GetServiceAccountNameRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetServiceAccountNameRequest) Reset() { *m = GetServiceAccountNameRequest{} } +func (m *GetServiceAccountNameRequest) String() string { return proto.CompactTextString(m) } +func (*GetServiceAccountNameRequest) ProtoMessage() {} + +type GetServiceAccountNameResponse struct { + ServiceAccountName *string `protobuf:"bytes,1,opt,name=service_account_name" json:"service_account_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetServiceAccountNameResponse) Reset() { *m = GetServiceAccountNameResponse{} } +func (m *GetServiceAccountNameResponse) String() string { return proto.CompactTextString(m) } +func (*GetServiceAccountNameResponse) ProtoMessage() {} + +func (m *GetServiceAccountNameResponse) GetServiceAccountName() string { + if m != nil && m.ServiceAccountName != nil { + return *m.ServiceAccountName + } + return "" +} + +type GetAccessTokenRequest struct { + Scope []string `protobuf:"bytes,1,rep,name=scope" json:"scope,omitempty"` + ServiceAccountId *int64 `protobuf:"varint,2,opt,name=service_account_id" json:"service_account_id,omitempty"` + ServiceAccountName *string `protobuf:"bytes,3,opt,name=service_account_name" json:"service_account_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetAccessTokenRequest) Reset() { *m = GetAccessTokenRequest{} } +func (m *GetAccessTokenRequest) String() string { return proto.CompactTextString(m) } +func (*GetAccessTokenRequest) ProtoMessage() {} + +func (m *GetAccessTokenRequest) GetScope() []string { + if m != nil { + return m.Scope + } + return nil +} + +func (m *GetAccessTokenRequest) GetServiceAccountId() int64 { + if m != nil && m.ServiceAccountId != nil { + return *m.ServiceAccountId + } + return 0 +} + +func (m *GetAccessTokenRequest) GetServiceAccountName() string { + if m != nil && m.ServiceAccountName != nil { + return *m.ServiceAccountName + } + return "" +} + +type GetAccessTokenResponse struct { + AccessToken *string `protobuf:"bytes,1,opt,name=access_token" json:"access_token,omitempty"` + ExpirationTime *int64 `protobuf:"varint,2,opt,name=expiration_time" json:"expiration_time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetAccessTokenResponse) Reset() { *m = GetAccessTokenResponse{} } +func (m *GetAccessTokenResponse) String() string { return proto.CompactTextString(m) } +func (*GetAccessTokenResponse) ProtoMessage() {} + +func (m *GetAccessTokenResponse) GetAccessToken() string { + if m != nil && m.AccessToken != nil { + return *m.AccessToken + } + return "" +} + +func (m *GetAccessTokenResponse) GetExpirationTime() int64 { + if m != nil && m.ExpirationTime != nil { + return *m.ExpirationTime + } + return 0 +} + +type GetDefaultGcsBucketNameRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetDefaultGcsBucketNameRequest) Reset() { *m = GetDefaultGcsBucketNameRequest{} } +func (m *GetDefaultGcsBucketNameRequest) String() string { return proto.CompactTextString(m) } +func (*GetDefaultGcsBucketNameRequest) ProtoMessage() {} + +type GetDefaultGcsBucketNameResponse struct { + DefaultGcsBucketName *string `protobuf:"bytes,1,opt,name=default_gcs_bucket_name" json:"default_gcs_bucket_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetDefaultGcsBucketNameResponse) Reset() { *m = GetDefaultGcsBucketNameResponse{} } +func (m *GetDefaultGcsBucketNameResponse) String() string { return proto.CompactTextString(m) } +func (*GetDefaultGcsBucketNameResponse) ProtoMessage() {} + +func (m *GetDefaultGcsBucketNameResponse) GetDefaultGcsBucketName() string { + if m != nil && m.DefaultGcsBucketName != nil { + return *m.DefaultGcsBucketName + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto new file mode 100644 index 000000000..19610ca5b --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto @@ -0,0 +1,64 @@ +syntax = "proto2"; +option go_package = "app_identity"; + +package appengine; + +message AppIdentityServiceError { + enum ErrorCode { + SUCCESS = 0; + UNKNOWN_SCOPE = 9; + BLOB_TOO_LARGE = 1000; + DEADLINE_EXCEEDED = 1001; + NOT_A_VALID_APP = 1002; + UNKNOWN_ERROR = 1003; + NOT_ALLOWED = 1005; + NOT_IMPLEMENTED = 1006; + } +} + +message SignForAppRequest { + optional bytes bytes_to_sign = 1; +} + +message SignForAppResponse { + optional string key_name = 1; + optional bytes signature_bytes = 2; +} + +message GetPublicCertificateForAppRequest { +} + +message PublicCertificate { + optional string key_name = 1; + optional string x509_certificate_pem = 2; +} + +message GetPublicCertificateForAppResponse { + repeated PublicCertificate public_certificate_list = 1; + optional int64 max_client_cache_time_in_second = 2; +} + +message GetServiceAccountNameRequest { +} + +message GetServiceAccountNameResponse { + optional string service_account_name = 1; +} + +message GetAccessTokenRequest { + repeated string scope = 1; + optional int64 service_account_id = 2; + optional string service_account_name = 3; +} + +message GetAccessTokenResponse { + optional string access_token = 1; + optional int64 expiration_time = 2; +} + +message GetDefaultGcsBucketNameRequest { +} + +message GetDefaultGcsBucketNameResponse { + optional string default_gcs_bucket_name = 1; +} diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.pb.go b/vendor/google.golang.org/appengine/internal/base/api_base.pb.go new file mode 100644 index 000000000..36a195650 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/base/api_base.pb.go @@ -0,0 +1,133 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/base/api_base.proto +// DO NOT EDIT! + +/* +Package base is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/base/api_base.proto + +It has these top-level messages: + StringProto + Integer32Proto + Integer64Proto + BoolProto + DoubleProto + BytesProto + VoidProto +*/ +package base + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type StringProto struct { + Value *string `protobuf:"bytes,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StringProto) Reset() { *m = StringProto{} } +func (m *StringProto) String() string { return proto.CompactTextString(m) } +func (*StringProto) ProtoMessage() {} + +func (m *StringProto) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +type Integer32Proto struct { + Value *int32 `protobuf:"varint,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Integer32Proto) Reset() { *m = Integer32Proto{} } +func (m *Integer32Proto) String() string { return proto.CompactTextString(m) } +func (*Integer32Proto) ProtoMessage() {} + +func (m *Integer32Proto) GetValue() int32 { + if m != nil && m.Value != nil { + return *m.Value + } + return 0 +} + +type Integer64Proto struct { + Value *int64 `protobuf:"varint,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Integer64Proto) Reset() { *m = Integer64Proto{} } +func (m *Integer64Proto) String() string { return proto.CompactTextString(m) } +func (*Integer64Proto) ProtoMessage() {} + +func (m *Integer64Proto) GetValue() int64 { + if m != nil && m.Value != nil { + return *m.Value + } + return 0 +} + +type BoolProto struct { + Value *bool `protobuf:"varint,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BoolProto) Reset() { *m = BoolProto{} } +func (m *BoolProto) String() string { return proto.CompactTextString(m) } +func (*BoolProto) ProtoMessage() {} + +func (m *BoolProto) GetValue() bool { + if m != nil && m.Value != nil { + return *m.Value + } + return false +} + +type DoubleProto struct { + Value *float64 `protobuf:"fixed64,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DoubleProto) Reset() { *m = DoubleProto{} } +func (m *DoubleProto) String() string { return proto.CompactTextString(m) } +func (*DoubleProto) ProtoMessage() {} + +func (m *DoubleProto) GetValue() float64 { + if m != nil && m.Value != nil { + return *m.Value + } + return 0 +} + +type BytesProto struct { + Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BytesProto) Reset() { *m = BytesProto{} } +func (m *BytesProto) String() string { return proto.CompactTextString(m) } +func (*BytesProto) ProtoMessage() {} + +func (m *BytesProto) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type VoidProto struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *VoidProto) Reset() { *m = VoidProto{} } +func (m *VoidProto) String() string { return proto.CompactTextString(m) } +func (*VoidProto) ProtoMessage() {} diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.proto b/vendor/google.golang.org/appengine/internal/base/api_base.proto new file mode 100644 index 000000000..56cd7a3ca --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/base/api_base.proto @@ -0,0 +1,33 @@ +// Built-in base types for API calls. Primarily useful as return types. + +syntax = "proto2"; +option go_package = "base"; + +package appengine.base; + +message StringProto { + required string value = 1; +} + +message Integer32Proto { + required int32 value = 1; +} + +message Integer64Proto { + required int64 value = 1; +} + +message BoolProto { + required bool value = 1; +} + +message DoubleProto { + required double value = 1; +} + +message BytesProto { + required bytes value = 1 [ctype=CORD]; +} + +message VoidProto { +} diff --git a/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.pb.go b/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.pb.go new file mode 100644 index 000000000..8705ec348 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.pb.go @@ -0,0 +1,347 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/blobstore/blobstore_service.proto +// DO NOT EDIT! + +/* +Package blobstore is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/blobstore/blobstore_service.proto + +It has these top-level messages: + BlobstoreServiceError + CreateUploadURLRequest + CreateUploadURLResponse + DeleteBlobRequest + FetchDataRequest + FetchDataResponse + CloneBlobRequest + CloneBlobResponse + DecodeBlobKeyRequest + DecodeBlobKeyResponse + CreateEncodedGoogleStorageKeyRequest + CreateEncodedGoogleStorageKeyResponse +*/ +package blobstore + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type BlobstoreServiceError_ErrorCode int32 + +const ( + BlobstoreServiceError_OK BlobstoreServiceError_ErrorCode = 0 + BlobstoreServiceError_INTERNAL_ERROR BlobstoreServiceError_ErrorCode = 1 + BlobstoreServiceError_URL_TOO_LONG BlobstoreServiceError_ErrorCode = 2 + BlobstoreServiceError_PERMISSION_DENIED BlobstoreServiceError_ErrorCode = 3 + BlobstoreServiceError_BLOB_NOT_FOUND BlobstoreServiceError_ErrorCode = 4 + BlobstoreServiceError_DATA_INDEX_OUT_OF_RANGE BlobstoreServiceError_ErrorCode = 5 + BlobstoreServiceError_BLOB_FETCH_SIZE_TOO_LARGE BlobstoreServiceError_ErrorCode = 6 + BlobstoreServiceError_ARGUMENT_OUT_OF_RANGE BlobstoreServiceError_ErrorCode = 8 + BlobstoreServiceError_INVALID_BLOB_KEY BlobstoreServiceError_ErrorCode = 9 +) + +var BlobstoreServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INTERNAL_ERROR", + 2: "URL_TOO_LONG", + 3: "PERMISSION_DENIED", + 4: "BLOB_NOT_FOUND", + 5: "DATA_INDEX_OUT_OF_RANGE", + 6: "BLOB_FETCH_SIZE_TOO_LARGE", + 8: "ARGUMENT_OUT_OF_RANGE", + 9: "INVALID_BLOB_KEY", +} +var BlobstoreServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INTERNAL_ERROR": 1, + "URL_TOO_LONG": 2, + "PERMISSION_DENIED": 3, + "BLOB_NOT_FOUND": 4, + "DATA_INDEX_OUT_OF_RANGE": 5, + "BLOB_FETCH_SIZE_TOO_LARGE": 6, + "ARGUMENT_OUT_OF_RANGE": 8, + "INVALID_BLOB_KEY": 9, +} + +func (x BlobstoreServiceError_ErrorCode) Enum() *BlobstoreServiceError_ErrorCode { + p := new(BlobstoreServiceError_ErrorCode) + *p = x + return p +} +func (x BlobstoreServiceError_ErrorCode) String() string { + return proto.EnumName(BlobstoreServiceError_ErrorCode_name, int32(x)) +} +func (x *BlobstoreServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(BlobstoreServiceError_ErrorCode_value, data, "BlobstoreServiceError_ErrorCode") + if err != nil { + return err + } + *x = BlobstoreServiceError_ErrorCode(value) + return nil +} + +type BlobstoreServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *BlobstoreServiceError) Reset() { *m = BlobstoreServiceError{} } +func (m *BlobstoreServiceError) String() string { return proto.CompactTextString(m) } +func (*BlobstoreServiceError) ProtoMessage() {} + +type CreateUploadURLRequest struct { + SuccessPath *string `protobuf:"bytes,1,req,name=success_path" json:"success_path,omitempty"` + MaxUploadSizeBytes *int64 `protobuf:"varint,2,opt,name=max_upload_size_bytes" json:"max_upload_size_bytes,omitempty"` + MaxUploadSizePerBlobBytes *int64 `protobuf:"varint,3,opt,name=max_upload_size_per_blob_bytes" json:"max_upload_size_per_blob_bytes,omitempty"` + GsBucketName *string `protobuf:"bytes,4,opt,name=gs_bucket_name" json:"gs_bucket_name,omitempty"` + UrlExpiryTimeSeconds *int32 `protobuf:"varint,5,opt,name=url_expiry_time_seconds" json:"url_expiry_time_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateUploadURLRequest) Reset() { *m = CreateUploadURLRequest{} } +func (m *CreateUploadURLRequest) String() string { return proto.CompactTextString(m) } +func (*CreateUploadURLRequest) ProtoMessage() {} + +func (m *CreateUploadURLRequest) GetSuccessPath() string { + if m != nil && m.SuccessPath != nil { + return *m.SuccessPath + } + return "" +} + +func (m *CreateUploadURLRequest) GetMaxUploadSizeBytes() int64 { + if m != nil && m.MaxUploadSizeBytes != nil { + return *m.MaxUploadSizeBytes + } + return 0 +} + +func (m *CreateUploadURLRequest) GetMaxUploadSizePerBlobBytes() int64 { + if m != nil && m.MaxUploadSizePerBlobBytes != nil { + return *m.MaxUploadSizePerBlobBytes + } + return 0 +} + +func (m *CreateUploadURLRequest) GetGsBucketName() string { + if m != nil && m.GsBucketName != nil { + return *m.GsBucketName + } + return "" +} + +func (m *CreateUploadURLRequest) GetUrlExpiryTimeSeconds() int32 { + if m != nil && m.UrlExpiryTimeSeconds != nil { + return *m.UrlExpiryTimeSeconds + } + return 0 +} + +type CreateUploadURLResponse struct { + Url *string `protobuf:"bytes,1,req,name=url" json:"url,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateUploadURLResponse) Reset() { *m = CreateUploadURLResponse{} } +func (m *CreateUploadURLResponse) String() string { return proto.CompactTextString(m) } +func (*CreateUploadURLResponse) ProtoMessage() {} + +func (m *CreateUploadURLResponse) GetUrl() string { + if m != nil && m.Url != nil { + return *m.Url + } + return "" +} + +type DeleteBlobRequest struct { + BlobKey []string `protobuf:"bytes,1,rep,name=blob_key" json:"blob_key,omitempty"` + Token *string `protobuf:"bytes,2,opt,name=token" json:"token,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteBlobRequest) Reset() { *m = DeleteBlobRequest{} } +func (m *DeleteBlobRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteBlobRequest) ProtoMessage() {} + +func (m *DeleteBlobRequest) GetBlobKey() []string { + if m != nil { + return m.BlobKey + } + return nil +} + +func (m *DeleteBlobRequest) GetToken() string { + if m != nil && m.Token != nil { + return *m.Token + } + return "" +} + +type FetchDataRequest struct { + BlobKey *string `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + StartIndex *int64 `protobuf:"varint,2,req,name=start_index" json:"start_index,omitempty"` + EndIndex *int64 `protobuf:"varint,3,req,name=end_index" json:"end_index,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FetchDataRequest) Reset() { *m = FetchDataRequest{} } +func (m *FetchDataRequest) String() string { return proto.CompactTextString(m) } +func (*FetchDataRequest) ProtoMessage() {} + +func (m *FetchDataRequest) GetBlobKey() string { + if m != nil && m.BlobKey != nil { + return *m.BlobKey + } + return "" +} + +func (m *FetchDataRequest) GetStartIndex() int64 { + if m != nil && m.StartIndex != nil { + return *m.StartIndex + } + return 0 +} + +func (m *FetchDataRequest) GetEndIndex() int64 { + if m != nil && m.EndIndex != nil { + return *m.EndIndex + } + return 0 +} + +type FetchDataResponse struct { + Data []byte `protobuf:"bytes,1000,req,name=data" json:"data,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FetchDataResponse) Reset() { *m = FetchDataResponse{} } +func (m *FetchDataResponse) String() string { return proto.CompactTextString(m) } +func (*FetchDataResponse) ProtoMessage() {} + +func (m *FetchDataResponse) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +type CloneBlobRequest struct { + BlobKey []byte `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + MimeType []byte `protobuf:"bytes,2,req,name=mime_type" json:"mime_type,omitempty"` + TargetAppId []byte `protobuf:"bytes,3,req,name=target_app_id" json:"target_app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CloneBlobRequest) Reset() { *m = CloneBlobRequest{} } +func (m *CloneBlobRequest) String() string { return proto.CompactTextString(m) } +func (*CloneBlobRequest) ProtoMessage() {} + +func (m *CloneBlobRequest) GetBlobKey() []byte { + if m != nil { + return m.BlobKey + } + return nil +} + +func (m *CloneBlobRequest) GetMimeType() []byte { + if m != nil { + return m.MimeType + } + return nil +} + +func (m *CloneBlobRequest) GetTargetAppId() []byte { + if m != nil { + return m.TargetAppId + } + return nil +} + +type CloneBlobResponse struct { + BlobKey []byte `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CloneBlobResponse) Reset() { *m = CloneBlobResponse{} } +func (m *CloneBlobResponse) String() string { return proto.CompactTextString(m) } +func (*CloneBlobResponse) ProtoMessage() {} + +func (m *CloneBlobResponse) GetBlobKey() []byte { + if m != nil { + return m.BlobKey + } + return nil +} + +type DecodeBlobKeyRequest struct { + BlobKey []string `protobuf:"bytes,1,rep,name=blob_key" json:"blob_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DecodeBlobKeyRequest) Reset() { *m = DecodeBlobKeyRequest{} } +func (m *DecodeBlobKeyRequest) String() string { return proto.CompactTextString(m) } +func (*DecodeBlobKeyRequest) ProtoMessage() {} + +func (m *DecodeBlobKeyRequest) GetBlobKey() []string { + if m != nil { + return m.BlobKey + } + return nil +} + +type DecodeBlobKeyResponse struct { + Decoded []string `protobuf:"bytes,1,rep,name=decoded" json:"decoded,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DecodeBlobKeyResponse) Reset() { *m = DecodeBlobKeyResponse{} } +func (m *DecodeBlobKeyResponse) String() string { return proto.CompactTextString(m) } +func (*DecodeBlobKeyResponse) ProtoMessage() {} + +func (m *DecodeBlobKeyResponse) GetDecoded() []string { + if m != nil { + return m.Decoded + } + return nil +} + +type CreateEncodedGoogleStorageKeyRequest struct { + Filename *string `protobuf:"bytes,1,req,name=filename" json:"filename,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateEncodedGoogleStorageKeyRequest) Reset() { *m = CreateEncodedGoogleStorageKeyRequest{} } +func (m *CreateEncodedGoogleStorageKeyRequest) String() string { return proto.CompactTextString(m) } +func (*CreateEncodedGoogleStorageKeyRequest) ProtoMessage() {} + +func (m *CreateEncodedGoogleStorageKeyRequest) GetFilename() string { + if m != nil && m.Filename != nil { + return *m.Filename + } + return "" +} + +type CreateEncodedGoogleStorageKeyResponse struct { + BlobKey *string `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateEncodedGoogleStorageKeyResponse) Reset() { *m = CreateEncodedGoogleStorageKeyResponse{} } +func (m *CreateEncodedGoogleStorageKeyResponse) String() string { return proto.CompactTextString(m) } +func (*CreateEncodedGoogleStorageKeyResponse) ProtoMessage() {} + +func (m *CreateEncodedGoogleStorageKeyResponse) GetBlobKey() string { + if m != nil && m.BlobKey != nil { + return *m.BlobKey + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.proto b/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.proto new file mode 100644 index 000000000..33b265032 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/blobstore/blobstore_service.proto @@ -0,0 +1,71 @@ +syntax = "proto2"; +option go_package = "blobstore"; + +package appengine; + +message BlobstoreServiceError { + enum ErrorCode { + OK = 0; + INTERNAL_ERROR = 1; + URL_TOO_LONG = 2; + PERMISSION_DENIED = 3; + BLOB_NOT_FOUND = 4; + DATA_INDEX_OUT_OF_RANGE = 5; + BLOB_FETCH_SIZE_TOO_LARGE = 6; + ARGUMENT_OUT_OF_RANGE = 8; + INVALID_BLOB_KEY = 9; + } +} + +message CreateUploadURLRequest { + required string success_path = 1; + optional int64 max_upload_size_bytes = 2; + optional int64 max_upload_size_per_blob_bytes = 3; + optional string gs_bucket_name = 4; + optional int32 url_expiry_time_seconds = 5; +} + +message CreateUploadURLResponse { + required string url = 1; +} + +message DeleteBlobRequest { + repeated string blob_key = 1; + optional string token = 2; +} + +message FetchDataRequest { + required string blob_key = 1; + required int64 start_index = 2; + required int64 end_index = 3; +} + +message FetchDataResponse { + required bytes data = 1000 [ctype = CORD]; +} + +message CloneBlobRequest { + required bytes blob_key = 1; + required bytes mime_type = 2; + required bytes target_app_id = 3; +} + +message CloneBlobResponse { + required bytes blob_key = 1; +} + +message DecodeBlobKeyRequest { + repeated string blob_key = 1; +} + +message DecodeBlobKeyResponse { + repeated string decoded = 1; +} + +message CreateEncodedGoogleStorageKeyRequest { + required string filename = 1; +} + +message CreateEncodedGoogleStorageKeyResponse { + required string blob_key = 1; +} diff --git a/vendor/google.golang.org/appengine/internal/capability/capability_service.pb.go b/vendor/google.golang.org/appengine/internal/capability/capability_service.pb.go new file mode 100644 index 000000000..e57a04be7 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/capability/capability_service.pb.go @@ -0,0 +1,125 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/capability/capability_service.proto +// DO NOT EDIT! + +/* +Package channel is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/capability/capability_service.proto + +It has these top-level messages: + IsEnabledRequest + IsEnabledResponse +*/ +package channel + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type IsEnabledResponse_SummaryStatus int32 + +const ( + IsEnabledResponse_DEFAULT IsEnabledResponse_SummaryStatus = 0 + IsEnabledResponse_ENABLED IsEnabledResponse_SummaryStatus = 1 + IsEnabledResponse_SCHEDULED_FUTURE IsEnabledResponse_SummaryStatus = 2 + IsEnabledResponse_SCHEDULED_NOW IsEnabledResponse_SummaryStatus = 3 + IsEnabledResponse_DISABLED IsEnabledResponse_SummaryStatus = 4 + IsEnabledResponse_UNKNOWN IsEnabledResponse_SummaryStatus = 5 +) + +var IsEnabledResponse_SummaryStatus_name = map[int32]string{ + 0: "DEFAULT", + 1: "ENABLED", + 2: "SCHEDULED_FUTURE", + 3: "SCHEDULED_NOW", + 4: "DISABLED", + 5: "UNKNOWN", +} +var IsEnabledResponse_SummaryStatus_value = map[string]int32{ + "DEFAULT": 0, + "ENABLED": 1, + "SCHEDULED_FUTURE": 2, + "SCHEDULED_NOW": 3, + "DISABLED": 4, + "UNKNOWN": 5, +} + +func (x IsEnabledResponse_SummaryStatus) Enum() *IsEnabledResponse_SummaryStatus { + p := new(IsEnabledResponse_SummaryStatus) + *p = x + return p +} +func (x IsEnabledResponse_SummaryStatus) String() string { + return proto.EnumName(IsEnabledResponse_SummaryStatus_name, int32(x)) +} +func (x *IsEnabledResponse_SummaryStatus) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(IsEnabledResponse_SummaryStatus_value, data, "IsEnabledResponse_SummaryStatus") + if err != nil { + return err + } + *x = IsEnabledResponse_SummaryStatus(value) + return nil +} + +type IsEnabledRequest struct { + Package *string `protobuf:"bytes,1,req,name=package" json:"package,omitempty"` + Capability []string `protobuf:"bytes,2,rep,name=capability" json:"capability,omitempty"` + Call []string `protobuf:"bytes,3,rep,name=call" json:"call,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IsEnabledRequest) Reset() { *m = IsEnabledRequest{} } +func (m *IsEnabledRequest) String() string { return proto.CompactTextString(m) } +func (*IsEnabledRequest) ProtoMessage() {} + +func (m *IsEnabledRequest) GetPackage() string { + if m != nil && m.Package != nil { + return *m.Package + } + return "" +} + +func (m *IsEnabledRequest) GetCapability() []string { + if m != nil { + return m.Capability + } + return nil +} + +func (m *IsEnabledRequest) GetCall() []string { + if m != nil { + return m.Call + } + return nil +} + +type IsEnabledResponse struct { + SummaryStatus *IsEnabledResponse_SummaryStatus `protobuf:"varint,1,opt,name=summary_status,enum=appengine.IsEnabledResponse_SummaryStatus" json:"summary_status,omitempty"` + TimeUntilScheduled *int64 `protobuf:"varint,2,opt,name=time_until_scheduled" json:"time_until_scheduled,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IsEnabledResponse) Reset() { *m = IsEnabledResponse{} } +func (m *IsEnabledResponse) String() string { return proto.CompactTextString(m) } +func (*IsEnabledResponse) ProtoMessage() {} + +func (m *IsEnabledResponse) GetSummaryStatus() IsEnabledResponse_SummaryStatus { + if m != nil && m.SummaryStatus != nil { + return *m.SummaryStatus + } + return IsEnabledResponse_DEFAULT +} + +func (m *IsEnabledResponse) GetTimeUntilScheduled() int64 { + if m != nil && m.TimeUntilScheduled != nil { + return *m.TimeUntilScheduled + } + return 0 +} diff --git a/vendor/google.golang.org/appengine/internal/capability/capability_service.proto b/vendor/google.golang.org/appengine/internal/capability/capability_service.proto new file mode 100644 index 000000000..8f7256d1c --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/capability/capability_service.proto @@ -0,0 +1,28 @@ +syntax = "proto2"; +option go_package = "channel"; + +package appengine; + +message IsEnabledRequest { + required string package = 1; + repeated string capability = 2; + repeated string call = 3; +} + +message IsEnabledResponse { + enum SummaryStatus { + DEFAULT = 0; + ENABLED = 1; + SCHEDULED_FUTURE = 2; + SCHEDULED_NOW = 3; + DISABLED = 4; + UNKNOWN = 5; + } + optional SummaryStatus summary_status = 1; + + optional int64 time_until_scheduled = 2; +} + +service CapabilityService { + rpc IsEnabled(IsEnabledRequest) returns (IsEnabledResponse) {}; +} diff --git a/vendor/google.golang.org/appengine/internal/channel/channel_service.pb.go b/vendor/google.golang.org/appengine/internal/channel/channel_service.pb.go new file mode 100644 index 000000000..7b8d00c98 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/channel/channel_service.pb.go @@ -0,0 +1,154 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/channel/channel_service.proto +// DO NOT EDIT! + +/* +Package channel is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/channel/channel_service.proto + +It has these top-level messages: + ChannelServiceError + CreateChannelRequest + CreateChannelResponse + SendMessageRequest +*/ +package channel + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ChannelServiceError_ErrorCode int32 + +const ( + ChannelServiceError_OK ChannelServiceError_ErrorCode = 0 + ChannelServiceError_INTERNAL_ERROR ChannelServiceError_ErrorCode = 1 + ChannelServiceError_INVALID_CHANNEL_KEY ChannelServiceError_ErrorCode = 2 + ChannelServiceError_BAD_MESSAGE ChannelServiceError_ErrorCode = 3 + ChannelServiceError_INVALID_CHANNEL_TOKEN_DURATION ChannelServiceError_ErrorCode = 4 + ChannelServiceError_APPID_ALIAS_REQUIRED ChannelServiceError_ErrorCode = 5 +) + +var ChannelServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INTERNAL_ERROR", + 2: "INVALID_CHANNEL_KEY", + 3: "BAD_MESSAGE", + 4: "INVALID_CHANNEL_TOKEN_DURATION", + 5: "APPID_ALIAS_REQUIRED", +} +var ChannelServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INTERNAL_ERROR": 1, + "INVALID_CHANNEL_KEY": 2, + "BAD_MESSAGE": 3, + "INVALID_CHANNEL_TOKEN_DURATION": 4, + "APPID_ALIAS_REQUIRED": 5, +} + +func (x ChannelServiceError_ErrorCode) Enum() *ChannelServiceError_ErrorCode { + p := new(ChannelServiceError_ErrorCode) + *p = x + return p +} +func (x ChannelServiceError_ErrorCode) String() string { + return proto.EnumName(ChannelServiceError_ErrorCode_name, int32(x)) +} +func (x *ChannelServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ChannelServiceError_ErrorCode_value, data, "ChannelServiceError_ErrorCode") + if err != nil { + return err + } + *x = ChannelServiceError_ErrorCode(value) + return nil +} + +type ChannelServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ChannelServiceError) Reset() { *m = ChannelServiceError{} } +func (m *ChannelServiceError) String() string { return proto.CompactTextString(m) } +func (*ChannelServiceError) ProtoMessage() {} + +type CreateChannelRequest struct { + ApplicationKey *string `protobuf:"bytes,1,req,name=application_key" json:"application_key,omitempty"` + DurationMinutes *int32 `protobuf:"varint,2,opt,name=duration_minutes" json:"duration_minutes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateChannelRequest) Reset() { *m = CreateChannelRequest{} } +func (m *CreateChannelRequest) String() string { return proto.CompactTextString(m) } +func (*CreateChannelRequest) ProtoMessage() {} + +func (m *CreateChannelRequest) GetApplicationKey() string { + if m != nil && m.ApplicationKey != nil { + return *m.ApplicationKey + } + return "" +} + +func (m *CreateChannelRequest) GetDurationMinutes() int32 { + if m != nil && m.DurationMinutes != nil { + return *m.DurationMinutes + } + return 0 +} + +type CreateChannelResponse struct { + Token *string `protobuf:"bytes,2,opt,name=token" json:"token,omitempty"` + DurationMinutes *int32 `protobuf:"varint,3,opt,name=duration_minutes" json:"duration_minutes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateChannelResponse) Reset() { *m = CreateChannelResponse{} } +func (m *CreateChannelResponse) String() string { return proto.CompactTextString(m) } +func (*CreateChannelResponse) ProtoMessage() {} + +func (m *CreateChannelResponse) GetToken() string { + if m != nil && m.Token != nil { + return *m.Token + } + return "" +} + +func (m *CreateChannelResponse) GetDurationMinutes() int32 { + if m != nil && m.DurationMinutes != nil { + return *m.DurationMinutes + } + return 0 +} + +type SendMessageRequest struct { + ApplicationKey *string `protobuf:"bytes,1,req,name=application_key" json:"application_key,omitempty"` + Message *string `protobuf:"bytes,2,req,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SendMessageRequest) Reset() { *m = SendMessageRequest{} } +func (m *SendMessageRequest) String() string { return proto.CompactTextString(m) } +func (*SendMessageRequest) ProtoMessage() {} + +func (m *SendMessageRequest) GetApplicationKey() string { + if m != nil && m.ApplicationKey != nil { + return *m.ApplicationKey + } + return "" +} + +func (m *SendMessageRequest) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/channel/channel_service.proto b/vendor/google.golang.org/appengine/internal/channel/channel_service.proto new file mode 100644 index 000000000..2b5a918ca --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/channel/channel_service.proto @@ -0,0 +1,30 @@ +syntax = "proto2"; +option go_package = "channel"; + +package appengine; + +message ChannelServiceError { + enum ErrorCode { + OK = 0; + INTERNAL_ERROR = 1; + INVALID_CHANNEL_KEY = 2; + BAD_MESSAGE = 3; + INVALID_CHANNEL_TOKEN_DURATION = 4; + APPID_ALIAS_REQUIRED = 5; + } +} + +message CreateChannelRequest { + required string application_key = 1; + optional int32 duration_minutes = 2; +} + +message CreateChannelResponse { + optional string token = 2; + optional int32 duration_minutes = 3; +} + +message SendMessageRequest { + required string application_key = 1; + required string message = 2; +} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go new file mode 100644 index 000000000..8613cb731 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go @@ -0,0 +1,2778 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/datastore/datastore_v3.proto +// DO NOT EDIT! + +/* +Package datastore is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/datastore/datastore_v3.proto + +It has these top-level messages: + Action + PropertyValue + Property + Path + Reference + User + EntityProto + CompositeProperty + Index + CompositeIndex + IndexPostfix + IndexPosition + Snapshot + InternalHeader + Transaction + Query + CompiledQuery + CompiledCursor + Cursor + Error + Cost + GetRequest + GetResponse + PutRequest + PutResponse + TouchRequest + TouchResponse + DeleteRequest + DeleteResponse + NextRequest + QueryResult + AllocateIdsRequest + AllocateIdsResponse + CompositeIndices + AddActionsRequest + AddActionsResponse + BeginTransactionRequest + CommitResponse +*/ +package datastore + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Property_Meaning int32 + +const ( + Property_NO_MEANING Property_Meaning = 0 + Property_BLOB Property_Meaning = 14 + Property_TEXT Property_Meaning = 15 + Property_BYTESTRING Property_Meaning = 16 + Property_ATOM_CATEGORY Property_Meaning = 1 + Property_ATOM_LINK Property_Meaning = 2 + Property_ATOM_TITLE Property_Meaning = 3 + Property_ATOM_CONTENT Property_Meaning = 4 + Property_ATOM_SUMMARY Property_Meaning = 5 + Property_ATOM_AUTHOR Property_Meaning = 6 + Property_GD_WHEN Property_Meaning = 7 + Property_GD_EMAIL Property_Meaning = 8 + Property_GEORSS_POINT Property_Meaning = 9 + Property_GD_IM Property_Meaning = 10 + Property_GD_PHONENUMBER Property_Meaning = 11 + Property_GD_POSTALADDRESS Property_Meaning = 12 + Property_GD_RATING Property_Meaning = 13 + Property_BLOBKEY Property_Meaning = 17 + Property_ENTITY_PROTO Property_Meaning = 19 + Property_INDEX_VALUE Property_Meaning = 18 +) + +var Property_Meaning_name = map[int32]string{ + 0: "NO_MEANING", + 14: "BLOB", + 15: "TEXT", + 16: "BYTESTRING", + 1: "ATOM_CATEGORY", + 2: "ATOM_LINK", + 3: "ATOM_TITLE", + 4: "ATOM_CONTENT", + 5: "ATOM_SUMMARY", + 6: "ATOM_AUTHOR", + 7: "GD_WHEN", + 8: "GD_EMAIL", + 9: "GEORSS_POINT", + 10: "GD_IM", + 11: "GD_PHONENUMBER", + 12: "GD_POSTALADDRESS", + 13: "GD_RATING", + 17: "BLOBKEY", + 19: "ENTITY_PROTO", + 18: "INDEX_VALUE", +} +var Property_Meaning_value = map[string]int32{ + "NO_MEANING": 0, + "BLOB": 14, + "TEXT": 15, + "BYTESTRING": 16, + "ATOM_CATEGORY": 1, + "ATOM_LINK": 2, + "ATOM_TITLE": 3, + "ATOM_CONTENT": 4, + "ATOM_SUMMARY": 5, + "ATOM_AUTHOR": 6, + "GD_WHEN": 7, + "GD_EMAIL": 8, + "GEORSS_POINT": 9, + "GD_IM": 10, + "GD_PHONENUMBER": 11, + "GD_POSTALADDRESS": 12, + "GD_RATING": 13, + "BLOBKEY": 17, + "ENTITY_PROTO": 19, + "INDEX_VALUE": 18, +} + +func (x Property_Meaning) Enum() *Property_Meaning { + p := new(Property_Meaning) + *p = x + return p +} +func (x Property_Meaning) String() string { + return proto.EnumName(Property_Meaning_name, int32(x)) +} +func (x *Property_Meaning) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Property_Meaning_value, data, "Property_Meaning") + if err != nil { + return err + } + *x = Property_Meaning(value) + return nil +} + +type Property_FtsTokenizationOption int32 + +const ( + Property_HTML Property_FtsTokenizationOption = 1 + Property_ATOM Property_FtsTokenizationOption = 2 +) + +var Property_FtsTokenizationOption_name = map[int32]string{ + 1: "HTML", + 2: "ATOM", +} +var Property_FtsTokenizationOption_value = map[string]int32{ + "HTML": 1, + "ATOM": 2, +} + +func (x Property_FtsTokenizationOption) Enum() *Property_FtsTokenizationOption { + p := new(Property_FtsTokenizationOption) + *p = x + return p +} +func (x Property_FtsTokenizationOption) String() string { + return proto.EnumName(Property_FtsTokenizationOption_name, int32(x)) +} +func (x *Property_FtsTokenizationOption) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Property_FtsTokenizationOption_value, data, "Property_FtsTokenizationOption") + if err != nil { + return err + } + *x = Property_FtsTokenizationOption(value) + return nil +} + +type EntityProto_Kind int32 + +const ( + EntityProto_GD_CONTACT EntityProto_Kind = 1 + EntityProto_GD_EVENT EntityProto_Kind = 2 + EntityProto_GD_MESSAGE EntityProto_Kind = 3 +) + +var EntityProto_Kind_name = map[int32]string{ + 1: "GD_CONTACT", + 2: "GD_EVENT", + 3: "GD_MESSAGE", +} +var EntityProto_Kind_value = map[string]int32{ + "GD_CONTACT": 1, + "GD_EVENT": 2, + "GD_MESSAGE": 3, +} + +func (x EntityProto_Kind) Enum() *EntityProto_Kind { + p := new(EntityProto_Kind) + *p = x + return p +} +func (x EntityProto_Kind) String() string { + return proto.EnumName(EntityProto_Kind_name, int32(x)) +} +func (x *EntityProto_Kind) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(EntityProto_Kind_value, data, "EntityProto_Kind") + if err != nil { + return err + } + *x = EntityProto_Kind(value) + return nil +} + +type Index_Property_Direction int32 + +const ( + Index_Property_ASCENDING Index_Property_Direction = 1 + Index_Property_DESCENDING Index_Property_Direction = 2 +) + +var Index_Property_Direction_name = map[int32]string{ + 1: "ASCENDING", + 2: "DESCENDING", +} +var Index_Property_Direction_value = map[string]int32{ + "ASCENDING": 1, + "DESCENDING": 2, +} + +func (x Index_Property_Direction) Enum() *Index_Property_Direction { + p := new(Index_Property_Direction) + *p = x + return p +} +func (x Index_Property_Direction) String() string { + return proto.EnumName(Index_Property_Direction_name, int32(x)) +} +func (x *Index_Property_Direction) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Index_Property_Direction_value, data, "Index_Property_Direction") + if err != nil { + return err + } + *x = Index_Property_Direction(value) + return nil +} + +type CompositeIndex_State int32 + +const ( + CompositeIndex_WRITE_ONLY CompositeIndex_State = 1 + CompositeIndex_READ_WRITE CompositeIndex_State = 2 + CompositeIndex_DELETED CompositeIndex_State = 3 + CompositeIndex_ERROR CompositeIndex_State = 4 +) + +var CompositeIndex_State_name = map[int32]string{ + 1: "WRITE_ONLY", + 2: "READ_WRITE", + 3: "DELETED", + 4: "ERROR", +} +var CompositeIndex_State_value = map[string]int32{ + "WRITE_ONLY": 1, + "READ_WRITE": 2, + "DELETED": 3, + "ERROR": 4, +} + +func (x CompositeIndex_State) Enum() *CompositeIndex_State { + p := new(CompositeIndex_State) + *p = x + return p +} +func (x CompositeIndex_State) String() string { + return proto.EnumName(CompositeIndex_State_name, int32(x)) +} +func (x *CompositeIndex_State) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CompositeIndex_State_value, data, "CompositeIndex_State") + if err != nil { + return err + } + *x = CompositeIndex_State(value) + return nil +} + +type Snapshot_Status int32 + +const ( + Snapshot_INACTIVE Snapshot_Status = 0 + Snapshot_ACTIVE Snapshot_Status = 1 +) + +var Snapshot_Status_name = map[int32]string{ + 0: "INACTIVE", + 1: "ACTIVE", +} +var Snapshot_Status_value = map[string]int32{ + "INACTIVE": 0, + "ACTIVE": 1, +} + +func (x Snapshot_Status) Enum() *Snapshot_Status { + p := new(Snapshot_Status) + *p = x + return p +} +func (x Snapshot_Status) String() string { + return proto.EnumName(Snapshot_Status_name, int32(x)) +} +func (x *Snapshot_Status) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Snapshot_Status_value, data, "Snapshot_Status") + if err != nil { + return err + } + *x = Snapshot_Status(value) + return nil +} + +type Query_Hint int32 + +const ( + Query_ORDER_FIRST Query_Hint = 1 + Query_ANCESTOR_FIRST Query_Hint = 2 + Query_FILTER_FIRST Query_Hint = 3 +) + +var Query_Hint_name = map[int32]string{ + 1: "ORDER_FIRST", + 2: "ANCESTOR_FIRST", + 3: "FILTER_FIRST", +} +var Query_Hint_value = map[string]int32{ + "ORDER_FIRST": 1, + "ANCESTOR_FIRST": 2, + "FILTER_FIRST": 3, +} + +func (x Query_Hint) Enum() *Query_Hint { + p := new(Query_Hint) + *p = x + return p +} +func (x Query_Hint) String() string { + return proto.EnumName(Query_Hint_name, int32(x)) +} +func (x *Query_Hint) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Query_Hint_value, data, "Query_Hint") + if err != nil { + return err + } + *x = Query_Hint(value) + return nil +} + +type Query_Filter_Operator int32 + +const ( + Query_Filter_LESS_THAN Query_Filter_Operator = 1 + Query_Filter_LESS_THAN_OR_EQUAL Query_Filter_Operator = 2 + Query_Filter_GREATER_THAN Query_Filter_Operator = 3 + Query_Filter_GREATER_THAN_OR_EQUAL Query_Filter_Operator = 4 + Query_Filter_EQUAL Query_Filter_Operator = 5 + Query_Filter_IN Query_Filter_Operator = 6 + Query_Filter_EXISTS Query_Filter_Operator = 7 +) + +var Query_Filter_Operator_name = map[int32]string{ + 1: "LESS_THAN", + 2: "LESS_THAN_OR_EQUAL", + 3: "GREATER_THAN", + 4: "GREATER_THAN_OR_EQUAL", + 5: "EQUAL", + 6: "IN", + 7: "EXISTS", +} +var Query_Filter_Operator_value = map[string]int32{ + "LESS_THAN": 1, + "LESS_THAN_OR_EQUAL": 2, + "GREATER_THAN": 3, + "GREATER_THAN_OR_EQUAL": 4, + "EQUAL": 5, + "IN": 6, + "EXISTS": 7, +} + +func (x Query_Filter_Operator) Enum() *Query_Filter_Operator { + p := new(Query_Filter_Operator) + *p = x + return p +} +func (x Query_Filter_Operator) String() string { + return proto.EnumName(Query_Filter_Operator_name, int32(x)) +} +func (x *Query_Filter_Operator) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Query_Filter_Operator_value, data, "Query_Filter_Operator") + if err != nil { + return err + } + *x = Query_Filter_Operator(value) + return nil +} + +type Query_Order_Direction int32 + +const ( + Query_Order_ASCENDING Query_Order_Direction = 1 + Query_Order_DESCENDING Query_Order_Direction = 2 +) + +var Query_Order_Direction_name = map[int32]string{ + 1: "ASCENDING", + 2: "DESCENDING", +} +var Query_Order_Direction_value = map[string]int32{ + "ASCENDING": 1, + "DESCENDING": 2, +} + +func (x Query_Order_Direction) Enum() *Query_Order_Direction { + p := new(Query_Order_Direction) + *p = x + return p +} +func (x Query_Order_Direction) String() string { + return proto.EnumName(Query_Order_Direction_name, int32(x)) +} +func (x *Query_Order_Direction) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Query_Order_Direction_value, data, "Query_Order_Direction") + if err != nil { + return err + } + *x = Query_Order_Direction(value) + return nil +} + +type Error_ErrorCode int32 + +const ( + Error_BAD_REQUEST Error_ErrorCode = 1 + Error_CONCURRENT_TRANSACTION Error_ErrorCode = 2 + Error_INTERNAL_ERROR Error_ErrorCode = 3 + Error_NEED_INDEX Error_ErrorCode = 4 + Error_TIMEOUT Error_ErrorCode = 5 + Error_PERMISSION_DENIED Error_ErrorCode = 6 + Error_BIGTABLE_ERROR Error_ErrorCode = 7 + Error_COMMITTED_BUT_STILL_APPLYING Error_ErrorCode = 8 + Error_CAPABILITY_DISABLED Error_ErrorCode = 9 + Error_TRY_ALTERNATE_BACKEND Error_ErrorCode = 10 + Error_SAFE_TIME_TOO_OLD Error_ErrorCode = 11 +) + +var Error_ErrorCode_name = map[int32]string{ + 1: "BAD_REQUEST", + 2: "CONCURRENT_TRANSACTION", + 3: "INTERNAL_ERROR", + 4: "NEED_INDEX", + 5: "TIMEOUT", + 6: "PERMISSION_DENIED", + 7: "BIGTABLE_ERROR", + 8: "COMMITTED_BUT_STILL_APPLYING", + 9: "CAPABILITY_DISABLED", + 10: "TRY_ALTERNATE_BACKEND", + 11: "SAFE_TIME_TOO_OLD", +} +var Error_ErrorCode_value = map[string]int32{ + "BAD_REQUEST": 1, + "CONCURRENT_TRANSACTION": 2, + "INTERNAL_ERROR": 3, + "NEED_INDEX": 4, + "TIMEOUT": 5, + "PERMISSION_DENIED": 6, + "BIGTABLE_ERROR": 7, + "COMMITTED_BUT_STILL_APPLYING": 8, + "CAPABILITY_DISABLED": 9, + "TRY_ALTERNATE_BACKEND": 10, + "SAFE_TIME_TOO_OLD": 11, +} + +func (x Error_ErrorCode) Enum() *Error_ErrorCode { + p := new(Error_ErrorCode) + *p = x + return p +} +func (x Error_ErrorCode) String() string { + return proto.EnumName(Error_ErrorCode_name, int32(x)) +} +func (x *Error_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Error_ErrorCode_value, data, "Error_ErrorCode") + if err != nil { + return err + } + *x = Error_ErrorCode(value) + return nil +} + +type PutRequest_AutoIdPolicy int32 + +const ( + PutRequest_CURRENT PutRequest_AutoIdPolicy = 0 + PutRequest_SEQUENTIAL PutRequest_AutoIdPolicy = 1 +) + +var PutRequest_AutoIdPolicy_name = map[int32]string{ + 0: "CURRENT", + 1: "SEQUENTIAL", +} +var PutRequest_AutoIdPolicy_value = map[string]int32{ + "CURRENT": 0, + "SEQUENTIAL": 1, +} + +func (x PutRequest_AutoIdPolicy) Enum() *PutRequest_AutoIdPolicy { + p := new(PutRequest_AutoIdPolicy) + *p = x + return p +} +func (x PutRequest_AutoIdPolicy) String() string { + return proto.EnumName(PutRequest_AutoIdPolicy_name, int32(x)) +} +func (x *PutRequest_AutoIdPolicy) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PutRequest_AutoIdPolicy_value, data, "PutRequest_AutoIdPolicy") + if err != nil { + return err + } + *x = PutRequest_AutoIdPolicy(value) + return nil +} + +type Action struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Action) Reset() { *m = Action{} } +func (m *Action) String() string { return proto.CompactTextString(m) } +func (*Action) ProtoMessage() {} + +type PropertyValue struct { + Int64Value *int64 `protobuf:"varint,1,opt,name=int64Value" json:"int64Value,omitempty"` + BooleanValue *bool `protobuf:"varint,2,opt,name=booleanValue" json:"booleanValue,omitempty"` + StringValue *string `protobuf:"bytes,3,opt,name=stringValue" json:"stringValue,omitempty"` + DoubleValue *float64 `protobuf:"fixed64,4,opt,name=doubleValue" json:"doubleValue,omitempty"` + Pointvalue *PropertyValue_PointValue `protobuf:"group,5,opt,name=PointValue" json:"pointvalue,omitempty"` + Uservalue *PropertyValue_UserValue `protobuf:"group,8,opt,name=UserValue" json:"uservalue,omitempty"` + Referencevalue *PropertyValue_ReferenceValue `protobuf:"group,12,opt,name=ReferenceValue" json:"referencevalue,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyValue) Reset() { *m = PropertyValue{} } +func (m *PropertyValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue) ProtoMessage() {} + +func (m *PropertyValue) GetInt64Value() int64 { + if m != nil && m.Int64Value != nil { + return *m.Int64Value + } + return 0 +} + +func (m *PropertyValue) GetBooleanValue() bool { + if m != nil && m.BooleanValue != nil { + return *m.BooleanValue + } + return false +} + +func (m *PropertyValue) GetStringValue() string { + if m != nil && m.StringValue != nil { + return *m.StringValue + } + return "" +} + +func (m *PropertyValue) GetDoubleValue() float64 { + if m != nil && m.DoubleValue != nil { + return *m.DoubleValue + } + return 0 +} + +func (m *PropertyValue) GetPointvalue() *PropertyValue_PointValue { + if m != nil { + return m.Pointvalue + } + return nil +} + +func (m *PropertyValue) GetUservalue() *PropertyValue_UserValue { + if m != nil { + return m.Uservalue + } + return nil +} + +func (m *PropertyValue) GetReferencevalue() *PropertyValue_ReferenceValue { + if m != nil { + return m.Referencevalue + } + return nil +} + +type PropertyValue_PointValue struct { + X *float64 `protobuf:"fixed64,6,req,name=x" json:"x,omitempty"` + Y *float64 `protobuf:"fixed64,7,req,name=y" json:"y,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyValue_PointValue) Reset() { *m = PropertyValue_PointValue{} } +func (m *PropertyValue_PointValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_PointValue) ProtoMessage() {} + +func (m *PropertyValue_PointValue) GetX() float64 { + if m != nil && m.X != nil { + return *m.X + } + return 0 +} + +func (m *PropertyValue_PointValue) GetY() float64 { + if m != nil && m.Y != nil { + return *m.Y + } + return 0 +} + +type PropertyValue_UserValue struct { + Email *string `protobuf:"bytes,9,req,name=email" json:"email,omitempty"` + AuthDomain *string `protobuf:"bytes,10,req,name=auth_domain" json:"auth_domain,omitempty"` + Nickname *string `protobuf:"bytes,11,opt,name=nickname" json:"nickname,omitempty"` + FederatedIdentity *string `protobuf:"bytes,21,opt,name=federated_identity" json:"federated_identity,omitempty"` + FederatedProvider *string `protobuf:"bytes,22,opt,name=federated_provider" json:"federated_provider,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyValue_UserValue) Reset() { *m = PropertyValue_UserValue{} } +func (m *PropertyValue_UserValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_UserValue) ProtoMessage() {} + +func (m *PropertyValue_UserValue) GetEmail() string { + if m != nil && m.Email != nil { + return *m.Email + } + return "" +} + +func (m *PropertyValue_UserValue) GetAuthDomain() string { + if m != nil && m.AuthDomain != nil { + return *m.AuthDomain + } + return "" +} + +func (m *PropertyValue_UserValue) GetNickname() string { + if m != nil && m.Nickname != nil { + return *m.Nickname + } + return "" +} + +func (m *PropertyValue_UserValue) GetFederatedIdentity() string { + if m != nil && m.FederatedIdentity != nil { + return *m.FederatedIdentity + } + return "" +} + +func (m *PropertyValue_UserValue) GetFederatedProvider() string { + if m != nil && m.FederatedProvider != nil { + return *m.FederatedProvider + } + return "" +} + +type PropertyValue_ReferenceValue struct { + App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` + NameSpace *string `protobuf:"bytes,20,opt,name=name_space" json:"name_space,omitempty"` + Pathelement []*PropertyValue_ReferenceValue_PathElement `protobuf:"group,14,rep,name=PathElement" json:"pathelement,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyValue_ReferenceValue) Reset() { *m = PropertyValue_ReferenceValue{} } +func (m *PropertyValue_ReferenceValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_ReferenceValue) ProtoMessage() {} + +func (m *PropertyValue_ReferenceValue) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +func (m *PropertyValue_ReferenceValue) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *PropertyValue_ReferenceValue) GetPathelement() []*PropertyValue_ReferenceValue_PathElement { + if m != nil { + return m.Pathelement + } + return nil +} + +type PropertyValue_ReferenceValue_PathElement struct { + Type *string `protobuf:"bytes,15,req,name=type" json:"type,omitempty"` + Id *int64 `protobuf:"varint,16,opt,name=id" json:"id,omitempty"` + Name *string `protobuf:"bytes,17,opt,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyValue_ReferenceValue_PathElement) Reset() { + *m = PropertyValue_ReferenceValue_PathElement{} +} +func (m *PropertyValue_ReferenceValue_PathElement) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_ReferenceValue_PathElement) ProtoMessage() {} + +func (m *PropertyValue_ReferenceValue_PathElement) GetType() string { + if m != nil && m.Type != nil { + return *m.Type + } + return "" +} + +func (m *PropertyValue_ReferenceValue_PathElement) GetId() int64 { + if m != nil && m.Id != nil { + return *m.Id + } + return 0 +} + +func (m *PropertyValue_ReferenceValue_PathElement) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +type Property struct { + Meaning *Property_Meaning `protobuf:"varint,1,opt,name=meaning,enum=appengine.Property_Meaning,def=0" json:"meaning,omitempty"` + MeaningUri *string `protobuf:"bytes,2,opt,name=meaning_uri" json:"meaning_uri,omitempty"` + Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` + Value *PropertyValue `protobuf:"bytes,5,req,name=value" json:"value,omitempty"` + Multiple *bool `protobuf:"varint,4,req,name=multiple" json:"multiple,omitempty"` + Searchable *bool `protobuf:"varint,6,opt,name=searchable,def=0" json:"searchable,omitempty"` + FtsTokenizationOption *Property_FtsTokenizationOption `protobuf:"varint,8,opt,name=fts_tokenization_option,enum=appengine.Property_FtsTokenizationOption" json:"fts_tokenization_option,omitempty"` + Locale *string `protobuf:"bytes,9,opt,name=locale,def=en" json:"locale,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Property) Reset() { *m = Property{} } +func (m *Property) String() string { return proto.CompactTextString(m) } +func (*Property) ProtoMessage() {} + +const Default_Property_Meaning Property_Meaning = Property_NO_MEANING +const Default_Property_Searchable bool = false +const Default_Property_Locale string = "en" + +func (m *Property) GetMeaning() Property_Meaning { + if m != nil && m.Meaning != nil { + return *m.Meaning + } + return Default_Property_Meaning +} + +func (m *Property) GetMeaningUri() string { + if m != nil && m.MeaningUri != nil { + return *m.MeaningUri + } + return "" +} + +func (m *Property) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *Property) GetValue() *PropertyValue { + if m != nil { + return m.Value + } + return nil +} + +func (m *Property) GetMultiple() bool { + if m != nil && m.Multiple != nil { + return *m.Multiple + } + return false +} + +func (m *Property) GetSearchable() bool { + if m != nil && m.Searchable != nil { + return *m.Searchable + } + return Default_Property_Searchable +} + +func (m *Property) GetFtsTokenizationOption() Property_FtsTokenizationOption { + if m != nil && m.FtsTokenizationOption != nil { + return *m.FtsTokenizationOption + } + return Property_HTML +} + +func (m *Property) GetLocale() string { + if m != nil && m.Locale != nil { + return *m.Locale + } + return Default_Property_Locale +} + +type Path struct { + Element []*Path_Element `protobuf:"group,1,rep,name=Element" json:"element,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Path) Reset() { *m = Path{} } +func (m *Path) String() string { return proto.CompactTextString(m) } +func (*Path) ProtoMessage() {} + +func (m *Path) GetElement() []*Path_Element { + if m != nil { + return m.Element + } + return nil +} + +type Path_Element struct { + Type *string `protobuf:"bytes,2,req,name=type" json:"type,omitempty"` + Id *int64 `protobuf:"varint,3,opt,name=id" json:"id,omitempty"` + Name *string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Path_Element) Reset() { *m = Path_Element{} } +func (m *Path_Element) String() string { return proto.CompactTextString(m) } +func (*Path_Element) ProtoMessage() {} + +func (m *Path_Element) GetType() string { + if m != nil && m.Type != nil { + return *m.Type + } + return "" +} + +func (m *Path_Element) GetId() int64 { + if m != nil && m.Id != nil { + return *m.Id + } + return 0 +} + +func (m *Path_Element) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +type Reference struct { + App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` + NameSpace *string `protobuf:"bytes,20,opt,name=name_space" json:"name_space,omitempty"` + Path *Path `protobuf:"bytes,14,req,name=path" json:"path,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Reference) Reset() { *m = Reference{} } +func (m *Reference) String() string { return proto.CompactTextString(m) } +func (*Reference) ProtoMessage() {} + +func (m *Reference) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +func (m *Reference) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *Reference) GetPath() *Path { + if m != nil { + return m.Path + } + return nil +} + +type User struct { + Email *string `protobuf:"bytes,1,req,name=email" json:"email,omitempty"` + AuthDomain *string `protobuf:"bytes,2,req,name=auth_domain" json:"auth_domain,omitempty"` + Nickname *string `protobuf:"bytes,3,opt,name=nickname" json:"nickname,omitempty"` + FederatedIdentity *string `protobuf:"bytes,6,opt,name=federated_identity" json:"federated_identity,omitempty"` + FederatedProvider *string `protobuf:"bytes,7,opt,name=federated_provider" json:"federated_provider,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *User) Reset() { *m = User{} } +func (m *User) String() string { return proto.CompactTextString(m) } +func (*User) ProtoMessage() {} + +func (m *User) GetEmail() string { + if m != nil && m.Email != nil { + return *m.Email + } + return "" +} + +func (m *User) GetAuthDomain() string { + if m != nil && m.AuthDomain != nil { + return *m.AuthDomain + } + return "" +} + +func (m *User) GetNickname() string { + if m != nil && m.Nickname != nil { + return *m.Nickname + } + return "" +} + +func (m *User) GetFederatedIdentity() string { + if m != nil && m.FederatedIdentity != nil { + return *m.FederatedIdentity + } + return "" +} + +func (m *User) GetFederatedProvider() string { + if m != nil && m.FederatedProvider != nil { + return *m.FederatedProvider + } + return "" +} + +type EntityProto struct { + Key *Reference `protobuf:"bytes,13,req,name=key" json:"key,omitempty"` + EntityGroup *Path `protobuf:"bytes,16,req,name=entity_group" json:"entity_group,omitempty"` + Owner *User `protobuf:"bytes,17,opt,name=owner" json:"owner,omitempty"` + Kind *EntityProto_Kind `protobuf:"varint,4,opt,name=kind,enum=appengine.EntityProto_Kind" json:"kind,omitempty"` + KindUri *string `protobuf:"bytes,5,opt,name=kind_uri" json:"kind_uri,omitempty"` + Property []*Property `protobuf:"bytes,14,rep,name=property" json:"property,omitempty"` + RawProperty []*Property `protobuf:"bytes,15,rep,name=raw_property" json:"raw_property,omitempty"` + Rank *int32 `protobuf:"varint,18,opt,name=rank" json:"rank,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EntityProto) Reset() { *m = EntityProto{} } +func (m *EntityProto) String() string { return proto.CompactTextString(m) } +func (*EntityProto) ProtoMessage() {} + +func (m *EntityProto) GetKey() *Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *EntityProto) GetEntityGroup() *Path { + if m != nil { + return m.EntityGroup + } + return nil +} + +func (m *EntityProto) GetOwner() *User { + if m != nil { + return m.Owner + } + return nil +} + +func (m *EntityProto) GetKind() EntityProto_Kind { + if m != nil && m.Kind != nil { + return *m.Kind + } + return EntityProto_GD_CONTACT +} + +func (m *EntityProto) GetKindUri() string { + if m != nil && m.KindUri != nil { + return *m.KindUri + } + return "" +} + +func (m *EntityProto) GetProperty() []*Property { + if m != nil { + return m.Property + } + return nil +} + +func (m *EntityProto) GetRawProperty() []*Property { + if m != nil { + return m.RawProperty + } + return nil +} + +func (m *EntityProto) GetRank() int32 { + if m != nil && m.Rank != nil { + return *m.Rank + } + return 0 +} + +type CompositeProperty struct { + IndexId *int64 `protobuf:"varint,1,req,name=index_id" json:"index_id,omitempty"` + Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompositeProperty) Reset() { *m = CompositeProperty{} } +func (m *CompositeProperty) String() string { return proto.CompactTextString(m) } +func (*CompositeProperty) ProtoMessage() {} + +func (m *CompositeProperty) GetIndexId() int64 { + if m != nil && m.IndexId != nil { + return *m.IndexId + } + return 0 +} + +func (m *CompositeProperty) GetValue() []string { + if m != nil { + return m.Value + } + return nil +} + +type Index struct { + EntityType *string `protobuf:"bytes,1,req,name=entity_type" json:"entity_type,omitempty"` + Ancestor *bool `protobuf:"varint,5,req,name=ancestor" json:"ancestor,omitempty"` + Property []*Index_Property `protobuf:"group,2,rep,name=Property" json:"property,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Index) Reset() { *m = Index{} } +func (m *Index) String() string { return proto.CompactTextString(m) } +func (*Index) ProtoMessage() {} + +func (m *Index) GetEntityType() string { + if m != nil && m.EntityType != nil { + return *m.EntityType + } + return "" +} + +func (m *Index) GetAncestor() bool { + if m != nil && m.Ancestor != nil { + return *m.Ancestor + } + return false +} + +func (m *Index) GetProperty() []*Index_Property { + if m != nil { + return m.Property + } + return nil +} + +type Index_Property struct { + Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` + Direction *Index_Property_Direction `protobuf:"varint,4,opt,name=direction,enum=appengine.Index_Property_Direction,def=1" json:"direction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Index_Property) Reset() { *m = Index_Property{} } +func (m *Index_Property) String() string { return proto.CompactTextString(m) } +func (*Index_Property) ProtoMessage() {} + +const Default_Index_Property_Direction Index_Property_Direction = Index_Property_ASCENDING + +func (m *Index_Property) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *Index_Property) GetDirection() Index_Property_Direction { + if m != nil && m.Direction != nil { + return *m.Direction + } + return Default_Index_Property_Direction +} + +type CompositeIndex struct { + AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + Id *int64 `protobuf:"varint,2,req,name=id" json:"id,omitempty"` + Definition *Index `protobuf:"bytes,3,req,name=definition" json:"definition,omitempty"` + State *CompositeIndex_State `protobuf:"varint,4,req,name=state,enum=appengine.CompositeIndex_State" json:"state,omitempty"` + OnlyUseIfRequired *bool `protobuf:"varint,6,opt,name=only_use_if_required,def=0" json:"only_use_if_required,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompositeIndex) Reset() { *m = CompositeIndex{} } +func (m *CompositeIndex) String() string { return proto.CompactTextString(m) } +func (*CompositeIndex) ProtoMessage() {} + +const Default_CompositeIndex_OnlyUseIfRequired bool = false + +func (m *CompositeIndex) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *CompositeIndex) GetId() int64 { + if m != nil && m.Id != nil { + return *m.Id + } + return 0 +} + +func (m *CompositeIndex) GetDefinition() *Index { + if m != nil { + return m.Definition + } + return nil +} + +func (m *CompositeIndex) GetState() CompositeIndex_State { + if m != nil && m.State != nil { + return *m.State + } + return CompositeIndex_WRITE_ONLY +} + +func (m *CompositeIndex) GetOnlyUseIfRequired() bool { + if m != nil && m.OnlyUseIfRequired != nil { + return *m.OnlyUseIfRequired + } + return Default_CompositeIndex_OnlyUseIfRequired +} + +type IndexPostfix struct { + IndexValue []*IndexPostfix_IndexValue `protobuf:"bytes,1,rep,name=index_value" json:"index_value,omitempty"` + Key *Reference `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"` + Before *bool `protobuf:"varint,3,opt,name=before,def=1" json:"before,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexPostfix) Reset() { *m = IndexPostfix{} } +func (m *IndexPostfix) String() string { return proto.CompactTextString(m) } +func (*IndexPostfix) ProtoMessage() {} + +const Default_IndexPostfix_Before bool = true + +func (m *IndexPostfix) GetIndexValue() []*IndexPostfix_IndexValue { + if m != nil { + return m.IndexValue + } + return nil +} + +func (m *IndexPostfix) GetKey() *Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *IndexPostfix) GetBefore() bool { + if m != nil && m.Before != nil { + return *m.Before + } + return Default_IndexPostfix_Before +} + +type IndexPostfix_IndexValue struct { + PropertyName *string `protobuf:"bytes,1,req,name=property_name" json:"property_name,omitempty"` + Value *PropertyValue `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexPostfix_IndexValue) Reset() { *m = IndexPostfix_IndexValue{} } +func (m *IndexPostfix_IndexValue) String() string { return proto.CompactTextString(m) } +func (*IndexPostfix_IndexValue) ProtoMessage() {} + +func (m *IndexPostfix_IndexValue) GetPropertyName() string { + if m != nil && m.PropertyName != nil { + return *m.PropertyName + } + return "" +} + +func (m *IndexPostfix_IndexValue) GetValue() *PropertyValue { + if m != nil { + return m.Value + } + return nil +} + +type IndexPosition struct { + Key *string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Before *bool `protobuf:"varint,2,opt,name=before,def=1" json:"before,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexPosition) Reset() { *m = IndexPosition{} } +func (m *IndexPosition) String() string { return proto.CompactTextString(m) } +func (*IndexPosition) ProtoMessage() {} + +const Default_IndexPosition_Before bool = true + +func (m *IndexPosition) GetKey() string { + if m != nil && m.Key != nil { + return *m.Key + } + return "" +} + +func (m *IndexPosition) GetBefore() bool { + if m != nil && m.Before != nil { + return *m.Before + } + return Default_IndexPosition_Before +} + +type Snapshot struct { + Ts *int64 `protobuf:"varint,1,req,name=ts" json:"ts,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Snapshot) Reset() { *m = Snapshot{} } +func (m *Snapshot) String() string { return proto.CompactTextString(m) } +func (*Snapshot) ProtoMessage() {} + +func (m *Snapshot) GetTs() int64 { + if m != nil && m.Ts != nil { + return *m.Ts + } + return 0 +} + +type InternalHeader struct { + Qos *string `protobuf:"bytes,1,opt,name=qos" json:"qos,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *InternalHeader) Reset() { *m = InternalHeader{} } +func (m *InternalHeader) String() string { return proto.CompactTextString(m) } +func (*InternalHeader) ProtoMessage() {} + +func (m *InternalHeader) GetQos() string { + if m != nil && m.Qos != nil { + return *m.Qos + } + return "" +} + +type Transaction struct { + Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` + Handle *uint64 `protobuf:"fixed64,1,req,name=handle" json:"handle,omitempty"` + App *string `protobuf:"bytes,2,req,name=app" json:"app,omitempty"` + MarkChanges *bool `protobuf:"varint,3,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Transaction) Reset() { *m = Transaction{} } +func (m *Transaction) String() string { return proto.CompactTextString(m) } +func (*Transaction) ProtoMessage() {} + +const Default_Transaction_MarkChanges bool = false + +func (m *Transaction) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *Transaction) GetHandle() uint64 { + if m != nil && m.Handle != nil { + return *m.Handle + } + return 0 +} + +func (m *Transaction) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +func (m *Transaction) GetMarkChanges() bool { + if m != nil && m.MarkChanges != nil { + return *m.MarkChanges + } + return Default_Transaction_MarkChanges +} + +type Query struct { + Header *InternalHeader `protobuf:"bytes,39,opt,name=header" json:"header,omitempty"` + App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` + NameSpace *string `protobuf:"bytes,29,opt,name=name_space" json:"name_space,omitempty"` + Kind *string `protobuf:"bytes,3,opt,name=kind" json:"kind,omitempty"` + Ancestor *Reference `protobuf:"bytes,17,opt,name=ancestor" json:"ancestor,omitempty"` + Filter []*Query_Filter `protobuf:"group,4,rep,name=Filter" json:"filter,omitempty"` + SearchQuery *string `protobuf:"bytes,8,opt,name=search_query" json:"search_query,omitempty"` + Order []*Query_Order `protobuf:"group,9,rep,name=Order" json:"order,omitempty"` + Hint *Query_Hint `protobuf:"varint,18,opt,name=hint,enum=appengine.Query_Hint" json:"hint,omitempty"` + Count *int32 `protobuf:"varint,23,opt,name=count" json:"count,omitempty"` + Offset *int32 `protobuf:"varint,12,opt,name=offset,def=0" json:"offset,omitempty"` + Limit *int32 `protobuf:"varint,16,opt,name=limit" json:"limit,omitempty"` + CompiledCursor *CompiledCursor `protobuf:"bytes,30,opt,name=compiled_cursor" json:"compiled_cursor,omitempty"` + EndCompiledCursor *CompiledCursor `protobuf:"bytes,31,opt,name=end_compiled_cursor" json:"end_compiled_cursor,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,19,rep,name=composite_index" json:"composite_index,omitempty"` + RequirePerfectPlan *bool `protobuf:"varint,20,opt,name=require_perfect_plan,def=0" json:"require_perfect_plan,omitempty"` + KeysOnly *bool `protobuf:"varint,21,opt,name=keys_only,def=0" json:"keys_only,omitempty"` + Transaction *Transaction `protobuf:"bytes,22,opt,name=transaction" json:"transaction,omitempty"` + Compile *bool `protobuf:"varint,25,opt,name=compile,def=0" json:"compile,omitempty"` + FailoverMs *int64 `protobuf:"varint,26,opt,name=failover_ms" json:"failover_ms,omitempty"` + Strong *bool `protobuf:"varint,32,opt,name=strong" json:"strong,omitempty"` + PropertyName []string `protobuf:"bytes,33,rep,name=property_name" json:"property_name,omitempty"` + GroupByPropertyName []string `protobuf:"bytes,34,rep,name=group_by_property_name" json:"group_by_property_name,omitempty"` + Distinct *bool `protobuf:"varint,24,opt,name=distinct" json:"distinct,omitempty"` + MinSafeTimeSeconds *int64 `protobuf:"varint,35,opt,name=min_safe_time_seconds" json:"min_safe_time_seconds,omitempty"` + SafeReplicaName []string `protobuf:"bytes,36,rep,name=safe_replica_name" json:"safe_replica_name,omitempty"` + PersistOffset *bool `protobuf:"varint,37,opt,name=persist_offset,def=0" json:"persist_offset,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Query) Reset() { *m = Query{} } +func (m *Query) String() string { return proto.CompactTextString(m) } +func (*Query) ProtoMessage() {} + +const Default_Query_Offset int32 = 0 +const Default_Query_RequirePerfectPlan bool = false +const Default_Query_KeysOnly bool = false +const Default_Query_Compile bool = false +const Default_Query_PersistOffset bool = false + +func (m *Query) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *Query) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +func (m *Query) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *Query) GetKind() string { + if m != nil && m.Kind != nil { + return *m.Kind + } + return "" +} + +func (m *Query) GetAncestor() *Reference { + if m != nil { + return m.Ancestor + } + return nil +} + +func (m *Query) GetFilter() []*Query_Filter { + if m != nil { + return m.Filter + } + return nil +} + +func (m *Query) GetSearchQuery() string { + if m != nil && m.SearchQuery != nil { + return *m.SearchQuery + } + return "" +} + +func (m *Query) GetOrder() []*Query_Order { + if m != nil { + return m.Order + } + return nil +} + +func (m *Query) GetHint() Query_Hint { + if m != nil && m.Hint != nil { + return *m.Hint + } + return Query_ORDER_FIRST +} + +func (m *Query) GetCount() int32 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *Query) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return Default_Query_Offset +} + +func (m *Query) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return 0 +} + +func (m *Query) GetCompiledCursor() *CompiledCursor { + if m != nil { + return m.CompiledCursor + } + return nil +} + +func (m *Query) GetEndCompiledCursor() *CompiledCursor { + if m != nil { + return m.EndCompiledCursor + } + return nil +} + +func (m *Query) GetCompositeIndex() []*CompositeIndex { + if m != nil { + return m.CompositeIndex + } + return nil +} + +func (m *Query) GetRequirePerfectPlan() bool { + if m != nil && m.RequirePerfectPlan != nil { + return *m.RequirePerfectPlan + } + return Default_Query_RequirePerfectPlan +} + +func (m *Query) GetKeysOnly() bool { + if m != nil && m.KeysOnly != nil { + return *m.KeysOnly + } + return Default_Query_KeysOnly +} + +func (m *Query) GetTransaction() *Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *Query) GetCompile() bool { + if m != nil && m.Compile != nil { + return *m.Compile + } + return Default_Query_Compile +} + +func (m *Query) GetFailoverMs() int64 { + if m != nil && m.FailoverMs != nil { + return *m.FailoverMs + } + return 0 +} + +func (m *Query) GetStrong() bool { + if m != nil && m.Strong != nil { + return *m.Strong + } + return false +} + +func (m *Query) GetPropertyName() []string { + if m != nil { + return m.PropertyName + } + return nil +} + +func (m *Query) GetGroupByPropertyName() []string { + if m != nil { + return m.GroupByPropertyName + } + return nil +} + +func (m *Query) GetDistinct() bool { + if m != nil && m.Distinct != nil { + return *m.Distinct + } + return false +} + +func (m *Query) GetMinSafeTimeSeconds() int64 { + if m != nil && m.MinSafeTimeSeconds != nil { + return *m.MinSafeTimeSeconds + } + return 0 +} + +func (m *Query) GetSafeReplicaName() []string { + if m != nil { + return m.SafeReplicaName + } + return nil +} + +func (m *Query) GetPersistOffset() bool { + if m != nil && m.PersistOffset != nil { + return *m.PersistOffset + } + return Default_Query_PersistOffset +} + +type Query_Filter struct { + Op *Query_Filter_Operator `protobuf:"varint,6,req,name=op,enum=appengine.Query_Filter_Operator" json:"op,omitempty"` + Property []*Property `protobuf:"bytes,14,rep,name=property" json:"property,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Query_Filter) Reset() { *m = Query_Filter{} } +func (m *Query_Filter) String() string { return proto.CompactTextString(m) } +func (*Query_Filter) ProtoMessage() {} + +func (m *Query_Filter) GetOp() Query_Filter_Operator { + if m != nil && m.Op != nil { + return *m.Op + } + return Query_Filter_LESS_THAN +} + +func (m *Query_Filter) GetProperty() []*Property { + if m != nil { + return m.Property + } + return nil +} + +type Query_Order struct { + Property *string `protobuf:"bytes,10,req,name=property" json:"property,omitempty"` + Direction *Query_Order_Direction `protobuf:"varint,11,opt,name=direction,enum=appengine.Query_Order_Direction,def=1" json:"direction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Query_Order) Reset() { *m = Query_Order{} } +func (m *Query_Order) String() string { return proto.CompactTextString(m) } +func (*Query_Order) ProtoMessage() {} + +const Default_Query_Order_Direction Query_Order_Direction = Query_Order_ASCENDING + +func (m *Query_Order) GetProperty() string { + if m != nil && m.Property != nil { + return *m.Property + } + return "" +} + +func (m *Query_Order) GetDirection() Query_Order_Direction { + if m != nil && m.Direction != nil { + return *m.Direction + } + return Default_Query_Order_Direction +} + +type CompiledQuery struct { + Primaryscan *CompiledQuery_PrimaryScan `protobuf:"group,1,req,name=PrimaryScan" json:"primaryscan,omitempty"` + Mergejoinscan []*CompiledQuery_MergeJoinScan `protobuf:"group,7,rep,name=MergeJoinScan" json:"mergejoinscan,omitempty"` + IndexDef *Index `protobuf:"bytes,21,opt,name=index_def" json:"index_def,omitempty"` + Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` + Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` + KeysOnly *bool `protobuf:"varint,12,req,name=keys_only" json:"keys_only,omitempty"` + PropertyName []string `protobuf:"bytes,24,rep,name=property_name" json:"property_name,omitempty"` + DistinctInfixSize *int32 `protobuf:"varint,25,opt,name=distinct_infix_size" json:"distinct_infix_size,omitempty"` + Entityfilter *CompiledQuery_EntityFilter `protobuf:"group,13,opt,name=EntityFilter" json:"entityfilter,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledQuery) Reset() { *m = CompiledQuery{} } +func (m *CompiledQuery) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery) ProtoMessage() {} + +const Default_CompiledQuery_Offset int32 = 0 + +func (m *CompiledQuery) GetPrimaryscan() *CompiledQuery_PrimaryScan { + if m != nil { + return m.Primaryscan + } + return nil +} + +func (m *CompiledQuery) GetMergejoinscan() []*CompiledQuery_MergeJoinScan { + if m != nil { + return m.Mergejoinscan + } + return nil +} + +func (m *CompiledQuery) GetIndexDef() *Index { + if m != nil { + return m.IndexDef + } + return nil +} + +func (m *CompiledQuery) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return Default_CompiledQuery_Offset +} + +func (m *CompiledQuery) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return 0 +} + +func (m *CompiledQuery) GetKeysOnly() bool { + if m != nil && m.KeysOnly != nil { + return *m.KeysOnly + } + return false +} + +func (m *CompiledQuery) GetPropertyName() []string { + if m != nil { + return m.PropertyName + } + return nil +} + +func (m *CompiledQuery) GetDistinctInfixSize() int32 { + if m != nil && m.DistinctInfixSize != nil { + return *m.DistinctInfixSize + } + return 0 +} + +func (m *CompiledQuery) GetEntityfilter() *CompiledQuery_EntityFilter { + if m != nil { + return m.Entityfilter + } + return nil +} + +type CompiledQuery_PrimaryScan struct { + IndexName *string `protobuf:"bytes,2,opt,name=index_name" json:"index_name,omitempty"` + StartKey *string `protobuf:"bytes,3,opt,name=start_key" json:"start_key,omitempty"` + StartInclusive *bool `protobuf:"varint,4,opt,name=start_inclusive" json:"start_inclusive,omitempty"` + EndKey *string `protobuf:"bytes,5,opt,name=end_key" json:"end_key,omitempty"` + EndInclusive *bool `protobuf:"varint,6,opt,name=end_inclusive" json:"end_inclusive,omitempty"` + StartPostfixValue []string `protobuf:"bytes,22,rep,name=start_postfix_value" json:"start_postfix_value,omitempty"` + EndPostfixValue []string `protobuf:"bytes,23,rep,name=end_postfix_value" json:"end_postfix_value,omitempty"` + EndUnappliedLogTimestampUs *int64 `protobuf:"varint,19,opt,name=end_unapplied_log_timestamp_us" json:"end_unapplied_log_timestamp_us,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledQuery_PrimaryScan) Reset() { *m = CompiledQuery_PrimaryScan{} } +func (m *CompiledQuery_PrimaryScan) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_PrimaryScan) ProtoMessage() {} + +func (m *CompiledQuery_PrimaryScan) GetIndexName() string { + if m != nil && m.IndexName != nil { + return *m.IndexName + } + return "" +} + +func (m *CompiledQuery_PrimaryScan) GetStartKey() string { + if m != nil && m.StartKey != nil { + return *m.StartKey + } + return "" +} + +func (m *CompiledQuery_PrimaryScan) GetStartInclusive() bool { + if m != nil && m.StartInclusive != nil { + return *m.StartInclusive + } + return false +} + +func (m *CompiledQuery_PrimaryScan) GetEndKey() string { + if m != nil && m.EndKey != nil { + return *m.EndKey + } + return "" +} + +func (m *CompiledQuery_PrimaryScan) GetEndInclusive() bool { + if m != nil && m.EndInclusive != nil { + return *m.EndInclusive + } + return false +} + +func (m *CompiledQuery_PrimaryScan) GetStartPostfixValue() []string { + if m != nil { + return m.StartPostfixValue + } + return nil +} + +func (m *CompiledQuery_PrimaryScan) GetEndPostfixValue() []string { + if m != nil { + return m.EndPostfixValue + } + return nil +} + +func (m *CompiledQuery_PrimaryScan) GetEndUnappliedLogTimestampUs() int64 { + if m != nil && m.EndUnappliedLogTimestampUs != nil { + return *m.EndUnappliedLogTimestampUs + } + return 0 +} + +type CompiledQuery_MergeJoinScan struct { + IndexName *string `protobuf:"bytes,8,req,name=index_name" json:"index_name,omitempty"` + PrefixValue []string `protobuf:"bytes,9,rep,name=prefix_value" json:"prefix_value,omitempty"` + ValuePrefix *bool `protobuf:"varint,20,opt,name=value_prefix,def=0" json:"value_prefix,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledQuery_MergeJoinScan) Reset() { *m = CompiledQuery_MergeJoinScan{} } +func (m *CompiledQuery_MergeJoinScan) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_MergeJoinScan) ProtoMessage() {} + +const Default_CompiledQuery_MergeJoinScan_ValuePrefix bool = false + +func (m *CompiledQuery_MergeJoinScan) GetIndexName() string { + if m != nil && m.IndexName != nil { + return *m.IndexName + } + return "" +} + +func (m *CompiledQuery_MergeJoinScan) GetPrefixValue() []string { + if m != nil { + return m.PrefixValue + } + return nil +} + +func (m *CompiledQuery_MergeJoinScan) GetValuePrefix() bool { + if m != nil && m.ValuePrefix != nil { + return *m.ValuePrefix + } + return Default_CompiledQuery_MergeJoinScan_ValuePrefix +} + +type CompiledQuery_EntityFilter struct { + Distinct *bool `protobuf:"varint,14,opt,name=distinct,def=0" json:"distinct,omitempty"` + Kind *string `protobuf:"bytes,17,opt,name=kind" json:"kind,omitempty"` + Ancestor *Reference `protobuf:"bytes,18,opt,name=ancestor" json:"ancestor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledQuery_EntityFilter) Reset() { *m = CompiledQuery_EntityFilter{} } +func (m *CompiledQuery_EntityFilter) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_EntityFilter) ProtoMessage() {} + +const Default_CompiledQuery_EntityFilter_Distinct bool = false + +func (m *CompiledQuery_EntityFilter) GetDistinct() bool { + if m != nil && m.Distinct != nil { + return *m.Distinct + } + return Default_CompiledQuery_EntityFilter_Distinct +} + +func (m *CompiledQuery_EntityFilter) GetKind() string { + if m != nil && m.Kind != nil { + return *m.Kind + } + return "" +} + +func (m *CompiledQuery_EntityFilter) GetAncestor() *Reference { + if m != nil { + return m.Ancestor + } + return nil +} + +type CompiledCursor struct { + Position *CompiledCursor_Position `protobuf:"group,2,opt,name=Position" json:"position,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledCursor) Reset() { *m = CompiledCursor{} } +func (m *CompiledCursor) String() string { return proto.CompactTextString(m) } +func (*CompiledCursor) ProtoMessage() {} + +func (m *CompiledCursor) GetPosition() *CompiledCursor_Position { + if m != nil { + return m.Position + } + return nil +} + +type CompiledCursor_Position struct { + StartKey *string `protobuf:"bytes,27,opt,name=start_key" json:"start_key,omitempty"` + Indexvalue []*CompiledCursor_Position_IndexValue `protobuf:"group,29,rep,name=IndexValue" json:"indexvalue,omitempty"` + Key *Reference `protobuf:"bytes,32,opt,name=key" json:"key,omitempty"` + StartInclusive *bool `protobuf:"varint,28,opt,name=start_inclusive,def=1" json:"start_inclusive,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledCursor_Position) Reset() { *m = CompiledCursor_Position{} } +func (m *CompiledCursor_Position) String() string { return proto.CompactTextString(m) } +func (*CompiledCursor_Position) ProtoMessage() {} + +const Default_CompiledCursor_Position_StartInclusive bool = true + +func (m *CompiledCursor_Position) GetStartKey() string { + if m != nil && m.StartKey != nil { + return *m.StartKey + } + return "" +} + +func (m *CompiledCursor_Position) GetIndexvalue() []*CompiledCursor_Position_IndexValue { + if m != nil { + return m.Indexvalue + } + return nil +} + +func (m *CompiledCursor_Position) GetKey() *Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *CompiledCursor_Position) GetStartInclusive() bool { + if m != nil && m.StartInclusive != nil { + return *m.StartInclusive + } + return Default_CompiledCursor_Position_StartInclusive +} + +type CompiledCursor_Position_IndexValue struct { + Property *string `protobuf:"bytes,30,opt,name=property" json:"property,omitempty"` + Value *PropertyValue `protobuf:"bytes,31,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompiledCursor_Position_IndexValue) Reset() { *m = CompiledCursor_Position_IndexValue{} } +func (m *CompiledCursor_Position_IndexValue) String() string { return proto.CompactTextString(m) } +func (*CompiledCursor_Position_IndexValue) ProtoMessage() {} + +func (m *CompiledCursor_Position_IndexValue) GetProperty() string { + if m != nil && m.Property != nil { + return *m.Property + } + return "" +} + +func (m *CompiledCursor_Position_IndexValue) GetValue() *PropertyValue { + if m != nil { + return m.Value + } + return nil +} + +type Cursor struct { + Cursor *uint64 `protobuf:"fixed64,1,req,name=cursor" json:"cursor,omitempty"` + App *string `protobuf:"bytes,2,opt,name=app" json:"app,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Cursor) Reset() { *m = Cursor{} } +func (m *Cursor) String() string { return proto.CompactTextString(m) } +func (*Cursor) ProtoMessage() {} + +func (m *Cursor) GetCursor() uint64 { + if m != nil && m.Cursor != nil { + return *m.Cursor + } + return 0 +} + +func (m *Cursor) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +type Error struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Error) Reset() { *m = Error{} } +func (m *Error) String() string { return proto.CompactTextString(m) } +func (*Error) ProtoMessage() {} + +type Cost struct { + IndexWrites *int32 `protobuf:"varint,1,opt,name=index_writes" json:"index_writes,omitempty"` + IndexWriteBytes *int32 `protobuf:"varint,2,opt,name=index_write_bytes" json:"index_write_bytes,omitempty"` + EntityWrites *int32 `protobuf:"varint,3,opt,name=entity_writes" json:"entity_writes,omitempty"` + EntityWriteBytes *int32 `protobuf:"varint,4,opt,name=entity_write_bytes" json:"entity_write_bytes,omitempty"` + Commitcost *Cost_CommitCost `protobuf:"group,5,opt,name=CommitCost" json:"commitcost,omitempty"` + ApproximateStorageDelta *int32 `protobuf:"varint,8,opt,name=approximate_storage_delta" json:"approximate_storage_delta,omitempty"` + IdSequenceUpdates *int32 `protobuf:"varint,9,opt,name=id_sequence_updates" json:"id_sequence_updates,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Cost) Reset() { *m = Cost{} } +func (m *Cost) String() string { return proto.CompactTextString(m) } +func (*Cost) ProtoMessage() {} + +func (m *Cost) GetIndexWrites() int32 { + if m != nil && m.IndexWrites != nil { + return *m.IndexWrites + } + return 0 +} + +func (m *Cost) GetIndexWriteBytes() int32 { + if m != nil && m.IndexWriteBytes != nil { + return *m.IndexWriteBytes + } + return 0 +} + +func (m *Cost) GetEntityWrites() int32 { + if m != nil && m.EntityWrites != nil { + return *m.EntityWrites + } + return 0 +} + +func (m *Cost) GetEntityWriteBytes() int32 { + if m != nil && m.EntityWriteBytes != nil { + return *m.EntityWriteBytes + } + return 0 +} + +func (m *Cost) GetCommitcost() *Cost_CommitCost { + if m != nil { + return m.Commitcost + } + return nil +} + +func (m *Cost) GetApproximateStorageDelta() int32 { + if m != nil && m.ApproximateStorageDelta != nil { + return *m.ApproximateStorageDelta + } + return 0 +} + +func (m *Cost) GetIdSequenceUpdates() int32 { + if m != nil && m.IdSequenceUpdates != nil { + return *m.IdSequenceUpdates + } + return 0 +} + +type Cost_CommitCost struct { + RequestedEntityPuts *int32 `protobuf:"varint,6,opt,name=requested_entity_puts" json:"requested_entity_puts,omitempty"` + RequestedEntityDeletes *int32 `protobuf:"varint,7,opt,name=requested_entity_deletes" json:"requested_entity_deletes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Cost_CommitCost) Reset() { *m = Cost_CommitCost{} } +func (m *Cost_CommitCost) String() string { return proto.CompactTextString(m) } +func (*Cost_CommitCost) ProtoMessage() {} + +func (m *Cost_CommitCost) GetRequestedEntityPuts() int32 { + if m != nil && m.RequestedEntityPuts != nil { + return *m.RequestedEntityPuts + } + return 0 +} + +func (m *Cost_CommitCost) GetRequestedEntityDeletes() int32 { + if m != nil && m.RequestedEntityDeletes != nil { + return *m.RequestedEntityDeletes + } + return 0 +} + +type GetRequest struct { + Header *InternalHeader `protobuf:"bytes,6,opt,name=header" json:"header,omitempty"` + Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` + FailoverMs *int64 `protobuf:"varint,3,opt,name=failover_ms" json:"failover_ms,omitempty"` + Strong *bool `protobuf:"varint,4,opt,name=strong" json:"strong,omitempty"` + AllowDeferred *bool `protobuf:"varint,5,opt,name=allow_deferred,def=0" json:"allow_deferred,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetRequest) Reset() { *m = GetRequest{} } +func (m *GetRequest) String() string { return proto.CompactTextString(m) } +func (*GetRequest) ProtoMessage() {} + +const Default_GetRequest_AllowDeferred bool = false + +func (m *GetRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *GetRequest) GetKey() []*Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *GetRequest) GetTransaction() *Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *GetRequest) GetFailoverMs() int64 { + if m != nil && m.FailoverMs != nil { + return *m.FailoverMs + } + return 0 +} + +func (m *GetRequest) GetStrong() bool { + if m != nil && m.Strong != nil { + return *m.Strong + } + return false +} + +func (m *GetRequest) GetAllowDeferred() bool { + if m != nil && m.AllowDeferred != nil { + return *m.AllowDeferred + } + return Default_GetRequest_AllowDeferred +} + +type GetResponse struct { + Entity []*GetResponse_Entity `protobuf:"group,1,rep,name=Entity" json:"entity,omitempty"` + Deferred []*Reference `protobuf:"bytes,5,rep,name=deferred" json:"deferred,omitempty"` + InOrder *bool `protobuf:"varint,6,opt,name=in_order,def=1" json:"in_order,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetResponse) Reset() { *m = GetResponse{} } +func (m *GetResponse) String() string { return proto.CompactTextString(m) } +func (*GetResponse) ProtoMessage() {} + +const Default_GetResponse_InOrder bool = true + +func (m *GetResponse) GetEntity() []*GetResponse_Entity { + if m != nil { + return m.Entity + } + return nil +} + +func (m *GetResponse) GetDeferred() []*Reference { + if m != nil { + return m.Deferred + } + return nil +} + +func (m *GetResponse) GetInOrder() bool { + if m != nil && m.InOrder != nil { + return *m.InOrder + } + return Default_GetResponse_InOrder +} + +type GetResponse_Entity struct { + Entity *EntityProto `protobuf:"bytes,2,opt,name=entity" json:"entity,omitempty"` + Key *Reference `protobuf:"bytes,4,opt,name=key" json:"key,omitempty"` + Version *int64 `protobuf:"varint,3,opt,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetResponse_Entity) Reset() { *m = GetResponse_Entity{} } +func (m *GetResponse_Entity) String() string { return proto.CompactTextString(m) } +func (*GetResponse_Entity) ProtoMessage() {} + +func (m *GetResponse_Entity) GetEntity() *EntityProto { + if m != nil { + return m.Entity + } + return nil +} + +func (m *GetResponse_Entity) GetKey() *Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *GetResponse_Entity) GetVersion() int64 { + if m != nil && m.Version != nil { + return *m.Version + } + return 0 +} + +type PutRequest struct { + Header *InternalHeader `protobuf:"bytes,11,opt,name=header" json:"header,omitempty"` + Entity []*EntityProto `protobuf:"bytes,1,rep,name=entity" json:"entity,omitempty"` + Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,3,rep,name=composite_index" json:"composite_index,omitempty"` + Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` + Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` + MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` + AutoIdPolicy *PutRequest_AutoIdPolicy `protobuf:"varint,10,opt,name=auto_id_policy,enum=appengine.PutRequest_AutoIdPolicy,def=0" json:"auto_id_policy,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PutRequest) Reset() { *m = PutRequest{} } +func (m *PutRequest) String() string { return proto.CompactTextString(m) } +func (*PutRequest) ProtoMessage() {} + +const Default_PutRequest_Trusted bool = false +const Default_PutRequest_Force bool = false +const Default_PutRequest_MarkChanges bool = false +const Default_PutRequest_AutoIdPolicy PutRequest_AutoIdPolicy = PutRequest_CURRENT + +func (m *PutRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *PutRequest) GetEntity() []*EntityProto { + if m != nil { + return m.Entity + } + return nil +} + +func (m *PutRequest) GetTransaction() *Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *PutRequest) GetCompositeIndex() []*CompositeIndex { + if m != nil { + return m.CompositeIndex + } + return nil +} + +func (m *PutRequest) GetTrusted() bool { + if m != nil && m.Trusted != nil { + return *m.Trusted + } + return Default_PutRequest_Trusted +} + +func (m *PutRequest) GetForce() bool { + if m != nil && m.Force != nil { + return *m.Force + } + return Default_PutRequest_Force +} + +func (m *PutRequest) GetMarkChanges() bool { + if m != nil && m.MarkChanges != nil { + return *m.MarkChanges + } + return Default_PutRequest_MarkChanges +} + +func (m *PutRequest) GetSnapshot() []*Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + +func (m *PutRequest) GetAutoIdPolicy() PutRequest_AutoIdPolicy { + if m != nil && m.AutoIdPolicy != nil { + return *m.AutoIdPolicy + } + return Default_PutRequest_AutoIdPolicy +} + +type PutResponse struct { + Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + Cost *Cost `protobuf:"bytes,2,opt,name=cost" json:"cost,omitempty"` + Version []int64 `protobuf:"varint,3,rep,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PutResponse) Reset() { *m = PutResponse{} } +func (m *PutResponse) String() string { return proto.CompactTextString(m) } +func (*PutResponse) ProtoMessage() {} + +func (m *PutResponse) GetKey() []*Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *PutResponse) GetCost() *Cost { + if m != nil { + return m.Cost + } + return nil +} + +func (m *PutResponse) GetVersion() []int64 { + if m != nil { + return m.Version + } + return nil +} + +type TouchRequest struct { + Header *InternalHeader `protobuf:"bytes,10,opt,name=header" json:"header,omitempty"` + Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,2,rep,name=composite_index" json:"composite_index,omitempty"` + Force *bool `protobuf:"varint,3,opt,name=force,def=0" json:"force,omitempty"` + Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TouchRequest) Reset() { *m = TouchRequest{} } +func (m *TouchRequest) String() string { return proto.CompactTextString(m) } +func (*TouchRequest) ProtoMessage() {} + +const Default_TouchRequest_Force bool = false + +func (m *TouchRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *TouchRequest) GetKey() []*Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *TouchRequest) GetCompositeIndex() []*CompositeIndex { + if m != nil { + return m.CompositeIndex + } + return nil +} + +func (m *TouchRequest) GetForce() bool { + if m != nil && m.Force != nil { + return *m.Force + } + return Default_TouchRequest_Force +} + +func (m *TouchRequest) GetSnapshot() []*Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + +type TouchResponse struct { + Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TouchResponse) Reset() { *m = TouchResponse{} } +func (m *TouchResponse) String() string { return proto.CompactTextString(m) } +func (*TouchResponse) ProtoMessage() {} + +func (m *TouchResponse) GetCost() *Cost { + if m != nil { + return m.Cost + } + return nil +} + +type DeleteRequest struct { + Header *InternalHeader `protobuf:"bytes,10,opt,name=header" json:"header,omitempty"` + Key []*Reference `protobuf:"bytes,6,rep,name=key" json:"key,omitempty"` + Transaction *Transaction `protobuf:"bytes,5,opt,name=transaction" json:"transaction,omitempty"` + Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` + Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` + MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} + +const Default_DeleteRequest_Trusted bool = false +const Default_DeleteRequest_Force bool = false +const Default_DeleteRequest_MarkChanges bool = false + +func (m *DeleteRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *DeleteRequest) GetKey() []*Reference { + if m != nil { + return m.Key + } + return nil +} + +func (m *DeleteRequest) GetTransaction() *Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *DeleteRequest) GetTrusted() bool { + if m != nil && m.Trusted != nil { + return *m.Trusted + } + return Default_DeleteRequest_Trusted +} + +func (m *DeleteRequest) GetForce() bool { + if m != nil && m.Force != nil { + return *m.Force + } + return Default_DeleteRequest_Force +} + +func (m *DeleteRequest) GetMarkChanges() bool { + if m != nil && m.MarkChanges != nil { + return *m.MarkChanges + } + return Default_DeleteRequest_MarkChanges +} + +func (m *DeleteRequest) GetSnapshot() []*Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + +type DeleteResponse struct { + Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` + Version []int64 `protobuf:"varint,3,rep,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } +func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteResponse) ProtoMessage() {} + +func (m *DeleteResponse) GetCost() *Cost { + if m != nil { + return m.Cost + } + return nil +} + +func (m *DeleteResponse) GetVersion() []int64 { + if m != nil { + return m.Version + } + return nil +} + +type NextRequest struct { + Header *InternalHeader `protobuf:"bytes,5,opt,name=header" json:"header,omitempty"` + Cursor *Cursor `protobuf:"bytes,1,req,name=cursor" json:"cursor,omitempty"` + Count *int32 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` + Offset *int32 `protobuf:"varint,4,opt,name=offset,def=0" json:"offset,omitempty"` + Compile *bool `protobuf:"varint,3,opt,name=compile,def=0" json:"compile,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *NextRequest) Reset() { *m = NextRequest{} } +func (m *NextRequest) String() string { return proto.CompactTextString(m) } +func (*NextRequest) ProtoMessage() {} + +const Default_NextRequest_Offset int32 = 0 +const Default_NextRequest_Compile bool = false + +func (m *NextRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *NextRequest) GetCursor() *Cursor { + if m != nil { + return m.Cursor + } + return nil +} + +func (m *NextRequest) GetCount() int32 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *NextRequest) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return Default_NextRequest_Offset +} + +func (m *NextRequest) GetCompile() bool { + if m != nil && m.Compile != nil { + return *m.Compile + } + return Default_NextRequest_Compile +} + +type QueryResult struct { + Cursor *Cursor `protobuf:"bytes,1,opt,name=cursor" json:"cursor,omitempty"` + Result []*EntityProto `protobuf:"bytes,2,rep,name=result" json:"result,omitempty"` + SkippedResults *int32 `protobuf:"varint,7,opt,name=skipped_results" json:"skipped_results,omitempty"` + MoreResults *bool `protobuf:"varint,3,req,name=more_results" json:"more_results,omitempty"` + KeysOnly *bool `protobuf:"varint,4,opt,name=keys_only" json:"keys_only,omitempty"` + IndexOnly *bool `protobuf:"varint,9,opt,name=index_only" json:"index_only,omitempty"` + SmallOps *bool `protobuf:"varint,10,opt,name=small_ops" json:"small_ops,omitempty"` + CompiledQuery *CompiledQuery `protobuf:"bytes,5,opt,name=compiled_query" json:"compiled_query,omitempty"` + CompiledCursor *CompiledCursor `protobuf:"bytes,6,opt,name=compiled_cursor" json:"compiled_cursor,omitempty"` + Index []*CompositeIndex `protobuf:"bytes,8,rep,name=index" json:"index,omitempty"` + Version []int64 `protobuf:"varint,11,rep,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *QueryResult) Reset() { *m = QueryResult{} } +func (m *QueryResult) String() string { return proto.CompactTextString(m) } +func (*QueryResult) ProtoMessage() {} + +func (m *QueryResult) GetCursor() *Cursor { + if m != nil { + return m.Cursor + } + return nil +} + +func (m *QueryResult) GetResult() []*EntityProto { + if m != nil { + return m.Result + } + return nil +} + +func (m *QueryResult) GetSkippedResults() int32 { + if m != nil && m.SkippedResults != nil { + return *m.SkippedResults + } + return 0 +} + +func (m *QueryResult) GetMoreResults() bool { + if m != nil && m.MoreResults != nil { + return *m.MoreResults + } + return false +} + +func (m *QueryResult) GetKeysOnly() bool { + if m != nil && m.KeysOnly != nil { + return *m.KeysOnly + } + return false +} + +func (m *QueryResult) GetIndexOnly() bool { + if m != nil && m.IndexOnly != nil { + return *m.IndexOnly + } + return false +} + +func (m *QueryResult) GetSmallOps() bool { + if m != nil && m.SmallOps != nil { + return *m.SmallOps + } + return false +} + +func (m *QueryResult) GetCompiledQuery() *CompiledQuery { + if m != nil { + return m.CompiledQuery + } + return nil +} + +func (m *QueryResult) GetCompiledCursor() *CompiledCursor { + if m != nil { + return m.CompiledCursor + } + return nil +} + +func (m *QueryResult) GetIndex() []*CompositeIndex { + if m != nil { + return m.Index + } + return nil +} + +func (m *QueryResult) GetVersion() []int64 { + if m != nil { + return m.Version + } + return nil +} + +type AllocateIdsRequest struct { + Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` + ModelKey *Reference `protobuf:"bytes,1,opt,name=model_key" json:"model_key,omitempty"` + Size *int64 `protobuf:"varint,2,opt,name=size" json:"size,omitempty"` + Max *int64 `protobuf:"varint,3,opt,name=max" json:"max,omitempty"` + Reserve []*Reference `protobuf:"bytes,5,rep,name=reserve" json:"reserve,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } +func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsRequest) ProtoMessage() {} + +func (m *AllocateIdsRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *AllocateIdsRequest) GetModelKey() *Reference { + if m != nil { + return m.ModelKey + } + return nil +} + +func (m *AllocateIdsRequest) GetSize() int64 { + if m != nil && m.Size != nil { + return *m.Size + } + return 0 +} + +func (m *AllocateIdsRequest) GetMax() int64 { + if m != nil && m.Max != nil { + return *m.Max + } + return 0 +} + +func (m *AllocateIdsRequest) GetReserve() []*Reference { + if m != nil { + return m.Reserve + } + return nil +} + +type AllocateIdsResponse struct { + Start *int64 `protobuf:"varint,1,req,name=start" json:"start,omitempty"` + End *int64 `protobuf:"varint,2,req,name=end" json:"end,omitempty"` + Cost *Cost `protobuf:"bytes,3,opt,name=cost" json:"cost,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } +func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsResponse) ProtoMessage() {} + +func (m *AllocateIdsResponse) GetStart() int64 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *AllocateIdsResponse) GetEnd() int64 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +func (m *AllocateIdsResponse) GetCost() *Cost { + if m != nil { + return m.Cost + } + return nil +} + +type CompositeIndices struct { + Index []*CompositeIndex `protobuf:"bytes,1,rep,name=index" json:"index,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompositeIndices) Reset() { *m = CompositeIndices{} } +func (m *CompositeIndices) String() string { return proto.CompactTextString(m) } +func (*CompositeIndices) ProtoMessage() {} + +func (m *CompositeIndices) GetIndex() []*CompositeIndex { + if m != nil { + return m.Index + } + return nil +} + +type AddActionsRequest struct { + Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` + Transaction *Transaction `protobuf:"bytes,1,req,name=transaction" json:"transaction,omitempty"` + Action []*Action `protobuf:"bytes,2,rep,name=action" json:"action,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AddActionsRequest) Reset() { *m = AddActionsRequest{} } +func (m *AddActionsRequest) String() string { return proto.CompactTextString(m) } +func (*AddActionsRequest) ProtoMessage() {} + +func (m *AddActionsRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *AddActionsRequest) GetTransaction() *Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *AddActionsRequest) GetAction() []*Action { + if m != nil { + return m.Action + } + return nil +} + +type AddActionsResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *AddActionsResponse) Reset() { *m = AddActionsResponse{} } +func (m *AddActionsResponse) String() string { return proto.CompactTextString(m) } +func (*AddActionsResponse) ProtoMessage() {} + +type BeginTransactionRequest struct { + Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` + App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` + AllowMultipleEg *bool `protobuf:"varint,2,opt,name=allow_multiple_eg,def=0" json:"allow_multiple_eg,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } +func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } +func (*BeginTransactionRequest) ProtoMessage() {} + +const Default_BeginTransactionRequest_AllowMultipleEg bool = false + +func (m *BeginTransactionRequest) GetHeader() *InternalHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *BeginTransactionRequest) GetApp() string { + if m != nil && m.App != nil { + return *m.App + } + return "" +} + +func (m *BeginTransactionRequest) GetAllowMultipleEg() bool { + if m != nil && m.AllowMultipleEg != nil { + return *m.AllowMultipleEg + } + return Default_BeginTransactionRequest_AllowMultipleEg +} + +type CommitResponse struct { + Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` + Version []*CommitResponse_Version `protobuf:"group,3,rep,name=Version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CommitResponse) Reset() { *m = CommitResponse{} } +func (m *CommitResponse) String() string { return proto.CompactTextString(m) } +func (*CommitResponse) ProtoMessage() {} + +func (m *CommitResponse) GetCost() *Cost { + if m != nil { + return m.Cost + } + return nil +} + +func (m *CommitResponse) GetVersion() []*CommitResponse_Version { + if m != nil { + return m.Version + } + return nil +} + +type CommitResponse_Version struct { + RootEntityKey *Reference `protobuf:"bytes,4,req,name=root_entity_key" json:"root_entity_key,omitempty"` + Version *int64 `protobuf:"varint,5,req,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CommitResponse_Version) Reset() { *m = CommitResponse_Version{} } +func (m *CommitResponse_Version) String() string { return proto.CompactTextString(m) } +func (*CommitResponse_Version) ProtoMessage() {} + +func (m *CommitResponse_Version) GetRootEntityKey() *Reference { + if m != nil { + return m.RootEntityKey + } + return nil +} + +func (m *CommitResponse_Version) GetVersion() int64 { + if m != nil && m.Version != nil { + return *m.Version + } + return 0 +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto new file mode 100644 index 000000000..e76f126ff --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto @@ -0,0 +1,541 @@ +syntax = "proto2"; +option go_package = "datastore"; + +package appengine; + +message Action{} + +message PropertyValue { + optional int64 int64Value = 1; + optional bool booleanValue = 2; + optional string stringValue = 3; + optional double doubleValue = 4; + + optional group PointValue = 5 { + required double x = 6; + required double y = 7; + } + + optional group UserValue = 8 { + required string email = 9; + required string auth_domain = 10; + optional string nickname = 11; + optional string federated_identity = 21; + optional string federated_provider = 22; + } + + optional group ReferenceValue = 12 { + required string app = 13; + optional string name_space = 20; + repeated group PathElement = 14 { + required string type = 15; + optional int64 id = 16; + optional string name = 17; + } + } +} + +message Property { + enum Meaning { + NO_MEANING = 0; + BLOB = 14; + TEXT = 15; + BYTESTRING = 16; + + ATOM_CATEGORY = 1; + ATOM_LINK = 2; + ATOM_TITLE = 3; + ATOM_CONTENT = 4; + ATOM_SUMMARY = 5; + ATOM_AUTHOR = 6; + + GD_WHEN = 7; + GD_EMAIL = 8; + GEORSS_POINT = 9; + GD_IM = 10; + + GD_PHONENUMBER = 11; + GD_POSTALADDRESS = 12; + + GD_RATING = 13; + + BLOBKEY = 17; + ENTITY_PROTO = 19; + + INDEX_VALUE = 18; + }; + + optional Meaning meaning = 1 [default = NO_MEANING]; + optional string meaning_uri = 2; + + required string name = 3; + + required PropertyValue value = 5; + + required bool multiple = 4; + + optional bool searchable = 6 [default=false]; + + enum FtsTokenizationOption { + HTML = 1; + ATOM = 2; + } + + optional FtsTokenizationOption fts_tokenization_option = 8; + + optional string locale = 9 [default = "en"]; +} + +message Path { + repeated group Element = 1 { + required string type = 2; + optional int64 id = 3; + optional string name = 4; + } +} + +message Reference { + required string app = 13; + optional string name_space = 20; + required Path path = 14; +} + +message User { + required string email = 1; + required string auth_domain = 2; + optional string nickname = 3; + optional string federated_identity = 6; + optional string federated_provider = 7; +} + +message EntityProto { + required Reference key = 13; + required Path entity_group = 16; + optional User owner = 17; + + enum Kind { + GD_CONTACT = 1; + GD_EVENT = 2; + GD_MESSAGE = 3; + } + optional Kind kind = 4; + optional string kind_uri = 5; + + repeated Property property = 14; + repeated Property raw_property = 15; + + optional int32 rank = 18; +} + +message CompositeProperty { + required int64 index_id = 1; + repeated string value = 2; +} + +message Index { + required string entity_type = 1; + required bool ancestor = 5; + repeated group Property = 2 { + required string name = 3; + enum Direction { + ASCENDING = 1; + DESCENDING = 2; + } + optional Direction direction = 4 [default = ASCENDING]; + } +} + +message CompositeIndex { + required string app_id = 1; + required int64 id = 2; + required Index definition = 3; + + enum State { + WRITE_ONLY = 1; + READ_WRITE = 2; + DELETED = 3; + ERROR = 4; + } + required State state = 4; + + optional bool only_use_if_required = 6 [default = false]; +} + +message IndexPostfix { + message IndexValue { + required string property_name = 1; + required PropertyValue value = 2; + } + + repeated IndexValue index_value = 1; + + optional Reference key = 2; + + optional bool before = 3 [default=true]; +} + +message IndexPosition { + optional string key = 1; + + optional bool before = 2 [default=true]; +} + +message Snapshot { + enum Status { + INACTIVE = 0; + ACTIVE = 1; + } + + required int64 ts = 1; +} + +message InternalHeader { + optional string qos = 1; +} + +message Transaction { + optional InternalHeader header = 4; + required fixed64 handle = 1; + required string app = 2; + optional bool mark_changes = 3 [default = false]; +} + +message Query { + optional InternalHeader header = 39; + + required string app = 1; + optional string name_space = 29; + + optional string kind = 3; + optional Reference ancestor = 17; + + repeated group Filter = 4 { + enum Operator { + LESS_THAN = 1; + LESS_THAN_OR_EQUAL = 2; + GREATER_THAN = 3; + GREATER_THAN_OR_EQUAL = 4; + EQUAL = 5; + IN = 6; + EXISTS = 7; + } + + required Operator op = 6; + repeated Property property = 14; + } + + optional string search_query = 8; + + repeated group Order = 9 { + enum Direction { + ASCENDING = 1; + DESCENDING = 2; + } + + required string property = 10; + optional Direction direction = 11 [default = ASCENDING]; + } + + enum Hint { + ORDER_FIRST = 1; + ANCESTOR_FIRST = 2; + FILTER_FIRST = 3; + } + optional Hint hint = 18; + + optional int32 count = 23; + + optional int32 offset = 12 [default = 0]; + + optional int32 limit = 16; + + optional CompiledCursor compiled_cursor = 30; + optional CompiledCursor end_compiled_cursor = 31; + + repeated CompositeIndex composite_index = 19; + + optional bool require_perfect_plan = 20 [default = false]; + + optional bool keys_only = 21 [default = false]; + + optional Transaction transaction = 22; + + optional bool compile = 25 [default = false]; + + optional int64 failover_ms = 26; + + optional bool strong = 32; + + repeated string property_name = 33; + + repeated string group_by_property_name = 34; + + optional bool distinct = 24; + + optional int64 min_safe_time_seconds = 35; + + repeated string safe_replica_name = 36; + + optional bool persist_offset = 37 [default=false]; +} + +message CompiledQuery { + required group PrimaryScan = 1 { + optional string index_name = 2; + + optional string start_key = 3; + optional bool start_inclusive = 4; + optional string end_key = 5; + optional bool end_inclusive = 6; + + repeated string start_postfix_value = 22; + repeated string end_postfix_value = 23; + + optional int64 end_unapplied_log_timestamp_us = 19; + } + + repeated group MergeJoinScan = 7 { + required string index_name = 8; + + repeated string prefix_value = 9; + + optional bool value_prefix = 20 [default=false]; + } + + optional Index index_def = 21; + + optional int32 offset = 10 [default = 0]; + + optional int32 limit = 11; + + required bool keys_only = 12; + + repeated string property_name = 24; + + optional int32 distinct_infix_size = 25; + + optional group EntityFilter = 13 { + optional bool distinct = 14 [default=false]; + + optional string kind = 17; + optional Reference ancestor = 18; + } +} + +message CompiledCursor { + optional group Position = 2 { + optional string start_key = 27; + + repeated group IndexValue = 29 { + optional string property = 30; + required PropertyValue value = 31; + } + + optional Reference key = 32; + + optional bool start_inclusive = 28 [default=true]; + } +} + +message Cursor { + required fixed64 cursor = 1; + + optional string app = 2; +} + +message Error { + enum ErrorCode { + BAD_REQUEST = 1; + CONCURRENT_TRANSACTION = 2; + INTERNAL_ERROR = 3; + NEED_INDEX = 4; + TIMEOUT = 5; + PERMISSION_DENIED = 6; + BIGTABLE_ERROR = 7; + COMMITTED_BUT_STILL_APPLYING = 8; + CAPABILITY_DISABLED = 9; + TRY_ALTERNATE_BACKEND = 10; + SAFE_TIME_TOO_OLD = 11; + } +} + +message Cost { + optional int32 index_writes = 1; + optional int32 index_write_bytes = 2; + optional int32 entity_writes = 3; + optional int32 entity_write_bytes = 4; + optional group CommitCost = 5 { + optional int32 requested_entity_puts = 6; + optional int32 requested_entity_deletes = 7; + }; + optional int32 approximate_storage_delta = 8; + optional int32 id_sequence_updates = 9; +} + +message GetRequest { + optional InternalHeader header = 6; + + repeated Reference key = 1; + optional Transaction transaction = 2; + + optional int64 failover_ms = 3; + + optional bool strong = 4; + + optional bool allow_deferred = 5 [default=false]; +} + +message GetResponse { + repeated group Entity = 1 { + optional EntityProto entity = 2; + optional Reference key = 4; + + optional int64 version = 3; + } + + repeated Reference deferred = 5; + + optional bool in_order = 6 [default=true]; +} + +message PutRequest { + optional InternalHeader header = 11; + + repeated EntityProto entity = 1; + optional Transaction transaction = 2; + repeated CompositeIndex composite_index = 3; + + optional bool trusted = 4 [default = false]; + + optional bool force = 7 [default = false]; + + optional bool mark_changes = 8 [default = false]; + repeated Snapshot snapshot = 9; + + enum AutoIdPolicy { + CURRENT = 0; + SEQUENTIAL = 1; + } + optional AutoIdPolicy auto_id_policy = 10 [default = CURRENT]; +} + +message PutResponse { + repeated Reference key = 1; + optional Cost cost = 2; + repeated int64 version = 3; +} + +message TouchRequest { + optional InternalHeader header = 10; + + repeated Reference key = 1; + repeated CompositeIndex composite_index = 2; + optional bool force = 3 [default = false]; + repeated Snapshot snapshot = 9; +} + +message TouchResponse { + optional Cost cost = 1; +} + +message DeleteRequest { + optional InternalHeader header = 10; + + repeated Reference key = 6; + optional Transaction transaction = 5; + + optional bool trusted = 4 [default = false]; + + optional bool force = 7 [default = false]; + + optional bool mark_changes = 8 [default = false]; + repeated Snapshot snapshot = 9; +} + +message DeleteResponse { + optional Cost cost = 1; + repeated int64 version = 3; +} + +message NextRequest { + optional InternalHeader header = 5; + + required Cursor cursor = 1; + optional int32 count = 2; + + optional int32 offset = 4 [default = 0]; + + optional bool compile = 3 [default = false]; +} + +message QueryResult { + optional Cursor cursor = 1; + + repeated EntityProto result = 2; + + optional int32 skipped_results = 7; + + required bool more_results = 3; + + optional bool keys_only = 4; + + optional bool index_only = 9; + + optional bool small_ops = 10; + + optional CompiledQuery compiled_query = 5; + + optional CompiledCursor compiled_cursor = 6; + + repeated CompositeIndex index = 8; + + repeated int64 version = 11; +} + +message AllocateIdsRequest { + optional InternalHeader header = 4; + + optional Reference model_key = 1; + + optional int64 size = 2; + + optional int64 max = 3; + + repeated Reference reserve = 5; +} + +message AllocateIdsResponse { + required int64 start = 1; + required int64 end = 2; + optional Cost cost = 3; +} + +message CompositeIndices { + repeated CompositeIndex index = 1; +} + +message AddActionsRequest { + optional InternalHeader header = 3; + + required Transaction transaction = 1; + repeated Action action = 2; +} + +message AddActionsResponse { +} + +message BeginTransactionRequest { + optional InternalHeader header = 3; + + required string app = 1; + optional bool allow_multiple_eg = 2 [default = false]; +} + +message CommitResponse { + optional Cost cost = 1; + + repeated group Version = 3 { + required Reference root_entity_key = 4; + required int64 version = 5; + } +} diff --git a/vendor/google.golang.org/appengine/internal/identity.go b/vendor/google.golang.org/appengine/internal/identity.go new file mode 100644 index 000000000..d538701ab --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/identity.go @@ -0,0 +1,14 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +import netcontext "golang.org/x/net/context" + +// These functions are implementations of the wrapper functions +// in ../appengine/identity.go. See that file for commentary. + +func AppID(c netcontext.Context) string { + return appID(FullyQualifiedAppID(c)) +} diff --git a/vendor/google.golang.org/appengine/internal/identity_classic.go b/vendor/google.golang.org/appengine/internal/identity_classic.go new file mode 100644 index 000000000..e6b9227c5 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/identity_classic.go @@ -0,0 +1,27 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import ( + "appengine" + + netcontext "golang.org/x/net/context" +) + +func DefaultVersionHostname(ctx netcontext.Context) string { + return appengine.DefaultVersionHostname(fromContext(ctx)) +} + +func RequestID(ctx netcontext.Context) string { return appengine.RequestID(fromContext(ctx)) } +func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() } +func ServerSoftware() string { return appengine.ServerSoftware() } +func ModuleName(ctx netcontext.Context) string { return appengine.ModuleName(fromContext(ctx)) } +func VersionID(ctx netcontext.Context) string { return appengine.VersionID(fromContext(ctx)) } +func InstanceID() string { return appengine.InstanceID() } +func IsDevAppServer() bool { return appengine.IsDevAppServer() } + +func fullyQualifiedAppID(ctx netcontext.Context) string { return fromContext(ctx).FullyQualifiedAppID() } diff --git a/vendor/google.golang.org/appengine/internal/identity_vm.go b/vendor/google.golang.org/appengine/internal/identity_vm.go new file mode 100644 index 000000000..ebe68b785 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/identity_vm.go @@ -0,0 +1,97 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine + +package internal + +import ( + "net/http" + "os" + + netcontext "golang.org/x/net/context" +) + +// These functions are implementations of the wrapper functions +// in ../appengine/identity.go. See that file for commentary. + +const ( + hDefaultVersionHostname = "X-AppEngine-Default-Version-Hostname" + hRequestLogId = "X-AppEngine-Request-Log-Id" + hDatacenter = "X-AppEngine-Datacenter" +) + +func ctxHeaders(ctx netcontext.Context) http.Header { + return fromContext(ctx).Request().Header +} + +func DefaultVersionHostname(ctx netcontext.Context) string { + return ctxHeaders(ctx).Get(hDefaultVersionHostname) +} + +func RequestID(ctx netcontext.Context) string { + return ctxHeaders(ctx).Get(hRequestLogId) +} + +func Datacenter(ctx netcontext.Context) string { + return ctxHeaders(ctx).Get(hDatacenter) +} + +func ServerSoftware() string { + // TODO(dsymonds): Remove fallback when we've verified this. + if s := os.Getenv("SERVER_SOFTWARE"); s != "" { + return s + } + return "Google App Engine/1.x.x" +} + +// TODO(dsymonds): Remove the metadata fetches. + +func ModuleName(_ netcontext.Context) string { + if s := os.Getenv("GAE_MODULE_NAME"); s != "" { + return s + } + return string(mustGetMetadata("instance/attributes/gae_backend_name")) +} + +func VersionID(_ netcontext.Context) string { + if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" { + return s1 + "." + s2 + } + return string(mustGetMetadata("instance/attributes/gae_backend_version")) + "." + string(mustGetMetadata("instance/attributes/gae_backend_minor_version")) +} + +func InstanceID() string { + if s := os.Getenv("GAE_MODULE_INSTANCE"); s != "" { + return s + } + return string(mustGetMetadata("instance/attributes/gae_backend_instance")) +} + +func partitionlessAppID() string { + // gae_project has everything except the partition prefix. + appID := os.Getenv("GAE_LONG_APP_ID") + if appID == "" { + appID = string(mustGetMetadata("instance/attributes/gae_project")) + } + return appID +} + +func fullyQualifiedAppID(_ netcontext.Context) string { + appID := partitionlessAppID() + + part := os.Getenv("GAE_PARTITION") + if part == "" { + part = string(mustGetMetadata("instance/attributes/gae_partition")) + } + + if part != "" { + appID = part + "~" + appID + } + return appID +} + +func IsDevAppServer() bool { + return os.Getenv("RUN_WITH_DEVAPPSERVER") != "" +} diff --git a/vendor/google.golang.org/appengine/internal/image/images_service.pb.go b/vendor/google.golang.org/appengine/internal/image/images_service.pb.go new file mode 100644 index 000000000..ba7c72206 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/image/images_service.pb.go @@ -0,0 +1,845 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/image/images_service.proto +// DO NOT EDIT! + +/* +Package image is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/image/images_service.proto + +It has these top-level messages: + ImagesServiceError + ImagesServiceTransform + Transform + ImageData + InputSettings + OutputSettings + ImagesTransformRequest + ImagesTransformResponse + CompositeImageOptions + ImagesCanvas + ImagesCompositeRequest + ImagesCompositeResponse + ImagesHistogramRequest + ImagesHistogram + ImagesHistogramResponse + ImagesGetUrlBaseRequest + ImagesGetUrlBaseResponse + ImagesDeleteUrlBaseRequest + ImagesDeleteUrlBaseResponse +*/ +package image + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ImagesServiceError_ErrorCode int32 + +const ( + ImagesServiceError_UNSPECIFIED_ERROR ImagesServiceError_ErrorCode = 1 + ImagesServiceError_BAD_TRANSFORM_DATA ImagesServiceError_ErrorCode = 2 + ImagesServiceError_NOT_IMAGE ImagesServiceError_ErrorCode = 3 + ImagesServiceError_BAD_IMAGE_DATA ImagesServiceError_ErrorCode = 4 + ImagesServiceError_IMAGE_TOO_LARGE ImagesServiceError_ErrorCode = 5 + ImagesServiceError_INVALID_BLOB_KEY ImagesServiceError_ErrorCode = 6 + ImagesServiceError_ACCESS_DENIED ImagesServiceError_ErrorCode = 7 + ImagesServiceError_OBJECT_NOT_FOUND ImagesServiceError_ErrorCode = 8 +) + +var ImagesServiceError_ErrorCode_name = map[int32]string{ + 1: "UNSPECIFIED_ERROR", + 2: "BAD_TRANSFORM_DATA", + 3: "NOT_IMAGE", + 4: "BAD_IMAGE_DATA", + 5: "IMAGE_TOO_LARGE", + 6: "INVALID_BLOB_KEY", + 7: "ACCESS_DENIED", + 8: "OBJECT_NOT_FOUND", +} +var ImagesServiceError_ErrorCode_value = map[string]int32{ + "UNSPECIFIED_ERROR": 1, + "BAD_TRANSFORM_DATA": 2, + "NOT_IMAGE": 3, + "BAD_IMAGE_DATA": 4, + "IMAGE_TOO_LARGE": 5, + "INVALID_BLOB_KEY": 6, + "ACCESS_DENIED": 7, + "OBJECT_NOT_FOUND": 8, +} + +func (x ImagesServiceError_ErrorCode) Enum() *ImagesServiceError_ErrorCode { + p := new(ImagesServiceError_ErrorCode) + *p = x + return p +} +func (x ImagesServiceError_ErrorCode) String() string { + return proto.EnumName(ImagesServiceError_ErrorCode_name, int32(x)) +} +func (x *ImagesServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ImagesServiceError_ErrorCode_value, data, "ImagesServiceError_ErrorCode") + if err != nil { + return err + } + *x = ImagesServiceError_ErrorCode(value) + return nil +} + +type ImagesServiceTransform_Type int32 + +const ( + ImagesServiceTransform_RESIZE ImagesServiceTransform_Type = 1 + ImagesServiceTransform_ROTATE ImagesServiceTransform_Type = 2 + ImagesServiceTransform_HORIZONTAL_FLIP ImagesServiceTransform_Type = 3 + ImagesServiceTransform_VERTICAL_FLIP ImagesServiceTransform_Type = 4 + ImagesServiceTransform_CROP ImagesServiceTransform_Type = 5 + ImagesServiceTransform_IM_FEELING_LUCKY ImagesServiceTransform_Type = 6 +) + +var ImagesServiceTransform_Type_name = map[int32]string{ + 1: "RESIZE", + 2: "ROTATE", + 3: "HORIZONTAL_FLIP", + 4: "VERTICAL_FLIP", + 5: "CROP", + 6: "IM_FEELING_LUCKY", +} +var ImagesServiceTransform_Type_value = map[string]int32{ + "RESIZE": 1, + "ROTATE": 2, + "HORIZONTAL_FLIP": 3, + "VERTICAL_FLIP": 4, + "CROP": 5, + "IM_FEELING_LUCKY": 6, +} + +func (x ImagesServiceTransform_Type) Enum() *ImagesServiceTransform_Type { + p := new(ImagesServiceTransform_Type) + *p = x + return p +} +func (x ImagesServiceTransform_Type) String() string { + return proto.EnumName(ImagesServiceTransform_Type_name, int32(x)) +} +func (x *ImagesServiceTransform_Type) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ImagesServiceTransform_Type_value, data, "ImagesServiceTransform_Type") + if err != nil { + return err + } + *x = ImagesServiceTransform_Type(value) + return nil +} + +type InputSettings_ORIENTATION_CORRECTION_TYPE int32 + +const ( + InputSettings_UNCHANGED_ORIENTATION InputSettings_ORIENTATION_CORRECTION_TYPE = 0 + InputSettings_CORRECT_ORIENTATION InputSettings_ORIENTATION_CORRECTION_TYPE = 1 +) + +var InputSettings_ORIENTATION_CORRECTION_TYPE_name = map[int32]string{ + 0: "UNCHANGED_ORIENTATION", + 1: "CORRECT_ORIENTATION", +} +var InputSettings_ORIENTATION_CORRECTION_TYPE_value = map[string]int32{ + "UNCHANGED_ORIENTATION": 0, + "CORRECT_ORIENTATION": 1, +} + +func (x InputSettings_ORIENTATION_CORRECTION_TYPE) Enum() *InputSettings_ORIENTATION_CORRECTION_TYPE { + p := new(InputSettings_ORIENTATION_CORRECTION_TYPE) + *p = x + return p +} +func (x InputSettings_ORIENTATION_CORRECTION_TYPE) String() string { + return proto.EnumName(InputSettings_ORIENTATION_CORRECTION_TYPE_name, int32(x)) +} +func (x *InputSettings_ORIENTATION_CORRECTION_TYPE) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(InputSettings_ORIENTATION_CORRECTION_TYPE_value, data, "InputSettings_ORIENTATION_CORRECTION_TYPE") + if err != nil { + return err + } + *x = InputSettings_ORIENTATION_CORRECTION_TYPE(value) + return nil +} + +type OutputSettings_MIME_TYPE int32 + +const ( + OutputSettings_PNG OutputSettings_MIME_TYPE = 0 + OutputSettings_JPEG OutputSettings_MIME_TYPE = 1 + OutputSettings_WEBP OutputSettings_MIME_TYPE = 2 +) + +var OutputSettings_MIME_TYPE_name = map[int32]string{ + 0: "PNG", + 1: "JPEG", + 2: "WEBP", +} +var OutputSettings_MIME_TYPE_value = map[string]int32{ + "PNG": 0, + "JPEG": 1, + "WEBP": 2, +} + +func (x OutputSettings_MIME_TYPE) Enum() *OutputSettings_MIME_TYPE { + p := new(OutputSettings_MIME_TYPE) + *p = x + return p +} +func (x OutputSettings_MIME_TYPE) String() string { + return proto.EnumName(OutputSettings_MIME_TYPE_name, int32(x)) +} +func (x *OutputSettings_MIME_TYPE) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(OutputSettings_MIME_TYPE_value, data, "OutputSettings_MIME_TYPE") + if err != nil { + return err + } + *x = OutputSettings_MIME_TYPE(value) + return nil +} + +type CompositeImageOptions_ANCHOR int32 + +const ( + CompositeImageOptions_TOP_LEFT CompositeImageOptions_ANCHOR = 0 + CompositeImageOptions_TOP CompositeImageOptions_ANCHOR = 1 + CompositeImageOptions_TOP_RIGHT CompositeImageOptions_ANCHOR = 2 + CompositeImageOptions_LEFT CompositeImageOptions_ANCHOR = 3 + CompositeImageOptions_CENTER CompositeImageOptions_ANCHOR = 4 + CompositeImageOptions_RIGHT CompositeImageOptions_ANCHOR = 5 + CompositeImageOptions_BOTTOM_LEFT CompositeImageOptions_ANCHOR = 6 + CompositeImageOptions_BOTTOM CompositeImageOptions_ANCHOR = 7 + CompositeImageOptions_BOTTOM_RIGHT CompositeImageOptions_ANCHOR = 8 +) + +var CompositeImageOptions_ANCHOR_name = map[int32]string{ + 0: "TOP_LEFT", + 1: "TOP", + 2: "TOP_RIGHT", + 3: "LEFT", + 4: "CENTER", + 5: "RIGHT", + 6: "BOTTOM_LEFT", + 7: "BOTTOM", + 8: "BOTTOM_RIGHT", +} +var CompositeImageOptions_ANCHOR_value = map[string]int32{ + "TOP_LEFT": 0, + "TOP": 1, + "TOP_RIGHT": 2, + "LEFT": 3, + "CENTER": 4, + "RIGHT": 5, + "BOTTOM_LEFT": 6, + "BOTTOM": 7, + "BOTTOM_RIGHT": 8, +} + +func (x CompositeImageOptions_ANCHOR) Enum() *CompositeImageOptions_ANCHOR { + p := new(CompositeImageOptions_ANCHOR) + *p = x + return p +} +func (x CompositeImageOptions_ANCHOR) String() string { + return proto.EnumName(CompositeImageOptions_ANCHOR_name, int32(x)) +} +func (x *CompositeImageOptions_ANCHOR) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CompositeImageOptions_ANCHOR_value, data, "CompositeImageOptions_ANCHOR") + if err != nil { + return err + } + *x = CompositeImageOptions_ANCHOR(value) + return nil +} + +type ImagesServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesServiceError) Reset() { *m = ImagesServiceError{} } +func (m *ImagesServiceError) String() string { return proto.CompactTextString(m) } +func (*ImagesServiceError) ProtoMessage() {} + +type ImagesServiceTransform struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesServiceTransform) Reset() { *m = ImagesServiceTransform{} } +func (m *ImagesServiceTransform) String() string { return proto.CompactTextString(m) } +func (*ImagesServiceTransform) ProtoMessage() {} + +type Transform struct { + Width *int32 `protobuf:"varint,1,opt,name=width" json:"width,omitempty"` + Height *int32 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + CropToFit *bool `protobuf:"varint,11,opt,name=crop_to_fit,def=0" json:"crop_to_fit,omitempty"` + CropOffsetX *float32 `protobuf:"fixed32,12,opt,name=crop_offset_x,def=0.5" json:"crop_offset_x,omitempty"` + CropOffsetY *float32 `protobuf:"fixed32,13,opt,name=crop_offset_y,def=0.5" json:"crop_offset_y,omitempty"` + Rotate *int32 `protobuf:"varint,3,opt,name=rotate,def=0" json:"rotate,omitempty"` + HorizontalFlip *bool `protobuf:"varint,4,opt,name=horizontal_flip,def=0" json:"horizontal_flip,omitempty"` + VerticalFlip *bool `protobuf:"varint,5,opt,name=vertical_flip,def=0" json:"vertical_flip,omitempty"` + CropLeftX *float32 `protobuf:"fixed32,6,opt,name=crop_left_x,def=0" json:"crop_left_x,omitempty"` + CropTopY *float32 `protobuf:"fixed32,7,opt,name=crop_top_y,def=0" json:"crop_top_y,omitempty"` + CropRightX *float32 `protobuf:"fixed32,8,opt,name=crop_right_x,def=1" json:"crop_right_x,omitempty"` + CropBottomY *float32 `protobuf:"fixed32,9,opt,name=crop_bottom_y,def=1" json:"crop_bottom_y,omitempty"` + Autolevels *bool `protobuf:"varint,10,opt,name=autolevels,def=0" json:"autolevels,omitempty"` + AllowStretch *bool `protobuf:"varint,14,opt,name=allow_stretch,def=0" json:"allow_stretch,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Transform) Reset() { *m = Transform{} } +func (m *Transform) String() string { return proto.CompactTextString(m) } +func (*Transform) ProtoMessage() {} + +const Default_Transform_CropToFit bool = false +const Default_Transform_CropOffsetX float32 = 0.5 +const Default_Transform_CropOffsetY float32 = 0.5 +const Default_Transform_Rotate int32 = 0 +const Default_Transform_HorizontalFlip bool = false +const Default_Transform_VerticalFlip bool = false +const Default_Transform_CropLeftX float32 = 0 +const Default_Transform_CropTopY float32 = 0 +const Default_Transform_CropRightX float32 = 1 +const Default_Transform_CropBottomY float32 = 1 +const Default_Transform_Autolevels bool = false +const Default_Transform_AllowStretch bool = false + +func (m *Transform) GetWidth() int32 { + if m != nil && m.Width != nil { + return *m.Width + } + return 0 +} + +func (m *Transform) GetHeight() int32 { + if m != nil && m.Height != nil { + return *m.Height + } + return 0 +} + +func (m *Transform) GetCropToFit() bool { + if m != nil && m.CropToFit != nil { + return *m.CropToFit + } + return Default_Transform_CropToFit +} + +func (m *Transform) GetCropOffsetX() float32 { + if m != nil && m.CropOffsetX != nil { + return *m.CropOffsetX + } + return Default_Transform_CropOffsetX +} + +func (m *Transform) GetCropOffsetY() float32 { + if m != nil && m.CropOffsetY != nil { + return *m.CropOffsetY + } + return Default_Transform_CropOffsetY +} + +func (m *Transform) GetRotate() int32 { + if m != nil && m.Rotate != nil { + return *m.Rotate + } + return Default_Transform_Rotate +} + +func (m *Transform) GetHorizontalFlip() bool { + if m != nil && m.HorizontalFlip != nil { + return *m.HorizontalFlip + } + return Default_Transform_HorizontalFlip +} + +func (m *Transform) GetVerticalFlip() bool { + if m != nil && m.VerticalFlip != nil { + return *m.VerticalFlip + } + return Default_Transform_VerticalFlip +} + +func (m *Transform) GetCropLeftX() float32 { + if m != nil && m.CropLeftX != nil { + return *m.CropLeftX + } + return Default_Transform_CropLeftX +} + +func (m *Transform) GetCropTopY() float32 { + if m != nil && m.CropTopY != nil { + return *m.CropTopY + } + return Default_Transform_CropTopY +} + +func (m *Transform) GetCropRightX() float32 { + if m != nil && m.CropRightX != nil { + return *m.CropRightX + } + return Default_Transform_CropRightX +} + +func (m *Transform) GetCropBottomY() float32 { + if m != nil && m.CropBottomY != nil { + return *m.CropBottomY + } + return Default_Transform_CropBottomY +} + +func (m *Transform) GetAutolevels() bool { + if m != nil && m.Autolevels != nil { + return *m.Autolevels + } + return Default_Transform_Autolevels +} + +func (m *Transform) GetAllowStretch() bool { + if m != nil && m.AllowStretch != nil { + return *m.AllowStretch + } + return Default_Transform_AllowStretch +} + +type ImageData struct { + Content []byte `protobuf:"bytes,1,req,name=content" json:"content,omitempty"` + BlobKey *string `protobuf:"bytes,2,opt,name=blob_key" json:"blob_key,omitempty"` + Width *int32 `protobuf:"varint,3,opt,name=width" json:"width,omitempty"` + Height *int32 `protobuf:"varint,4,opt,name=height" json:"height,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImageData) Reset() { *m = ImageData{} } +func (m *ImageData) String() string { return proto.CompactTextString(m) } +func (*ImageData) ProtoMessage() {} + +func (m *ImageData) GetContent() []byte { + if m != nil { + return m.Content + } + return nil +} + +func (m *ImageData) GetBlobKey() string { + if m != nil && m.BlobKey != nil { + return *m.BlobKey + } + return "" +} + +func (m *ImageData) GetWidth() int32 { + if m != nil && m.Width != nil { + return *m.Width + } + return 0 +} + +func (m *ImageData) GetHeight() int32 { + if m != nil && m.Height != nil { + return *m.Height + } + return 0 +} + +type InputSettings struct { + CorrectExifOrientation *InputSettings_ORIENTATION_CORRECTION_TYPE `protobuf:"varint,1,opt,name=correct_exif_orientation,enum=appengine.InputSettings_ORIENTATION_CORRECTION_TYPE,def=0" json:"correct_exif_orientation,omitempty"` + ParseMetadata *bool `protobuf:"varint,2,opt,name=parse_metadata,def=0" json:"parse_metadata,omitempty"` + TransparentSubstitutionRgb *int32 `protobuf:"varint,3,opt,name=transparent_substitution_rgb" json:"transparent_substitution_rgb,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *InputSettings) Reset() { *m = InputSettings{} } +func (m *InputSettings) String() string { return proto.CompactTextString(m) } +func (*InputSettings) ProtoMessage() {} + +const Default_InputSettings_CorrectExifOrientation InputSettings_ORIENTATION_CORRECTION_TYPE = InputSettings_UNCHANGED_ORIENTATION +const Default_InputSettings_ParseMetadata bool = false + +func (m *InputSettings) GetCorrectExifOrientation() InputSettings_ORIENTATION_CORRECTION_TYPE { + if m != nil && m.CorrectExifOrientation != nil { + return *m.CorrectExifOrientation + } + return Default_InputSettings_CorrectExifOrientation +} + +func (m *InputSettings) GetParseMetadata() bool { + if m != nil && m.ParseMetadata != nil { + return *m.ParseMetadata + } + return Default_InputSettings_ParseMetadata +} + +func (m *InputSettings) GetTransparentSubstitutionRgb() int32 { + if m != nil && m.TransparentSubstitutionRgb != nil { + return *m.TransparentSubstitutionRgb + } + return 0 +} + +type OutputSettings struct { + MimeType *OutputSettings_MIME_TYPE `protobuf:"varint,1,opt,name=mime_type,enum=appengine.OutputSettings_MIME_TYPE,def=0" json:"mime_type,omitempty"` + Quality *int32 `protobuf:"varint,2,opt,name=quality" json:"quality,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OutputSettings) Reset() { *m = OutputSettings{} } +func (m *OutputSettings) String() string { return proto.CompactTextString(m) } +func (*OutputSettings) ProtoMessage() {} + +const Default_OutputSettings_MimeType OutputSettings_MIME_TYPE = OutputSettings_PNG + +func (m *OutputSettings) GetMimeType() OutputSettings_MIME_TYPE { + if m != nil && m.MimeType != nil { + return *m.MimeType + } + return Default_OutputSettings_MimeType +} + +func (m *OutputSettings) GetQuality() int32 { + if m != nil && m.Quality != nil { + return *m.Quality + } + return 0 +} + +type ImagesTransformRequest struct { + Image *ImageData `protobuf:"bytes,1,req,name=image" json:"image,omitempty"` + Transform []*Transform `protobuf:"bytes,2,rep,name=transform" json:"transform,omitempty"` + Output *OutputSettings `protobuf:"bytes,3,req,name=output" json:"output,omitempty"` + Input *InputSettings `protobuf:"bytes,4,opt,name=input" json:"input,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesTransformRequest) Reset() { *m = ImagesTransformRequest{} } +func (m *ImagesTransformRequest) String() string { return proto.CompactTextString(m) } +func (*ImagesTransformRequest) ProtoMessage() {} + +func (m *ImagesTransformRequest) GetImage() *ImageData { + if m != nil { + return m.Image + } + return nil +} + +func (m *ImagesTransformRequest) GetTransform() []*Transform { + if m != nil { + return m.Transform + } + return nil +} + +func (m *ImagesTransformRequest) GetOutput() *OutputSettings { + if m != nil { + return m.Output + } + return nil +} + +func (m *ImagesTransformRequest) GetInput() *InputSettings { + if m != nil { + return m.Input + } + return nil +} + +type ImagesTransformResponse struct { + Image *ImageData `protobuf:"bytes,1,req,name=image" json:"image,omitempty"` + SourceMetadata *string `protobuf:"bytes,2,opt,name=source_metadata" json:"source_metadata,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesTransformResponse) Reset() { *m = ImagesTransformResponse{} } +func (m *ImagesTransformResponse) String() string { return proto.CompactTextString(m) } +func (*ImagesTransformResponse) ProtoMessage() {} + +func (m *ImagesTransformResponse) GetImage() *ImageData { + if m != nil { + return m.Image + } + return nil +} + +func (m *ImagesTransformResponse) GetSourceMetadata() string { + if m != nil && m.SourceMetadata != nil { + return *m.SourceMetadata + } + return "" +} + +type CompositeImageOptions struct { + SourceIndex *int32 `protobuf:"varint,1,req,name=source_index" json:"source_index,omitempty"` + XOffset *int32 `protobuf:"varint,2,req,name=x_offset" json:"x_offset,omitempty"` + YOffset *int32 `protobuf:"varint,3,req,name=y_offset" json:"y_offset,omitempty"` + Opacity *float32 `protobuf:"fixed32,4,req,name=opacity" json:"opacity,omitempty"` + Anchor *CompositeImageOptions_ANCHOR `protobuf:"varint,5,req,name=anchor,enum=appengine.CompositeImageOptions_ANCHOR" json:"anchor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompositeImageOptions) Reset() { *m = CompositeImageOptions{} } +func (m *CompositeImageOptions) String() string { return proto.CompactTextString(m) } +func (*CompositeImageOptions) ProtoMessage() {} + +func (m *CompositeImageOptions) GetSourceIndex() int32 { + if m != nil && m.SourceIndex != nil { + return *m.SourceIndex + } + return 0 +} + +func (m *CompositeImageOptions) GetXOffset() int32 { + if m != nil && m.XOffset != nil { + return *m.XOffset + } + return 0 +} + +func (m *CompositeImageOptions) GetYOffset() int32 { + if m != nil && m.YOffset != nil { + return *m.YOffset + } + return 0 +} + +func (m *CompositeImageOptions) GetOpacity() float32 { + if m != nil && m.Opacity != nil { + return *m.Opacity + } + return 0 +} + +func (m *CompositeImageOptions) GetAnchor() CompositeImageOptions_ANCHOR { + if m != nil && m.Anchor != nil { + return *m.Anchor + } + return CompositeImageOptions_TOP_LEFT +} + +type ImagesCanvas struct { + Width *int32 `protobuf:"varint,1,req,name=width" json:"width,omitempty"` + Height *int32 `protobuf:"varint,2,req,name=height" json:"height,omitempty"` + Output *OutputSettings `protobuf:"bytes,3,req,name=output" json:"output,omitempty"` + Color *int32 `protobuf:"varint,4,opt,name=color,def=-1" json:"color,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesCanvas) Reset() { *m = ImagesCanvas{} } +func (m *ImagesCanvas) String() string { return proto.CompactTextString(m) } +func (*ImagesCanvas) ProtoMessage() {} + +const Default_ImagesCanvas_Color int32 = -1 + +func (m *ImagesCanvas) GetWidth() int32 { + if m != nil && m.Width != nil { + return *m.Width + } + return 0 +} + +func (m *ImagesCanvas) GetHeight() int32 { + if m != nil && m.Height != nil { + return *m.Height + } + return 0 +} + +func (m *ImagesCanvas) GetOutput() *OutputSettings { + if m != nil { + return m.Output + } + return nil +} + +func (m *ImagesCanvas) GetColor() int32 { + if m != nil && m.Color != nil { + return *m.Color + } + return Default_ImagesCanvas_Color +} + +type ImagesCompositeRequest struct { + Image []*ImageData `protobuf:"bytes,1,rep,name=image" json:"image,omitempty"` + Options []*CompositeImageOptions `protobuf:"bytes,2,rep,name=options" json:"options,omitempty"` + Canvas *ImagesCanvas `protobuf:"bytes,3,req,name=canvas" json:"canvas,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesCompositeRequest) Reset() { *m = ImagesCompositeRequest{} } +func (m *ImagesCompositeRequest) String() string { return proto.CompactTextString(m) } +func (*ImagesCompositeRequest) ProtoMessage() {} + +func (m *ImagesCompositeRequest) GetImage() []*ImageData { + if m != nil { + return m.Image + } + return nil +} + +func (m *ImagesCompositeRequest) GetOptions() []*CompositeImageOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *ImagesCompositeRequest) GetCanvas() *ImagesCanvas { + if m != nil { + return m.Canvas + } + return nil +} + +type ImagesCompositeResponse struct { + Image *ImageData `protobuf:"bytes,1,req,name=image" json:"image,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesCompositeResponse) Reset() { *m = ImagesCompositeResponse{} } +func (m *ImagesCompositeResponse) String() string { return proto.CompactTextString(m) } +func (*ImagesCompositeResponse) ProtoMessage() {} + +func (m *ImagesCompositeResponse) GetImage() *ImageData { + if m != nil { + return m.Image + } + return nil +} + +type ImagesHistogramRequest struct { + Image *ImageData `protobuf:"bytes,1,req,name=image" json:"image,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesHistogramRequest) Reset() { *m = ImagesHistogramRequest{} } +func (m *ImagesHistogramRequest) String() string { return proto.CompactTextString(m) } +func (*ImagesHistogramRequest) ProtoMessage() {} + +func (m *ImagesHistogramRequest) GetImage() *ImageData { + if m != nil { + return m.Image + } + return nil +} + +type ImagesHistogram struct { + Red []int32 `protobuf:"varint,1,rep,name=red" json:"red,omitempty"` + Green []int32 `protobuf:"varint,2,rep,name=green" json:"green,omitempty"` + Blue []int32 `protobuf:"varint,3,rep,name=blue" json:"blue,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesHistogram) Reset() { *m = ImagesHistogram{} } +func (m *ImagesHistogram) String() string { return proto.CompactTextString(m) } +func (*ImagesHistogram) ProtoMessage() {} + +func (m *ImagesHistogram) GetRed() []int32 { + if m != nil { + return m.Red + } + return nil +} + +func (m *ImagesHistogram) GetGreen() []int32 { + if m != nil { + return m.Green + } + return nil +} + +func (m *ImagesHistogram) GetBlue() []int32 { + if m != nil { + return m.Blue + } + return nil +} + +type ImagesHistogramResponse struct { + Histogram *ImagesHistogram `protobuf:"bytes,1,req,name=histogram" json:"histogram,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesHistogramResponse) Reset() { *m = ImagesHistogramResponse{} } +func (m *ImagesHistogramResponse) String() string { return proto.CompactTextString(m) } +func (*ImagesHistogramResponse) ProtoMessage() {} + +func (m *ImagesHistogramResponse) GetHistogram() *ImagesHistogram { + if m != nil { + return m.Histogram + } + return nil +} + +type ImagesGetUrlBaseRequest struct { + BlobKey *string `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + CreateSecureUrl *bool `protobuf:"varint,2,opt,name=create_secure_url,def=0" json:"create_secure_url,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesGetUrlBaseRequest) Reset() { *m = ImagesGetUrlBaseRequest{} } +func (m *ImagesGetUrlBaseRequest) String() string { return proto.CompactTextString(m) } +func (*ImagesGetUrlBaseRequest) ProtoMessage() {} + +const Default_ImagesGetUrlBaseRequest_CreateSecureUrl bool = false + +func (m *ImagesGetUrlBaseRequest) GetBlobKey() string { + if m != nil && m.BlobKey != nil { + return *m.BlobKey + } + return "" +} + +func (m *ImagesGetUrlBaseRequest) GetCreateSecureUrl() bool { + if m != nil && m.CreateSecureUrl != nil { + return *m.CreateSecureUrl + } + return Default_ImagesGetUrlBaseRequest_CreateSecureUrl +} + +type ImagesGetUrlBaseResponse struct { + Url *string `protobuf:"bytes,1,req,name=url" json:"url,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesGetUrlBaseResponse) Reset() { *m = ImagesGetUrlBaseResponse{} } +func (m *ImagesGetUrlBaseResponse) String() string { return proto.CompactTextString(m) } +func (*ImagesGetUrlBaseResponse) ProtoMessage() {} + +func (m *ImagesGetUrlBaseResponse) GetUrl() string { + if m != nil && m.Url != nil { + return *m.Url + } + return "" +} + +type ImagesDeleteUrlBaseRequest struct { + BlobKey *string `protobuf:"bytes,1,req,name=blob_key" json:"blob_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesDeleteUrlBaseRequest) Reset() { *m = ImagesDeleteUrlBaseRequest{} } +func (m *ImagesDeleteUrlBaseRequest) String() string { return proto.CompactTextString(m) } +func (*ImagesDeleteUrlBaseRequest) ProtoMessage() {} + +func (m *ImagesDeleteUrlBaseRequest) GetBlobKey() string { + if m != nil && m.BlobKey != nil { + return *m.BlobKey + } + return "" +} + +type ImagesDeleteUrlBaseResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ImagesDeleteUrlBaseResponse) Reset() { *m = ImagesDeleteUrlBaseResponse{} } +func (m *ImagesDeleteUrlBaseResponse) String() string { return proto.CompactTextString(m) } +func (*ImagesDeleteUrlBaseResponse) ProtoMessage() {} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/image/images_service.proto b/vendor/google.golang.org/appengine/internal/image/images_service.proto new file mode 100644 index 000000000..f0d2ed5d3 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/image/images_service.proto @@ -0,0 +1,162 @@ +syntax = "proto2"; +option go_package = "image"; + +package appengine; + +message ImagesServiceError { + enum ErrorCode { + UNSPECIFIED_ERROR = 1; + BAD_TRANSFORM_DATA = 2; + NOT_IMAGE = 3; + BAD_IMAGE_DATA = 4; + IMAGE_TOO_LARGE = 5; + INVALID_BLOB_KEY = 6; + ACCESS_DENIED = 7; + OBJECT_NOT_FOUND = 8; + } +} + +message ImagesServiceTransform { + enum Type { + RESIZE = 1; + ROTATE = 2; + HORIZONTAL_FLIP = 3; + VERTICAL_FLIP = 4; + CROP = 5; + IM_FEELING_LUCKY = 6; + } +} + +message Transform { + optional int32 width = 1; + optional int32 height = 2; + optional bool crop_to_fit = 11 [default = false]; + optional float crop_offset_x = 12 [default = 0.5]; + optional float crop_offset_y = 13 [default = 0.5]; + + optional int32 rotate = 3 [default = 0]; + + optional bool horizontal_flip = 4 [default = false]; + + optional bool vertical_flip = 5 [default = false]; + + optional float crop_left_x = 6 [default = 0.0]; + optional float crop_top_y = 7 [default = 0.0]; + optional float crop_right_x = 8 [default = 1.0]; + optional float crop_bottom_y = 9 [default = 1.0]; + + optional bool autolevels = 10 [default = false]; + + optional bool allow_stretch = 14 [default = false]; +} + +message ImageData { + required bytes content = 1 [ctype=CORD]; + optional string blob_key = 2; + + optional int32 width = 3; + optional int32 height = 4; +} + +message InputSettings { + enum ORIENTATION_CORRECTION_TYPE { + UNCHANGED_ORIENTATION = 0; + CORRECT_ORIENTATION = 1; + } + optional ORIENTATION_CORRECTION_TYPE correct_exif_orientation = 1 + [default=UNCHANGED_ORIENTATION]; + optional bool parse_metadata = 2 [default=false]; + optional int32 transparent_substitution_rgb = 3; +} + +message OutputSettings { + enum MIME_TYPE { + PNG = 0; + JPEG = 1; + WEBP = 2; + } + + optional MIME_TYPE mime_type = 1 [default=PNG]; + optional int32 quality = 2; +} + +message ImagesTransformRequest { + required ImageData image = 1; + repeated Transform transform = 2; + required OutputSettings output = 3; + optional InputSettings input = 4; +} + +message ImagesTransformResponse { + required ImageData image = 1; + optional string source_metadata = 2; +} + +message CompositeImageOptions { + required int32 source_index = 1; + required int32 x_offset = 2; + required int32 y_offset = 3; + required float opacity = 4; + + enum ANCHOR { + TOP_LEFT = 0; + TOP = 1; + TOP_RIGHT = 2; + LEFT = 3; + CENTER = 4; + RIGHT = 5; + BOTTOM_LEFT = 6; + BOTTOM = 7; + BOTTOM_RIGHT = 8; + } + + required ANCHOR anchor = 5; +} + +message ImagesCanvas { + required int32 width = 1; + required int32 height = 2; + required OutputSettings output = 3; + optional int32 color = 4 [default=-1]; +} + +message ImagesCompositeRequest { + repeated ImageData image = 1; + repeated CompositeImageOptions options = 2; + required ImagesCanvas canvas = 3; +} + +message ImagesCompositeResponse { + required ImageData image = 1; +} + +message ImagesHistogramRequest { + required ImageData image = 1; +} + +message ImagesHistogram { + repeated int32 red = 1; + repeated int32 green = 2; + repeated int32 blue = 3; +} + +message ImagesHistogramResponse { + required ImagesHistogram histogram = 1; +} + +message ImagesGetUrlBaseRequest { + required string blob_key = 1; + + optional bool create_secure_url = 2 [default = false]; +} + +message ImagesGetUrlBaseResponse { + required string url = 1; +} + +message ImagesDeleteUrlBaseRequest { + required string blob_key = 1; +} + +message ImagesDeleteUrlBaseResponse { +} diff --git a/vendor/google.golang.org/appengine/internal/internal.go b/vendor/google.golang.org/appengine/internal/internal.go new file mode 100644 index 000000000..66e8d7686 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/internal.go @@ -0,0 +1,144 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package internal provides support for package appengine. +// +// Programs should not use this package directly. Its API is not stable. +// Use packages appengine and appengine/* instead. +package internal + +import ( + "fmt" + "io" + "log" + "net/http" + "net/url" + "os" + + "github.com/golang/protobuf/proto" + + remotepb "google.golang.org/appengine/internal/remote_api" +) + +// errorCodeMaps is a map of service name to the error code map for the service. +var errorCodeMaps = make(map[string]map[int32]string) + +// RegisterErrorCodeMap is called from API implementations to register their +// error code map. This should only be called from init functions. +func RegisterErrorCodeMap(service string, m map[int32]string) { + errorCodeMaps[service] = m +} + +type timeoutCodeKey struct { + service string + code int32 +} + +// timeoutCodes is the set of service+code pairs that represent timeouts. +var timeoutCodes = make(map[timeoutCodeKey]bool) + +func RegisterTimeoutErrorCode(service string, code int32) { + timeoutCodes[timeoutCodeKey{service, code}] = true +} + +// APIError is the type returned by appengine.Context's Call method +// when an API call fails in an API-specific way. This may be, for instance, +// a taskqueue API call failing with TaskQueueServiceError::UNKNOWN_QUEUE. +type APIError struct { + Service string + Detail string + Code int32 // API-specific error code +} + +func (e *APIError) Error() string { + if e.Code == 0 { + if e.Detail == "" { + return "APIError " + } + return e.Detail + } + s := fmt.Sprintf("API error %d", e.Code) + if m, ok := errorCodeMaps[e.Service]; ok { + s += " (" + e.Service + ": " + m[e.Code] + ")" + } else { + // Shouldn't happen, but provide a bit more detail if it does. + s = e.Service + " " + s + } + if e.Detail != "" { + s += ": " + e.Detail + } + return s +} + +func (e *APIError) IsTimeout() bool { + return timeoutCodes[timeoutCodeKey{e.Service, e.Code}] +} + +// CallError is the type returned by appengine.Context's Call method when an +// API call fails in a generic way, such as RpcError::CAPABILITY_DISABLED. +type CallError struct { + Detail string + Code int32 + // TODO: Remove this if we get a distinguishable error code. + Timeout bool +} + +func (e *CallError) Error() string { + var msg string + switch remotepb.RpcError_ErrorCode(e.Code) { + case remotepb.RpcError_UNKNOWN: + return e.Detail + case remotepb.RpcError_OVER_QUOTA: + msg = "Over quota" + case remotepb.RpcError_CAPABILITY_DISABLED: + msg = "Capability disabled" + case remotepb.RpcError_CANCELLED: + msg = "Canceled" + default: + msg = fmt.Sprintf("Call error %d", e.Code) + } + s := msg + ": " + e.Detail + if e.Timeout { + s += " (timeout)" + } + return s +} + +func (e *CallError) IsTimeout() bool { + return e.Timeout +} + +func Main() { + installHealthChecker(http.DefaultServeMux) + + port := "8080" + if s := os.Getenv("PORT"); s != "" { + port = s + } + + if err := http.ListenAndServe(":"+port, http.HandlerFunc(handleHTTP)); err != nil { + log.Fatalf("http.ListenAndServe: %v", err) + } +} + +func installHealthChecker(mux *http.ServeMux) { + // If no health check handler has been installed by this point, add a trivial one. + const healthPath = "/_ah/health" + hreq := &http.Request{ + Method: "GET", + URL: &url.URL{ + Path: healthPath, + }, + } + if _, pat := mux.Handler(hreq); pat != healthPath { + mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "ok") + }) + } +} + +// NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace. +// The function should be prepared to be called on the same message more than once; it should only modify the +// RPC request the first time. +var NamespaceMods = make(map[string]func(m proto.Message, namespace string)) diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.pb.go b/vendor/google.golang.org/appengine/internal/log/log_service.pb.go new file mode 100644 index 000000000..20c595be3 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/log/log_service.pb.go @@ -0,0 +1,899 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/log/log_service.proto +// DO NOT EDIT! + +/* +Package log is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/log/log_service.proto + +It has these top-level messages: + LogServiceError + UserAppLogLine + UserAppLogGroup + FlushRequest + SetStatusRequest + LogOffset + LogLine + RequestLog + LogModuleVersion + LogReadRequest + LogReadResponse + LogUsageRecord + LogUsageRequest + LogUsageResponse +*/ +package log + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type LogServiceError_ErrorCode int32 + +const ( + LogServiceError_OK LogServiceError_ErrorCode = 0 + LogServiceError_INVALID_REQUEST LogServiceError_ErrorCode = 1 + LogServiceError_STORAGE_ERROR LogServiceError_ErrorCode = 2 +) + +var LogServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INVALID_REQUEST", + 2: "STORAGE_ERROR", +} +var LogServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INVALID_REQUEST": 1, + "STORAGE_ERROR": 2, +} + +func (x LogServiceError_ErrorCode) Enum() *LogServiceError_ErrorCode { + p := new(LogServiceError_ErrorCode) + *p = x + return p +} +func (x LogServiceError_ErrorCode) String() string { + return proto.EnumName(LogServiceError_ErrorCode_name, int32(x)) +} +func (x *LogServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(LogServiceError_ErrorCode_value, data, "LogServiceError_ErrorCode") + if err != nil { + return err + } + *x = LogServiceError_ErrorCode(value) + return nil +} + +type LogServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogServiceError) Reset() { *m = LogServiceError{} } +func (m *LogServiceError) String() string { return proto.CompactTextString(m) } +func (*LogServiceError) ProtoMessage() {} + +type UserAppLogLine struct { + TimestampUsec *int64 `protobuf:"varint,1,req,name=timestamp_usec" json:"timestamp_usec,omitempty"` + Level *int64 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` + Message *string `protobuf:"bytes,3,req,name=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *UserAppLogLine) Reset() { *m = UserAppLogLine{} } +func (m *UserAppLogLine) String() string { return proto.CompactTextString(m) } +func (*UserAppLogLine) ProtoMessage() {} + +func (m *UserAppLogLine) GetTimestampUsec() int64 { + if m != nil && m.TimestampUsec != nil { + return *m.TimestampUsec + } + return 0 +} + +func (m *UserAppLogLine) GetLevel() int64 { + if m != nil && m.Level != nil { + return *m.Level + } + return 0 +} + +func (m *UserAppLogLine) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +type UserAppLogGroup struct { + LogLine []*UserAppLogLine `protobuf:"bytes,2,rep,name=log_line" json:"log_line,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *UserAppLogGroup) Reset() { *m = UserAppLogGroup{} } +func (m *UserAppLogGroup) String() string { return proto.CompactTextString(m) } +func (*UserAppLogGroup) ProtoMessage() {} + +func (m *UserAppLogGroup) GetLogLine() []*UserAppLogLine { + if m != nil { + return m.LogLine + } + return nil +} + +type FlushRequest struct { + Logs []byte `protobuf:"bytes,1,opt,name=logs" json:"logs,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FlushRequest) Reset() { *m = FlushRequest{} } +func (m *FlushRequest) String() string { return proto.CompactTextString(m) } +func (*FlushRequest) ProtoMessage() {} + +func (m *FlushRequest) GetLogs() []byte { + if m != nil { + return m.Logs + } + return nil +} + +type SetStatusRequest struct { + Status *string `protobuf:"bytes,1,req,name=status" json:"status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetStatusRequest) Reset() { *m = SetStatusRequest{} } +func (m *SetStatusRequest) String() string { return proto.CompactTextString(m) } +func (*SetStatusRequest) ProtoMessage() {} + +func (m *SetStatusRequest) GetStatus() string { + if m != nil && m.Status != nil { + return *m.Status + } + return "" +} + +type LogOffset struct { + RequestId []byte `protobuf:"bytes,1,opt,name=request_id" json:"request_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogOffset) Reset() { *m = LogOffset{} } +func (m *LogOffset) String() string { return proto.CompactTextString(m) } +func (*LogOffset) ProtoMessage() {} + +func (m *LogOffset) GetRequestId() []byte { + if m != nil { + return m.RequestId + } + return nil +} + +type LogLine struct { + Time *int64 `protobuf:"varint,1,req,name=time" json:"time,omitempty"` + Level *int32 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` + LogMessage *string `protobuf:"bytes,3,req,name=log_message" json:"log_message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogLine) Reset() { *m = LogLine{} } +func (m *LogLine) String() string { return proto.CompactTextString(m) } +func (*LogLine) ProtoMessage() {} + +func (m *LogLine) GetTime() int64 { + if m != nil && m.Time != nil { + return *m.Time + } + return 0 +} + +func (m *LogLine) GetLevel() int32 { + if m != nil && m.Level != nil { + return *m.Level + } + return 0 +} + +func (m *LogLine) GetLogMessage() string { + if m != nil && m.LogMessage != nil { + return *m.LogMessage + } + return "" +} + +type RequestLog struct { + AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + ModuleId *string `protobuf:"bytes,37,opt,name=module_id,def=default" json:"module_id,omitempty"` + VersionId *string `protobuf:"bytes,2,req,name=version_id" json:"version_id,omitempty"` + RequestId []byte `protobuf:"bytes,3,req,name=request_id" json:"request_id,omitempty"` + Offset *LogOffset `protobuf:"bytes,35,opt,name=offset" json:"offset,omitempty"` + Ip *string `protobuf:"bytes,4,req,name=ip" json:"ip,omitempty"` + Nickname *string `protobuf:"bytes,5,opt,name=nickname" json:"nickname,omitempty"` + StartTime *int64 `protobuf:"varint,6,req,name=start_time" json:"start_time,omitempty"` + EndTime *int64 `protobuf:"varint,7,req,name=end_time" json:"end_time,omitempty"` + Latency *int64 `protobuf:"varint,8,req,name=latency" json:"latency,omitempty"` + Mcycles *int64 `protobuf:"varint,9,req,name=mcycles" json:"mcycles,omitempty"` + Method *string `protobuf:"bytes,10,req,name=method" json:"method,omitempty"` + Resource *string `protobuf:"bytes,11,req,name=resource" json:"resource,omitempty"` + HttpVersion *string `protobuf:"bytes,12,req,name=http_version" json:"http_version,omitempty"` + Status *int32 `protobuf:"varint,13,req,name=status" json:"status,omitempty"` + ResponseSize *int64 `protobuf:"varint,14,req,name=response_size" json:"response_size,omitempty"` + Referrer *string `protobuf:"bytes,15,opt,name=referrer" json:"referrer,omitempty"` + UserAgent *string `protobuf:"bytes,16,opt,name=user_agent" json:"user_agent,omitempty"` + UrlMapEntry *string `protobuf:"bytes,17,req,name=url_map_entry" json:"url_map_entry,omitempty"` + Combined *string `protobuf:"bytes,18,req,name=combined" json:"combined,omitempty"` + ApiMcycles *int64 `protobuf:"varint,19,opt,name=api_mcycles" json:"api_mcycles,omitempty"` + Host *string `protobuf:"bytes,20,opt,name=host" json:"host,omitempty"` + Cost *float64 `protobuf:"fixed64,21,opt,name=cost" json:"cost,omitempty"` + TaskQueueName *string `protobuf:"bytes,22,opt,name=task_queue_name" json:"task_queue_name,omitempty"` + TaskName *string `protobuf:"bytes,23,opt,name=task_name" json:"task_name,omitempty"` + WasLoadingRequest *bool `protobuf:"varint,24,opt,name=was_loading_request" json:"was_loading_request,omitempty"` + PendingTime *int64 `protobuf:"varint,25,opt,name=pending_time" json:"pending_time,omitempty"` + ReplicaIndex *int32 `protobuf:"varint,26,opt,name=replica_index,def=-1" json:"replica_index,omitempty"` + Finished *bool `protobuf:"varint,27,opt,name=finished,def=1" json:"finished,omitempty"` + CloneKey []byte `protobuf:"bytes,28,opt,name=clone_key" json:"clone_key,omitempty"` + Line []*LogLine `protobuf:"bytes,29,rep,name=line" json:"line,omitempty"` + LinesIncomplete *bool `protobuf:"varint,36,opt,name=lines_incomplete" json:"lines_incomplete,omitempty"` + AppEngineRelease []byte `protobuf:"bytes,38,opt,name=app_engine_release" json:"app_engine_release,omitempty"` + ExitReason *int32 `protobuf:"varint,30,opt,name=exit_reason" json:"exit_reason,omitempty"` + WasThrottledForTime *bool `protobuf:"varint,31,opt,name=was_throttled_for_time" json:"was_throttled_for_time,omitempty"` + WasThrottledForRequests *bool `protobuf:"varint,32,opt,name=was_throttled_for_requests" json:"was_throttled_for_requests,omitempty"` + ThrottledTime *int64 `protobuf:"varint,33,opt,name=throttled_time" json:"throttled_time,omitempty"` + ServerName []byte `protobuf:"bytes,34,opt,name=server_name" json:"server_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RequestLog) Reset() { *m = RequestLog{} } +func (m *RequestLog) String() string { return proto.CompactTextString(m) } +func (*RequestLog) ProtoMessage() {} + +const Default_RequestLog_ModuleId string = "default" +const Default_RequestLog_ReplicaIndex int32 = -1 +const Default_RequestLog_Finished bool = true + +func (m *RequestLog) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *RequestLog) GetModuleId() string { + if m != nil && m.ModuleId != nil { + return *m.ModuleId + } + return Default_RequestLog_ModuleId +} + +func (m *RequestLog) GetVersionId() string { + if m != nil && m.VersionId != nil { + return *m.VersionId + } + return "" +} + +func (m *RequestLog) GetRequestId() []byte { + if m != nil { + return m.RequestId + } + return nil +} + +func (m *RequestLog) GetOffset() *LogOffset { + if m != nil { + return m.Offset + } + return nil +} + +func (m *RequestLog) GetIp() string { + if m != nil && m.Ip != nil { + return *m.Ip + } + return "" +} + +func (m *RequestLog) GetNickname() string { + if m != nil && m.Nickname != nil { + return *m.Nickname + } + return "" +} + +func (m *RequestLog) GetStartTime() int64 { + if m != nil && m.StartTime != nil { + return *m.StartTime + } + return 0 +} + +func (m *RequestLog) GetEndTime() int64 { + if m != nil && m.EndTime != nil { + return *m.EndTime + } + return 0 +} + +func (m *RequestLog) GetLatency() int64 { + if m != nil && m.Latency != nil { + return *m.Latency + } + return 0 +} + +func (m *RequestLog) GetMcycles() int64 { + if m != nil && m.Mcycles != nil { + return *m.Mcycles + } + return 0 +} + +func (m *RequestLog) GetMethod() string { + if m != nil && m.Method != nil { + return *m.Method + } + return "" +} + +func (m *RequestLog) GetResource() string { + if m != nil && m.Resource != nil { + return *m.Resource + } + return "" +} + +func (m *RequestLog) GetHttpVersion() string { + if m != nil && m.HttpVersion != nil { + return *m.HttpVersion + } + return "" +} + +func (m *RequestLog) GetStatus() int32 { + if m != nil && m.Status != nil { + return *m.Status + } + return 0 +} + +func (m *RequestLog) GetResponseSize() int64 { + if m != nil && m.ResponseSize != nil { + return *m.ResponseSize + } + return 0 +} + +func (m *RequestLog) GetReferrer() string { + if m != nil && m.Referrer != nil { + return *m.Referrer + } + return "" +} + +func (m *RequestLog) GetUserAgent() string { + if m != nil && m.UserAgent != nil { + return *m.UserAgent + } + return "" +} + +func (m *RequestLog) GetUrlMapEntry() string { + if m != nil && m.UrlMapEntry != nil { + return *m.UrlMapEntry + } + return "" +} + +func (m *RequestLog) GetCombined() string { + if m != nil && m.Combined != nil { + return *m.Combined + } + return "" +} + +func (m *RequestLog) GetApiMcycles() int64 { + if m != nil && m.ApiMcycles != nil { + return *m.ApiMcycles + } + return 0 +} + +func (m *RequestLog) GetHost() string { + if m != nil && m.Host != nil { + return *m.Host + } + return "" +} + +func (m *RequestLog) GetCost() float64 { + if m != nil && m.Cost != nil { + return *m.Cost + } + return 0 +} + +func (m *RequestLog) GetTaskQueueName() string { + if m != nil && m.TaskQueueName != nil { + return *m.TaskQueueName + } + return "" +} + +func (m *RequestLog) GetTaskName() string { + if m != nil && m.TaskName != nil { + return *m.TaskName + } + return "" +} + +func (m *RequestLog) GetWasLoadingRequest() bool { + if m != nil && m.WasLoadingRequest != nil { + return *m.WasLoadingRequest + } + return false +} + +func (m *RequestLog) GetPendingTime() int64 { + if m != nil && m.PendingTime != nil { + return *m.PendingTime + } + return 0 +} + +func (m *RequestLog) GetReplicaIndex() int32 { + if m != nil && m.ReplicaIndex != nil { + return *m.ReplicaIndex + } + return Default_RequestLog_ReplicaIndex +} + +func (m *RequestLog) GetFinished() bool { + if m != nil && m.Finished != nil { + return *m.Finished + } + return Default_RequestLog_Finished +} + +func (m *RequestLog) GetCloneKey() []byte { + if m != nil { + return m.CloneKey + } + return nil +} + +func (m *RequestLog) GetLine() []*LogLine { + if m != nil { + return m.Line + } + return nil +} + +func (m *RequestLog) GetLinesIncomplete() bool { + if m != nil && m.LinesIncomplete != nil { + return *m.LinesIncomplete + } + return false +} + +func (m *RequestLog) GetAppEngineRelease() []byte { + if m != nil { + return m.AppEngineRelease + } + return nil +} + +func (m *RequestLog) GetExitReason() int32 { + if m != nil && m.ExitReason != nil { + return *m.ExitReason + } + return 0 +} + +func (m *RequestLog) GetWasThrottledForTime() bool { + if m != nil && m.WasThrottledForTime != nil { + return *m.WasThrottledForTime + } + return false +} + +func (m *RequestLog) GetWasThrottledForRequests() bool { + if m != nil && m.WasThrottledForRequests != nil { + return *m.WasThrottledForRequests + } + return false +} + +func (m *RequestLog) GetThrottledTime() int64 { + if m != nil && m.ThrottledTime != nil { + return *m.ThrottledTime + } + return 0 +} + +func (m *RequestLog) GetServerName() []byte { + if m != nil { + return m.ServerName + } + return nil +} + +type LogModuleVersion struct { + ModuleId *string `protobuf:"bytes,1,opt,name=module_id,def=default" json:"module_id,omitempty"` + VersionId *string `protobuf:"bytes,2,opt,name=version_id" json:"version_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogModuleVersion) Reset() { *m = LogModuleVersion{} } +func (m *LogModuleVersion) String() string { return proto.CompactTextString(m) } +func (*LogModuleVersion) ProtoMessage() {} + +const Default_LogModuleVersion_ModuleId string = "default" + +func (m *LogModuleVersion) GetModuleId() string { + if m != nil && m.ModuleId != nil { + return *m.ModuleId + } + return Default_LogModuleVersion_ModuleId +} + +func (m *LogModuleVersion) GetVersionId() string { + if m != nil && m.VersionId != nil { + return *m.VersionId + } + return "" +} + +type LogReadRequest struct { + AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"` + ModuleVersion []*LogModuleVersion `protobuf:"bytes,19,rep,name=module_version" json:"module_version,omitempty"` + StartTime *int64 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"` + EndTime *int64 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"` + Offset *LogOffset `protobuf:"bytes,5,opt,name=offset" json:"offset,omitempty"` + RequestId [][]byte `protobuf:"bytes,6,rep,name=request_id" json:"request_id,omitempty"` + MinimumLogLevel *int32 `protobuf:"varint,7,opt,name=minimum_log_level" json:"minimum_log_level,omitempty"` + IncludeIncomplete *bool `protobuf:"varint,8,opt,name=include_incomplete" json:"include_incomplete,omitempty"` + Count *int64 `protobuf:"varint,9,opt,name=count" json:"count,omitempty"` + CombinedLogRegex *string `protobuf:"bytes,14,opt,name=combined_log_regex" json:"combined_log_regex,omitempty"` + HostRegex *string `protobuf:"bytes,15,opt,name=host_regex" json:"host_regex,omitempty"` + ReplicaIndex *int32 `protobuf:"varint,16,opt,name=replica_index" json:"replica_index,omitempty"` + IncludeAppLogs *bool `protobuf:"varint,10,opt,name=include_app_logs" json:"include_app_logs,omitempty"` + AppLogsPerRequest *int32 `protobuf:"varint,17,opt,name=app_logs_per_request" json:"app_logs_per_request,omitempty"` + IncludeHost *bool `protobuf:"varint,11,opt,name=include_host" json:"include_host,omitempty"` + IncludeAll *bool `protobuf:"varint,12,opt,name=include_all" json:"include_all,omitempty"` + CacheIterator *bool `protobuf:"varint,13,opt,name=cache_iterator" json:"cache_iterator,omitempty"` + NumShards *int32 `protobuf:"varint,18,opt,name=num_shards" json:"num_shards,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogReadRequest) Reset() { *m = LogReadRequest{} } +func (m *LogReadRequest) String() string { return proto.CompactTextString(m) } +func (*LogReadRequest) ProtoMessage() {} + +func (m *LogReadRequest) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *LogReadRequest) GetVersionId() []string { + if m != nil { + return m.VersionId + } + return nil +} + +func (m *LogReadRequest) GetModuleVersion() []*LogModuleVersion { + if m != nil { + return m.ModuleVersion + } + return nil +} + +func (m *LogReadRequest) GetStartTime() int64 { + if m != nil && m.StartTime != nil { + return *m.StartTime + } + return 0 +} + +func (m *LogReadRequest) GetEndTime() int64 { + if m != nil && m.EndTime != nil { + return *m.EndTime + } + return 0 +} + +func (m *LogReadRequest) GetOffset() *LogOffset { + if m != nil { + return m.Offset + } + return nil +} + +func (m *LogReadRequest) GetRequestId() [][]byte { + if m != nil { + return m.RequestId + } + return nil +} + +func (m *LogReadRequest) GetMinimumLogLevel() int32 { + if m != nil && m.MinimumLogLevel != nil { + return *m.MinimumLogLevel + } + return 0 +} + +func (m *LogReadRequest) GetIncludeIncomplete() bool { + if m != nil && m.IncludeIncomplete != nil { + return *m.IncludeIncomplete + } + return false +} + +func (m *LogReadRequest) GetCount() int64 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *LogReadRequest) GetCombinedLogRegex() string { + if m != nil && m.CombinedLogRegex != nil { + return *m.CombinedLogRegex + } + return "" +} + +func (m *LogReadRequest) GetHostRegex() string { + if m != nil && m.HostRegex != nil { + return *m.HostRegex + } + return "" +} + +func (m *LogReadRequest) GetReplicaIndex() int32 { + if m != nil && m.ReplicaIndex != nil { + return *m.ReplicaIndex + } + return 0 +} + +func (m *LogReadRequest) GetIncludeAppLogs() bool { + if m != nil && m.IncludeAppLogs != nil { + return *m.IncludeAppLogs + } + return false +} + +func (m *LogReadRequest) GetAppLogsPerRequest() int32 { + if m != nil && m.AppLogsPerRequest != nil { + return *m.AppLogsPerRequest + } + return 0 +} + +func (m *LogReadRequest) GetIncludeHost() bool { + if m != nil && m.IncludeHost != nil { + return *m.IncludeHost + } + return false +} + +func (m *LogReadRequest) GetIncludeAll() bool { + if m != nil && m.IncludeAll != nil { + return *m.IncludeAll + } + return false +} + +func (m *LogReadRequest) GetCacheIterator() bool { + if m != nil && m.CacheIterator != nil { + return *m.CacheIterator + } + return false +} + +func (m *LogReadRequest) GetNumShards() int32 { + if m != nil && m.NumShards != nil { + return *m.NumShards + } + return 0 +} + +type LogReadResponse struct { + Log []*RequestLog `protobuf:"bytes,1,rep,name=log" json:"log,omitempty"` + Offset *LogOffset `protobuf:"bytes,2,opt,name=offset" json:"offset,omitempty"` + LastEndTime *int64 `protobuf:"varint,3,opt,name=last_end_time" json:"last_end_time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogReadResponse) Reset() { *m = LogReadResponse{} } +func (m *LogReadResponse) String() string { return proto.CompactTextString(m) } +func (*LogReadResponse) ProtoMessage() {} + +func (m *LogReadResponse) GetLog() []*RequestLog { + if m != nil { + return m.Log + } + return nil +} + +func (m *LogReadResponse) GetOffset() *LogOffset { + if m != nil { + return m.Offset + } + return nil +} + +func (m *LogReadResponse) GetLastEndTime() int64 { + if m != nil && m.LastEndTime != nil { + return *m.LastEndTime + } + return 0 +} + +type LogUsageRecord struct { + VersionId *string `protobuf:"bytes,1,opt,name=version_id" json:"version_id,omitempty"` + StartTime *int32 `protobuf:"varint,2,opt,name=start_time" json:"start_time,omitempty"` + EndTime *int32 `protobuf:"varint,3,opt,name=end_time" json:"end_time,omitempty"` + Count *int64 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"` + TotalSize *int64 `protobuf:"varint,5,opt,name=total_size" json:"total_size,omitempty"` + Records *int32 `protobuf:"varint,6,opt,name=records" json:"records,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogUsageRecord) Reset() { *m = LogUsageRecord{} } +func (m *LogUsageRecord) String() string { return proto.CompactTextString(m) } +func (*LogUsageRecord) ProtoMessage() {} + +func (m *LogUsageRecord) GetVersionId() string { + if m != nil && m.VersionId != nil { + return *m.VersionId + } + return "" +} + +func (m *LogUsageRecord) GetStartTime() int32 { + if m != nil && m.StartTime != nil { + return *m.StartTime + } + return 0 +} + +func (m *LogUsageRecord) GetEndTime() int32 { + if m != nil && m.EndTime != nil { + return *m.EndTime + } + return 0 +} + +func (m *LogUsageRecord) GetCount() int64 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *LogUsageRecord) GetTotalSize() int64 { + if m != nil && m.TotalSize != nil { + return *m.TotalSize + } + return 0 +} + +func (m *LogUsageRecord) GetRecords() int32 { + if m != nil && m.Records != nil { + return *m.Records + } + return 0 +} + +type LogUsageRequest struct { + AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"` + StartTime *int32 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"` + EndTime *int32 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"` + ResolutionHours *uint32 `protobuf:"varint,5,opt,name=resolution_hours,def=1" json:"resolution_hours,omitempty"` + CombineVersions *bool `protobuf:"varint,6,opt,name=combine_versions" json:"combine_versions,omitempty"` + UsageVersion *int32 `protobuf:"varint,7,opt,name=usage_version" json:"usage_version,omitempty"` + VersionsOnly *bool `protobuf:"varint,8,opt,name=versions_only" json:"versions_only,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogUsageRequest) Reset() { *m = LogUsageRequest{} } +func (m *LogUsageRequest) String() string { return proto.CompactTextString(m) } +func (*LogUsageRequest) ProtoMessage() {} + +const Default_LogUsageRequest_ResolutionHours uint32 = 1 + +func (m *LogUsageRequest) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *LogUsageRequest) GetVersionId() []string { + if m != nil { + return m.VersionId + } + return nil +} + +func (m *LogUsageRequest) GetStartTime() int32 { + if m != nil && m.StartTime != nil { + return *m.StartTime + } + return 0 +} + +func (m *LogUsageRequest) GetEndTime() int32 { + if m != nil && m.EndTime != nil { + return *m.EndTime + } + return 0 +} + +func (m *LogUsageRequest) GetResolutionHours() uint32 { + if m != nil && m.ResolutionHours != nil { + return *m.ResolutionHours + } + return Default_LogUsageRequest_ResolutionHours +} + +func (m *LogUsageRequest) GetCombineVersions() bool { + if m != nil && m.CombineVersions != nil { + return *m.CombineVersions + } + return false +} + +func (m *LogUsageRequest) GetUsageVersion() int32 { + if m != nil && m.UsageVersion != nil { + return *m.UsageVersion + } + return 0 +} + +func (m *LogUsageRequest) GetVersionsOnly() bool { + if m != nil && m.VersionsOnly != nil { + return *m.VersionsOnly + } + return false +} + +type LogUsageResponse struct { + Usage []*LogUsageRecord `protobuf:"bytes,1,rep,name=usage" json:"usage,omitempty"` + Summary *LogUsageRecord `protobuf:"bytes,2,opt,name=summary" json:"summary,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LogUsageResponse) Reset() { *m = LogUsageResponse{} } +func (m *LogUsageResponse) String() string { return proto.CompactTextString(m) } +func (*LogUsageResponse) ProtoMessage() {} + +func (m *LogUsageResponse) GetUsage() []*LogUsageRecord { + if m != nil { + return m.Usage + } + return nil +} + +func (m *LogUsageResponse) GetSummary() *LogUsageRecord { + if m != nil { + return m.Summary + } + return nil +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.proto b/vendor/google.golang.org/appengine/internal/log/log_service.proto new file mode 100644 index 000000000..8981dc475 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/log/log_service.proto @@ -0,0 +1,150 @@ +syntax = "proto2"; +option go_package = "log"; + +package appengine; + +message LogServiceError { + enum ErrorCode { + OK = 0; + INVALID_REQUEST = 1; + STORAGE_ERROR = 2; + } +} + +message UserAppLogLine { + required int64 timestamp_usec = 1; + required int64 level = 2; + required string message = 3; +} + +message UserAppLogGroup { + repeated UserAppLogLine log_line = 2; +} + +message FlushRequest { + optional bytes logs = 1; +} + +message SetStatusRequest { + required string status = 1; +} + + +message LogOffset { + optional bytes request_id = 1; +} + +message LogLine { + required int64 time = 1; + required int32 level = 2; + required string log_message = 3; +} + +message RequestLog { + required string app_id = 1; + optional string module_id = 37 [default="default"]; + required string version_id = 2; + required bytes request_id = 3; + optional LogOffset offset = 35; + required string ip = 4; + optional string nickname = 5; + required int64 start_time = 6; + required int64 end_time = 7; + required int64 latency = 8; + required int64 mcycles = 9; + required string method = 10; + required string resource = 11; + required string http_version = 12; + required int32 status = 13; + required int64 response_size = 14; + optional string referrer = 15; + optional string user_agent = 16; + required string url_map_entry = 17; + required string combined = 18; + optional int64 api_mcycles = 19; + optional string host = 20; + optional double cost = 21; + + optional string task_queue_name = 22; + optional string task_name = 23; + + optional bool was_loading_request = 24; + optional int64 pending_time = 25; + optional int32 replica_index = 26 [default = -1]; + optional bool finished = 27 [default = true]; + optional bytes clone_key = 28; + + repeated LogLine line = 29; + + optional bool lines_incomplete = 36; + optional bytes app_engine_release = 38; + + optional int32 exit_reason = 30; + optional bool was_throttled_for_time = 31; + optional bool was_throttled_for_requests = 32; + optional int64 throttled_time = 33; + + optional bytes server_name = 34; +} + +message LogModuleVersion { + optional string module_id = 1 [default="default"]; + optional string version_id = 2; +} + +message LogReadRequest { + required string app_id = 1; + repeated string version_id = 2; + repeated LogModuleVersion module_version = 19; + + optional int64 start_time = 3; + optional int64 end_time = 4; + optional LogOffset offset = 5; + repeated bytes request_id = 6; + + optional int32 minimum_log_level = 7; + optional bool include_incomplete = 8; + optional int64 count = 9; + + optional string combined_log_regex = 14; + optional string host_regex = 15; + optional int32 replica_index = 16; + + optional bool include_app_logs = 10; + optional int32 app_logs_per_request = 17; + optional bool include_host = 11; + optional bool include_all = 12; + optional bool cache_iterator = 13; + optional int32 num_shards = 18; +} + +message LogReadResponse { + repeated RequestLog log = 1; + optional LogOffset offset = 2; + optional int64 last_end_time = 3; +} + +message LogUsageRecord { + optional string version_id = 1; + optional int32 start_time = 2; + optional int32 end_time = 3; + optional int64 count = 4; + optional int64 total_size = 5; + optional int32 records = 6; +} + +message LogUsageRequest { + required string app_id = 1; + repeated string version_id = 2; + optional int32 start_time = 3; + optional int32 end_time = 4; + optional uint32 resolution_hours = 5 [default = 1]; + optional bool combine_versions = 6; + optional int32 usage_version = 7; + optional bool versions_only = 8; +} + +message LogUsageResponse { + repeated LogUsageRecord usage = 1; + optional LogUsageRecord summary = 2; +} diff --git a/vendor/google.golang.org/appengine/internal/mail/mail_service.pb.go b/vendor/google.golang.org/appengine/internal/mail/mail_service.pb.go new file mode 100644 index 000000000..b8d5f0301 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/mail/mail_service.pb.go @@ -0,0 +1,229 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/mail/mail_service.proto +// DO NOT EDIT! + +/* +Package mail is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/mail/mail_service.proto + +It has these top-level messages: + MailServiceError + MailAttachment + MailHeader + MailMessage +*/ +package mail + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type MailServiceError_ErrorCode int32 + +const ( + MailServiceError_OK MailServiceError_ErrorCode = 0 + MailServiceError_INTERNAL_ERROR MailServiceError_ErrorCode = 1 + MailServiceError_BAD_REQUEST MailServiceError_ErrorCode = 2 + MailServiceError_UNAUTHORIZED_SENDER MailServiceError_ErrorCode = 3 + MailServiceError_INVALID_ATTACHMENT_TYPE MailServiceError_ErrorCode = 4 + MailServiceError_INVALID_HEADER_NAME MailServiceError_ErrorCode = 5 + MailServiceError_INVALID_CONTENT_ID MailServiceError_ErrorCode = 6 +) + +var MailServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INTERNAL_ERROR", + 2: "BAD_REQUEST", + 3: "UNAUTHORIZED_SENDER", + 4: "INVALID_ATTACHMENT_TYPE", + 5: "INVALID_HEADER_NAME", + 6: "INVALID_CONTENT_ID", +} +var MailServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INTERNAL_ERROR": 1, + "BAD_REQUEST": 2, + "UNAUTHORIZED_SENDER": 3, + "INVALID_ATTACHMENT_TYPE": 4, + "INVALID_HEADER_NAME": 5, + "INVALID_CONTENT_ID": 6, +} + +func (x MailServiceError_ErrorCode) Enum() *MailServiceError_ErrorCode { + p := new(MailServiceError_ErrorCode) + *p = x + return p +} +func (x MailServiceError_ErrorCode) String() string { + return proto.EnumName(MailServiceError_ErrorCode_name, int32(x)) +} +func (x *MailServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MailServiceError_ErrorCode_value, data, "MailServiceError_ErrorCode") + if err != nil { + return err + } + *x = MailServiceError_ErrorCode(value) + return nil +} + +type MailServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *MailServiceError) Reset() { *m = MailServiceError{} } +func (m *MailServiceError) String() string { return proto.CompactTextString(m) } +func (*MailServiceError) ProtoMessage() {} + +type MailAttachment struct { + FileName *string `protobuf:"bytes,1,req,name=FileName" json:"FileName,omitempty"` + Data []byte `protobuf:"bytes,2,req,name=Data" json:"Data,omitempty"` + ContentID *string `protobuf:"bytes,3,opt,name=ContentID" json:"ContentID,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MailAttachment) Reset() { *m = MailAttachment{} } +func (m *MailAttachment) String() string { return proto.CompactTextString(m) } +func (*MailAttachment) ProtoMessage() {} + +func (m *MailAttachment) GetFileName() string { + if m != nil && m.FileName != nil { + return *m.FileName + } + return "" +} + +func (m *MailAttachment) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *MailAttachment) GetContentID() string { + if m != nil && m.ContentID != nil { + return *m.ContentID + } + return "" +} + +type MailHeader struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Value *string `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MailHeader) Reset() { *m = MailHeader{} } +func (m *MailHeader) String() string { return proto.CompactTextString(m) } +func (*MailHeader) ProtoMessage() {} + +func (m *MailHeader) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *MailHeader) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +type MailMessage struct { + Sender *string `protobuf:"bytes,1,req,name=Sender" json:"Sender,omitempty"` + ReplyTo *string `protobuf:"bytes,2,opt,name=ReplyTo" json:"ReplyTo,omitempty"` + To []string `protobuf:"bytes,3,rep,name=To" json:"To,omitempty"` + Cc []string `protobuf:"bytes,4,rep,name=Cc" json:"Cc,omitempty"` + Bcc []string `protobuf:"bytes,5,rep,name=Bcc" json:"Bcc,omitempty"` + Subject *string `protobuf:"bytes,6,req,name=Subject" json:"Subject,omitempty"` + TextBody *string `protobuf:"bytes,7,opt,name=TextBody" json:"TextBody,omitempty"` + HtmlBody *string `protobuf:"bytes,8,opt,name=HtmlBody" json:"HtmlBody,omitempty"` + Attachment []*MailAttachment `protobuf:"bytes,9,rep,name=Attachment" json:"Attachment,omitempty"` + Header []*MailHeader `protobuf:"bytes,10,rep,name=Header" json:"Header,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MailMessage) Reset() { *m = MailMessage{} } +func (m *MailMessage) String() string { return proto.CompactTextString(m) } +func (*MailMessage) ProtoMessage() {} + +func (m *MailMessage) GetSender() string { + if m != nil && m.Sender != nil { + return *m.Sender + } + return "" +} + +func (m *MailMessage) GetReplyTo() string { + if m != nil && m.ReplyTo != nil { + return *m.ReplyTo + } + return "" +} + +func (m *MailMessage) GetTo() []string { + if m != nil { + return m.To + } + return nil +} + +func (m *MailMessage) GetCc() []string { + if m != nil { + return m.Cc + } + return nil +} + +func (m *MailMessage) GetBcc() []string { + if m != nil { + return m.Bcc + } + return nil +} + +func (m *MailMessage) GetSubject() string { + if m != nil && m.Subject != nil { + return *m.Subject + } + return "" +} + +func (m *MailMessage) GetTextBody() string { + if m != nil && m.TextBody != nil { + return *m.TextBody + } + return "" +} + +func (m *MailMessage) GetHtmlBody() string { + if m != nil && m.HtmlBody != nil { + return *m.HtmlBody + } + return "" +} + +func (m *MailMessage) GetAttachment() []*MailAttachment { + if m != nil { + return m.Attachment + } + return nil +} + +func (m *MailMessage) GetHeader() []*MailHeader { + if m != nil { + return m.Header + } + return nil +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/mail/mail_service.proto b/vendor/google.golang.org/appengine/internal/mail/mail_service.proto new file mode 100644 index 000000000..4e57b7aa5 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/mail/mail_service.proto @@ -0,0 +1,45 @@ +syntax = "proto2"; +option go_package = "mail"; + +package appengine; + +message MailServiceError { + enum ErrorCode { + OK = 0; + INTERNAL_ERROR = 1; + BAD_REQUEST = 2; + UNAUTHORIZED_SENDER = 3; + INVALID_ATTACHMENT_TYPE = 4; + INVALID_HEADER_NAME = 5; + INVALID_CONTENT_ID = 6; + } +} + +message MailAttachment { + required string FileName = 1; + required bytes Data = 2; + optional string ContentID = 3; +} + +message MailHeader { + required string name = 1; + required string value = 2; +} + +message MailMessage { + required string Sender = 1; + optional string ReplyTo = 2; + + repeated string To = 3; + repeated string Cc = 4; + repeated string Bcc = 5; + + required string Subject = 6; + + optional string TextBody = 7; + optional string HtmlBody = 8; + + repeated MailAttachment Attachment = 9; + + repeated MailHeader Header = 10; +} diff --git a/vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go b/vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go new file mode 100644 index 000000000..252fef869 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go @@ -0,0 +1,938 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/memcache/memcache_service.proto +// DO NOT EDIT! + +/* +Package memcache is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/memcache/memcache_service.proto + +It has these top-level messages: + MemcacheServiceError + AppOverride + MemcacheGetRequest + MemcacheGetResponse + MemcacheSetRequest + MemcacheSetResponse + MemcacheDeleteRequest + MemcacheDeleteResponse + MemcacheIncrementRequest + MemcacheIncrementResponse + MemcacheBatchIncrementRequest + MemcacheBatchIncrementResponse + MemcacheFlushRequest + MemcacheFlushResponse + MemcacheStatsRequest + MergedNamespaceStats + MemcacheStatsResponse + MemcacheGrabTailRequest + MemcacheGrabTailResponse +*/ +package memcache + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type MemcacheServiceError_ErrorCode int32 + +const ( + MemcacheServiceError_OK MemcacheServiceError_ErrorCode = 0 + MemcacheServiceError_UNSPECIFIED_ERROR MemcacheServiceError_ErrorCode = 1 + MemcacheServiceError_NAMESPACE_NOT_SET MemcacheServiceError_ErrorCode = 2 + MemcacheServiceError_PERMISSION_DENIED MemcacheServiceError_ErrorCode = 3 + MemcacheServiceError_INVALID_VALUE MemcacheServiceError_ErrorCode = 6 +) + +var MemcacheServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "UNSPECIFIED_ERROR", + 2: "NAMESPACE_NOT_SET", + 3: "PERMISSION_DENIED", + 6: "INVALID_VALUE", +} +var MemcacheServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "UNSPECIFIED_ERROR": 1, + "NAMESPACE_NOT_SET": 2, + "PERMISSION_DENIED": 3, + "INVALID_VALUE": 6, +} + +func (x MemcacheServiceError_ErrorCode) Enum() *MemcacheServiceError_ErrorCode { + p := new(MemcacheServiceError_ErrorCode) + *p = x + return p +} +func (x MemcacheServiceError_ErrorCode) String() string { + return proto.EnumName(MemcacheServiceError_ErrorCode_name, int32(x)) +} +func (x *MemcacheServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheServiceError_ErrorCode_value, data, "MemcacheServiceError_ErrorCode") + if err != nil { + return err + } + *x = MemcacheServiceError_ErrorCode(value) + return nil +} + +type MemcacheSetRequest_SetPolicy int32 + +const ( + MemcacheSetRequest_SET MemcacheSetRequest_SetPolicy = 1 + MemcacheSetRequest_ADD MemcacheSetRequest_SetPolicy = 2 + MemcacheSetRequest_REPLACE MemcacheSetRequest_SetPolicy = 3 + MemcacheSetRequest_CAS MemcacheSetRequest_SetPolicy = 4 +) + +var MemcacheSetRequest_SetPolicy_name = map[int32]string{ + 1: "SET", + 2: "ADD", + 3: "REPLACE", + 4: "CAS", +} +var MemcacheSetRequest_SetPolicy_value = map[string]int32{ + "SET": 1, + "ADD": 2, + "REPLACE": 3, + "CAS": 4, +} + +func (x MemcacheSetRequest_SetPolicy) Enum() *MemcacheSetRequest_SetPolicy { + p := new(MemcacheSetRequest_SetPolicy) + *p = x + return p +} +func (x MemcacheSetRequest_SetPolicy) String() string { + return proto.EnumName(MemcacheSetRequest_SetPolicy_name, int32(x)) +} +func (x *MemcacheSetRequest_SetPolicy) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheSetRequest_SetPolicy_value, data, "MemcacheSetRequest_SetPolicy") + if err != nil { + return err + } + *x = MemcacheSetRequest_SetPolicy(value) + return nil +} + +type MemcacheSetResponse_SetStatusCode int32 + +const ( + MemcacheSetResponse_STORED MemcacheSetResponse_SetStatusCode = 1 + MemcacheSetResponse_NOT_STORED MemcacheSetResponse_SetStatusCode = 2 + MemcacheSetResponse_ERROR MemcacheSetResponse_SetStatusCode = 3 + MemcacheSetResponse_EXISTS MemcacheSetResponse_SetStatusCode = 4 +) + +var MemcacheSetResponse_SetStatusCode_name = map[int32]string{ + 1: "STORED", + 2: "NOT_STORED", + 3: "ERROR", + 4: "EXISTS", +} +var MemcacheSetResponse_SetStatusCode_value = map[string]int32{ + "STORED": 1, + "NOT_STORED": 2, + "ERROR": 3, + "EXISTS": 4, +} + +func (x MemcacheSetResponse_SetStatusCode) Enum() *MemcacheSetResponse_SetStatusCode { + p := new(MemcacheSetResponse_SetStatusCode) + *p = x + return p +} +func (x MemcacheSetResponse_SetStatusCode) String() string { + return proto.EnumName(MemcacheSetResponse_SetStatusCode_name, int32(x)) +} +func (x *MemcacheSetResponse_SetStatusCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheSetResponse_SetStatusCode_value, data, "MemcacheSetResponse_SetStatusCode") + if err != nil { + return err + } + *x = MemcacheSetResponse_SetStatusCode(value) + return nil +} + +type MemcacheDeleteResponse_DeleteStatusCode int32 + +const ( + MemcacheDeleteResponse_DELETED MemcacheDeleteResponse_DeleteStatusCode = 1 + MemcacheDeleteResponse_NOT_FOUND MemcacheDeleteResponse_DeleteStatusCode = 2 +) + +var MemcacheDeleteResponse_DeleteStatusCode_name = map[int32]string{ + 1: "DELETED", + 2: "NOT_FOUND", +} +var MemcacheDeleteResponse_DeleteStatusCode_value = map[string]int32{ + "DELETED": 1, + "NOT_FOUND": 2, +} + +func (x MemcacheDeleteResponse_DeleteStatusCode) Enum() *MemcacheDeleteResponse_DeleteStatusCode { + p := new(MemcacheDeleteResponse_DeleteStatusCode) + *p = x + return p +} +func (x MemcacheDeleteResponse_DeleteStatusCode) String() string { + return proto.EnumName(MemcacheDeleteResponse_DeleteStatusCode_name, int32(x)) +} +func (x *MemcacheDeleteResponse_DeleteStatusCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheDeleteResponse_DeleteStatusCode_value, data, "MemcacheDeleteResponse_DeleteStatusCode") + if err != nil { + return err + } + *x = MemcacheDeleteResponse_DeleteStatusCode(value) + return nil +} + +type MemcacheIncrementRequest_Direction int32 + +const ( + MemcacheIncrementRequest_INCREMENT MemcacheIncrementRequest_Direction = 1 + MemcacheIncrementRequest_DECREMENT MemcacheIncrementRequest_Direction = 2 +) + +var MemcacheIncrementRequest_Direction_name = map[int32]string{ + 1: "INCREMENT", + 2: "DECREMENT", +} +var MemcacheIncrementRequest_Direction_value = map[string]int32{ + "INCREMENT": 1, + "DECREMENT": 2, +} + +func (x MemcacheIncrementRequest_Direction) Enum() *MemcacheIncrementRequest_Direction { + p := new(MemcacheIncrementRequest_Direction) + *p = x + return p +} +func (x MemcacheIncrementRequest_Direction) String() string { + return proto.EnumName(MemcacheIncrementRequest_Direction_name, int32(x)) +} +func (x *MemcacheIncrementRequest_Direction) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheIncrementRequest_Direction_value, data, "MemcacheIncrementRequest_Direction") + if err != nil { + return err + } + *x = MemcacheIncrementRequest_Direction(value) + return nil +} + +type MemcacheIncrementResponse_IncrementStatusCode int32 + +const ( + MemcacheIncrementResponse_OK MemcacheIncrementResponse_IncrementStatusCode = 1 + MemcacheIncrementResponse_NOT_CHANGED MemcacheIncrementResponse_IncrementStatusCode = 2 + MemcacheIncrementResponse_ERROR MemcacheIncrementResponse_IncrementStatusCode = 3 +) + +var MemcacheIncrementResponse_IncrementStatusCode_name = map[int32]string{ + 1: "OK", + 2: "NOT_CHANGED", + 3: "ERROR", +} +var MemcacheIncrementResponse_IncrementStatusCode_value = map[string]int32{ + "OK": 1, + "NOT_CHANGED": 2, + "ERROR": 3, +} + +func (x MemcacheIncrementResponse_IncrementStatusCode) Enum() *MemcacheIncrementResponse_IncrementStatusCode { + p := new(MemcacheIncrementResponse_IncrementStatusCode) + *p = x + return p +} +func (x MemcacheIncrementResponse_IncrementStatusCode) String() string { + return proto.EnumName(MemcacheIncrementResponse_IncrementStatusCode_name, int32(x)) +} +func (x *MemcacheIncrementResponse_IncrementStatusCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MemcacheIncrementResponse_IncrementStatusCode_value, data, "MemcacheIncrementResponse_IncrementStatusCode") + if err != nil { + return err + } + *x = MemcacheIncrementResponse_IncrementStatusCode(value) + return nil +} + +type MemcacheServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheServiceError) Reset() { *m = MemcacheServiceError{} } +func (m *MemcacheServiceError) String() string { return proto.CompactTextString(m) } +func (*MemcacheServiceError) ProtoMessage() {} + +type AppOverride struct { + AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + NumMemcachegBackends *int32 `protobuf:"varint,2,opt,name=num_memcacheg_backends" json:"num_memcacheg_backends,omitempty"` + IgnoreShardlock *bool `protobuf:"varint,3,opt,name=ignore_shardlock" json:"ignore_shardlock,omitempty"` + MemcachePoolHint *string `protobuf:"bytes,4,opt,name=memcache_pool_hint" json:"memcache_pool_hint,omitempty"` + MemcacheShardingStrategy []byte `protobuf:"bytes,5,opt,name=memcache_sharding_strategy" json:"memcache_sharding_strategy,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AppOverride) Reset() { *m = AppOverride{} } +func (m *AppOverride) String() string { return proto.CompactTextString(m) } +func (*AppOverride) ProtoMessage() {} + +func (m *AppOverride) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *AppOverride) GetNumMemcachegBackends() int32 { + if m != nil && m.NumMemcachegBackends != nil { + return *m.NumMemcachegBackends + } + return 0 +} + +func (m *AppOverride) GetIgnoreShardlock() bool { + if m != nil && m.IgnoreShardlock != nil { + return *m.IgnoreShardlock + } + return false +} + +func (m *AppOverride) GetMemcachePoolHint() string { + if m != nil && m.MemcachePoolHint != nil { + return *m.MemcachePoolHint + } + return "" +} + +func (m *AppOverride) GetMemcacheShardingStrategy() []byte { + if m != nil { + return m.MemcacheShardingStrategy + } + return nil +} + +type MemcacheGetRequest struct { + Key [][]byte `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + NameSpace *string `protobuf:"bytes,2,opt,name=name_space,def=" json:"name_space,omitempty"` + ForCas *bool `protobuf:"varint,4,opt,name=for_cas" json:"for_cas,omitempty"` + Override *AppOverride `protobuf:"bytes,5,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGetRequest) Reset() { *m = MemcacheGetRequest{} } +func (m *MemcacheGetRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheGetRequest) ProtoMessage() {} + +func (m *MemcacheGetRequest) GetKey() [][]byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *MemcacheGetRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheGetRequest) GetForCas() bool { + if m != nil && m.ForCas != nil { + return *m.ForCas + } + return false +} + +func (m *MemcacheGetRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheGetResponse struct { + Item []*MemcacheGetResponse_Item `protobuf:"group,1,rep,name=Item" json:"item,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGetResponse) Reset() { *m = MemcacheGetResponse{} } +func (m *MemcacheGetResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheGetResponse) ProtoMessage() {} + +func (m *MemcacheGetResponse) GetItem() []*MemcacheGetResponse_Item { + if m != nil { + return m.Item + } + return nil +} + +type MemcacheGetResponse_Item struct { + Key []byte `protobuf:"bytes,2,req,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` + Flags *uint32 `protobuf:"fixed32,4,opt,name=flags" json:"flags,omitempty"` + CasId *uint64 `protobuf:"fixed64,5,opt,name=cas_id" json:"cas_id,omitempty"` + ExpiresInSeconds *int32 `protobuf:"varint,6,opt,name=expires_in_seconds" json:"expires_in_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGetResponse_Item) Reset() { *m = MemcacheGetResponse_Item{} } +func (m *MemcacheGetResponse_Item) String() string { return proto.CompactTextString(m) } +func (*MemcacheGetResponse_Item) ProtoMessage() {} + +func (m *MemcacheGetResponse_Item) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *MemcacheGetResponse_Item) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *MemcacheGetResponse_Item) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +func (m *MemcacheGetResponse_Item) GetCasId() uint64 { + if m != nil && m.CasId != nil { + return *m.CasId + } + return 0 +} + +func (m *MemcacheGetResponse_Item) GetExpiresInSeconds() int32 { + if m != nil && m.ExpiresInSeconds != nil { + return *m.ExpiresInSeconds + } + return 0 +} + +type MemcacheSetRequest struct { + Item []*MemcacheSetRequest_Item `protobuf:"group,1,rep,name=Item" json:"item,omitempty"` + NameSpace *string `protobuf:"bytes,7,opt,name=name_space,def=" json:"name_space,omitempty"` + Override *AppOverride `protobuf:"bytes,10,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheSetRequest) Reset() { *m = MemcacheSetRequest{} } +func (m *MemcacheSetRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheSetRequest) ProtoMessage() {} + +func (m *MemcacheSetRequest) GetItem() []*MemcacheSetRequest_Item { + if m != nil { + return m.Item + } + return nil +} + +func (m *MemcacheSetRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheSetRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheSetRequest_Item struct { + Key []byte `protobuf:"bytes,2,req,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` + Flags *uint32 `protobuf:"fixed32,4,opt,name=flags" json:"flags,omitempty"` + SetPolicy *MemcacheSetRequest_SetPolicy `protobuf:"varint,5,opt,name=set_policy,enum=appengine.MemcacheSetRequest_SetPolicy,def=1" json:"set_policy,omitempty"` + ExpirationTime *uint32 `protobuf:"fixed32,6,opt,name=expiration_time,def=0" json:"expiration_time,omitempty"` + CasId *uint64 `protobuf:"fixed64,8,opt,name=cas_id" json:"cas_id,omitempty"` + ForCas *bool `protobuf:"varint,9,opt,name=for_cas" json:"for_cas,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheSetRequest_Item) Reset() { *m = MemcacheSetRequest_Item{} } +func (m *MemcacheSetRequest_Item) String() string { return proto.CompactTextString(m) } +func (*MemcacheSetRequest_Item) ProtoMessage() {} + +const Default_MemcacheSetRequest_Item_SetPolicy MemcacheSetRequest_SetPolicy = MemcacheSetRequest_SET +const Default_MemcacheSetRequest_Item_ExpirationTime uint32 = 0 + +func (m *MemcacheSetRequest_Item) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *MemcacheSetRequest_Item) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *MemcacheSetRequest_Item) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +func (m *MemcacheSetRequest_Item) GetSetPolicy() MemcacheSetRequest_SetPolicy { + if m != nil && m.SetPolicy != nil { + return *m.SetPolicy + } + return Default_MemcacheSetRequest_Item_SetPolicy +} + +func (m *MemcacheSetRequest_Item) GetExpirationTime() uint32 { + if m != nil && m.ExpirationTime != nil { + return *m.ExpirationTime + } + return Default_MemcacheSetRequest_Item_ExpirationTime +} + +func (m *MemcacheSetRequest_Item) GetCasId() uint64 { + if m != nil && m.CasId != nil { + return *m.CasId + } + return 0 +} + +func (m *MemcacheSetRequest_Item) GetForCas() bool { + if m != nil && m.ForCas != nil { + return *m.ForCas + } + return false +} + +type MemcacheSetResponse struct { + SetStatus []MemcacheSetResponse_SetStatusCode `protobuf:"varint,1,rep,name=set_status,enum=appengine.MemcacheSetResponse_SetStatusCode" json:"set_status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheSetResponse) Reset() { *m = MemcacheSetResponse{} } +func (m *MemcacheSetResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheSetResponse) ProtoMessage() {} + +func (m *MemcacheSetResponse) GetSetStatus() []MemcacheSetResponse_SetStatusCode { + if m != nil { + return m.SetStatus + } + return nil +} + +type MemcacheDeleteRequest struct { + Item []*MemcacheDeleteRequest_Item `protobuf:"group,1,rep,name=Item" json:"item,omitempty"` + NameSpace *string `protobuf:"bytes,4,opt,name=name_space,def=" json:"name_space,omitempty"` + Override *AppOverride `protobuf:"bytes,5,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheDeleteRequest) Reset() { *m = MemcacheDeleteRequest{} } +func (m *MemcacheDeleteRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheDeleteRequest) ProtoMessage() {} + +func (m *MemcacheDeleteRequest) GetItem() []*MemcacheDeleteRequest_Item { + if m != nil { + return m.Item + } + return nil +} + +func (m *MemcacheDeleteRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheDeleteRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheDeleteRequest_Item struct { + Key []byte `protobuf:"bytes,2,req,name=key" json:"key,omitempty"` + DeleteTime *uint32 `protobuf:"fixed32,3,opt,name=delete_time,def=0" json:"delete_time,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheDeleteRequest_Item) Reset() { *m = MemcacheDeleteRequest_Item{} } +func (m *MemcacheDeleteRequest_Item) String() string { return proto.CompactTextString(m) } +func (*MemcacheDeleteRequest_Item) ProtoMessage() {} + +const Default_MemcacheDeleteRequest_Item_DeleteTime uint32 = 0 + +func (m *MemcacheDeleteRequest_Item) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *MemcacheDeleteRequest_Item) GetDeleteTime() uint32 { + if m != nil && m.DeleteTime != nil { + return *m.DeleteTime + } + return Default_MemcacheDeleteRequest_Item_DeleteTime +} + +type MemcacheDeleteResponse struct { + DeleteStatus []MemcacheDeleteResponse_DeleteStatusCode `protobuf:"varint,1,rep,name=delete_status,enum=appengine.MemcacheDeleteResponse_DeleteStatusCode" json:"delete_status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheDeleteResponse) Reset() { *m = MemcacheDeleteResponse{} } +func (m *MemcacheDeleteResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheDeleteResponse) ProtoMessage() {} + +func (m *MemcacheDeleteResponse) GetDeleteStatus() []MemcacheDeleteResponse_DeleteStatusCode { + if m != nil { + return m.DeleteStatus + } + return nil +} + +type MemcacheIncrementRequest struct { + Key []byte `protobuf:"bytes,1,req,name=key" json:"key,omitempty"` + NameSpace *string `protobuf:"bytes,4,opt,name=name_space,def=" json:"name_space,omitempty"` + Delta *uint64 `protobuf:"varint,2,opt,name=delta,def=1" json:"delta,omitempty"` + Direction *MemcacheIncrementRequest_Direction `protobuf:"varint,3,opt,name=direction,enum=appengine.MemcacheIncrementRequest_Direction,def=1" json:"direction,omitempty"` + InitialValue *uint64 `protobuf:"varint,5,opt,name=initial_value" json:"initial_value,omitempty"` + InitialFlags *uint32 `protobuf:"fixed32,6,opt,name=initial_flags" json:"initial_flags,omitempty"` + Override *AppOverride `protobuf:"bytes,7,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheIncrementRequest) Reset() { *m = MemcacheIncrementRequest{} } +func (m *MemcacheIncrementRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheIncrementRequest) ProtoMessage() {} + +const Default_MemcacheIncrementRequest_Delta uint64 = 1 +const Default_MemcacheIncrementRequest_Direction MemcacheIncrementRequest_Direction = MemcacheIncrementRequest_INCREMENT + +func (m *MemcacheIncrementRequest) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *MemcacheIncrementRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheIncrementRequest) GetDelta() uint64 { + if m != nil && m.Delta != nil { + return *m.Delta + } + return Default_MemcacheIncrementRequest_Delta +} + +func (m *MemcacheIncrementRequest) GetDirection() MemcacheIncrementRequest_Direction { + if m != nil && m.Direction != nil { + return *m.Direction + } + return Default_MemcacheIncrementRequest_Direction +} + +func (m *MemcacheIncrementRequest) GetInitialValue() uint64 { + if m != nil && m.InitialValue != nil { + return *m.InitialValue + } + return 0 +} + +func (m *MemcacheIncrementRequest) GetInitialFlags() uint32 { + if m != nil && m.InitialFlags != nil { + return *m.InitialFlags + } + return 0 +} + +func (m *MemcacheIncrementRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheIncrementResponse struct { + NewValue *uint64 `protobuf:"varint,1,opt,name=new_value" json:"new_value,omitempty"` + IncrementStatus *MemcacheIncrementResponse_IncrementStatusCode `protobuf:"varint,2,opt,name=increment_status,enum=appengine.MemcacheIncrementResponse_IncrementStatusCode" json:"increment_status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheIncrementResponse) Reset() { *m = MemcacheIncrementResponse{} } +func (m *MemcacheIncrementResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheIncrementResponse) ProtoMessage() {} + +func (m *MemcacheIncrementResponse) GetNewValue() uint64 { + if m != nil && m.NewValue != nil { + return *m.NewValue + } + return 0 +} + +func (m *MemcacheIncrementResponse) GetIncrementStatus() MemcacheIncrementResponse_IncrementStatusCode { + if m != nil && m.IncrementStatus != nil { + return *m.IncrementStatus + } + return MemcacheIncrementResponse_OK +} + +type MemcacheBatchIncrementRequest struct { + NameSpace *string `protobuf:"bytes,1,opt,name=name_space,def=" json:"name_space,omitempty"` + Item []*MemcacheIncrementRequest `protobuf:"bytes,2,rep,name=item" json:"item,omitempty"` + Override *AppOverride `protobuf:"bytes,3,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheBatchIncrementRequest) Reset() { *m = MemcacheBatchIncrementRequest{} } +func (m *MemcacheBatchIncrementRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheBatchIncrementRequest) ProtoMessage() {} + +func (m *MemcacheBatchIncrementRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheBatchIncrementRequest) GetItem() []*MemcacheIncrementRequest { + if m != nil { + return m.Item + } + return nil +} + +func (m *MemcacheBatchIncrementRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheBatchIncrementResponse struct { + Item []*MemcacheIncrementResponse `protobuf:"bytes,1,rep,name=item" json:"item,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheBatchIncrementResponse) Reset() { *m = MemcacheBatchIncrementResponse{} } +func (m *MemcacheBatchIncrementResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheBatchIncrementResponse) ProtoMessage() {} + +func (m *MemcacheBatchIncrementResponse) GetItem() []*MemcacheIncrementResponse { + if m != nil { + return m.Item + } + return nil +} + +type MemcacheFlushRequest struct { + Override *AppOverride `protobuf:"bytes,1,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheFlushRequest) Reset() { *m = MemcacheFlushRequest{} } +func (m *MemcacheFlushRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheFlushRequest) ProtoMessage() {} + +func (m *MemcacheFlushRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheFlushResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheFlushResponse) Reset() { *m = MemcacheFlushResponse{} } +func (m *MemcacheFlushResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheFlushResponse) ProtoMessage() {} + +type MemcacheStatsRequest struct { + Override *AppOverride `protobuf:"bytes,1,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheStatsRequest) Reset() { *m = MemcacheStatsRequest{} } +func (m *MemcacheStatsRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheStatsRequest) ProtoMessage() {} + +func (m *MemcacheStatsRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MergedNamespaceStats struct { + Hits *uint64 `protobuf:"varint,1,req,name=hits" json:"hits,omitempty"` + Misses *uint64 `protobuf:"varint,2,req,name=misses" json:"misses,omitempty"` + ByteHits *uint64 `protobuf:"varint,3,req,name=byte_hits" json:"byte_hits,omitempty"` + Items *uint64 `protobuf:"varint,4,req,name=items" json:"items,omitempty"` + Bytes *uint64 `protobuf:"varint,5,req,name=bytes" json:"bytes,omitempty"` + OldestItemAge *uint32 `protobuf:"fixed32,6,req,name=oldest_item_age" json:"oldest_item_age,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MergedNamespaceStats) Reset() { *m = MergedNamespaceStats{} } +func (m *MergedNamespaceStats) String() string { return proto.CompactTextString(m) } +func (*MergedNamespaceStats) ProtoMessage() {} + +func (m *MergedNamespaceStats) GetHits() uint64 { + if m != nil && m.Hits != nil { + return *m.Hits + } + return 0 +} + +func (m *MergedNamespaceStats) GetMisses() uint64 { + if m != nil && m.Misses != nil { + return *m.Misses + } + return 0 +} + +func (m *MergedNamespaceStats) GetByteHits() uint64 { + if m != nil && m.ByteHits != nil { + return *m.ByteHits + } + return 0 +} + +func (m *MergedNamespaceStats) GetItems() uint64 { + if m != nil && m.Items != nil { + return *m.Items + } + return 0 +} + +func (m *MergedNamespaceStats) GetBytes() uint64 { + if m != nil && m.Bytes != nil { + return *m.Bytes + } + return 0 +} + +func (m *MergedNamespaceStats) GetOldestItemAge() uint32 { + if m != nil && m.OldestItemAge != nil { + return *m.OldestItemAge + } + return 0 +} + +type MemcacheStatsResponse struct { + Stats *MergedNamespaceStats `protobuf:"bytes,1,opt,name=stats" json:"stats,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheStatsResponse) Reset() { *m = MemcacheStatsResponse{} } +func (m *MemcacheStatsResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheStatsResponse) ProtoMessage() {} + +func (m *MemcacheStatsResponse) GetStats() *MergedNamespaceStats { + if m != nil { + return m.Stats + } + return nil +} + +type MemcacheGrabTailRequest struct { + ItemCount *int32 `protobuf:"varint,1,req,name=item_count" json:"item_count,omitempty"` + NameSpace *string `protobuf:"bytes,2,opt,name=name_space,def=" json:"name_space,omitempty"` + Override *AppOverride `protobuf:"bytes,3,opt,name=override" json:"override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGrabTailRequest) Reset() { *m = MemcacheGrabTailRequest{} } +func (m *MemcacheGrabTailRequest) String() string { return proto.CompactTextString(m) } +func (*MemcacheGrabTailRequest) ProtoMessage() {} + +func (m *MemcacheGrabTailRequest) GetItemCount() int32 { + if m != nil && m.ItemCount != nil { + return *m.ItemCount + } + return 0 +} + +func (m *MemcacheGrabTailRequest) GetNameSpace() string { + if m != nil && m.NameSpace != nil { + return *m.NameSpace + } + return "" +} + +func (m *MemcacheGrabTailRequest) GetOverride() *AppOverride { + if m != nil { + return m.Override + } + return nil +} + +type MemcacheGrabTailResponse struct { + Item []*MemcacheGrabTailResponse_Item `protobuf:"group,1,rep,name=Item" json:"item,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGrabTailResponse) Reset() { *m = MemcacheGrabTailResponse{} } +func (m *MemcacheGrabTailResponse) String() string { return proto.CompactTextString(m) } +func (*MemcacheGrabTailResponse) ProtoMessage() {} + +func (m *MemcacheGrabTailResponse) GetItem() []*MemcacheGrabTailResponse_Item { + if m != nil { + return m.Item + } + return nil +} + +type MemcacheGrabTailResponse_Item struct { + Value []byte `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + Flags *uint32 `protobuf:"fixed32,3,opt,name=flags" json:"flags,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MemcacheGrabTailResponse_Item) Reset() { *m = MemcacheGrabTailResponse_Item{} } +func (m *MemcacheGrabTailResponse_Item) String() string { return proto.CompactTextString(m) } +func (*MemcacheGrabTailResponse_Item) ProtoMessage() {} + +func (m *MemcacheGrabTailResponse_Item) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *MemcacheGrabTailResponse_Item) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto b/vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto new file mode 100644 index 000000000..5f0edcdc7 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto @@ -0,0 +1,165 @@ +syntax = "proto2"; +option go_package = "memcache"; + +package appengine; + +message MemcacheServiceError { + enum ErrorCode { + OK = 0; + UNSPECIFIED_ERROR = 1; + NAMESPACE_NOT_SET = 2; + PERMISSION_DENIED = 3; + INVALID_VALUE = 6; + } +} + +message AppOverride { + required string app_id = 1; + + optional int32 num_memcacheg_backends = 2 [deprecated=true]; + optional bool ignore_shardlock = 3 [deprecated=true]; + optional string memcache_pool_hint = 4 [deprecated=true]; + optional bytes memcache_sharding_strategy = 5 [deprecated=true]; +} + +message MemcacheGetRequest { + repeated bytes key = 1; + optional string name_space = 2 [default = ""]; + optional bool for_cas = 4; + optional AppOverride override = 5; +} + +message MemcacheGetResponse { + repeated group Item = 1 { + required bytes key = 2; + required bytes value = 3; + optional fixed32 flags = 4; + optional fixed64 cas_id = 5; + optional int32 expires_in_seconds = 6; + } +} + +message MemcacheSetRequest { + enum SetPolicy { + SET = 1; + ADD = 2; + REPLACE = 3; + CAS = 4; + } + repeated group Item = 1 { + required bytes key = 2; + required bytes value = 3; + + optional fixed32 flags = 4; + optional SetPolicy set_policy = 5 [default = SET]; + optional fixed32 expiration_time = 6 [default = 0]; + + optional fixed64 cas_id = 8; + optional bool for_cas = 9; + } + optional string name_space = 7 [default = ""]; + optional AppOverride override = 10; +} + +message MemcacheSetResponse { + enum SetStatusCode { + STORED = 1; + NOT_STORED = 2; + ERROR = 3; + EXISTS = 4; + } + repeated SetStatusCode set_status = 1; +} + +message MemcacheDeleteRequest { + repeated group Item = 1 { + required bytes key = 2; + optional fixed32 delete_time = 3 [default = 0]; + } + optional string name_space = 4 [default = ""]; + optional AppOverride override = 5; +} + +message MemcacheDeleteResponse { + enum DeleteStatusCode { + DELETED = 1; + NOT_FOUND = 2; + } + repeated DeleteStatusCode delete_status = 1; +} + +message MemcacheIncrementRequest { + enum Direction { + INCREMENT = 1; + DECREMENT = 2; + } + required bytes key = 1; + optional string name_space = 4 [default = ""]; + + optional uint64 delta = 2 [default = 1]; + optional Direction direction = 3 [default = INCREMENT]; + + optional uint64 initial_value = 5; + optional fixed32 initial_flags = 6; + optional AppOverride override = 7; +} + +message MemcacheIncrementResponse { + enum IncrementStatusCode { + OK = 1; + NOT_CHANGED = 2; + ERROR = 3; + } + + optional uint64 new_value = 1; + optional IncrementStatusCode increment_status = 2; +} + +message MemcacheBatchIncrementRequest { + optional string name_space = 1 [default = ""]; + repeated MemcacheIncrementRequest item = 2; + optional AppOverride override = 3; +} + +message MemcacheBatchIncrementResponse { + repeated MemcacheIncrementResponse item = 1; +} + +message MemcacheFlushRequest { + optional AppOverride override = 1; +} + +message MemcacheFlushResponse { +} + +message MemcacheStatsRequest { + optional AppOverride override = 1; +} + +message MergedNamespaceStats { + required uint64 hits = 1; + required uint64 misses = 2; + required uint64 byte_hits = 3; + + required uint64 items = 4; + required uint64 bytes = 5; + + required fixed32 oldest_item_age = 6; +} + +message MemcacheStatsResponse { + optional MergedNamespaceStats stats = 1; +} + +message MemcacheGrabTailRequest { + required int32 item_count = 1; + optional string name_space = 2 [default = ""]; + optional AppOverride override = 3; +} + +message MemcacheGrabTailResponse { + repeated group Item = 1 { + required bytes value = 2; + optional fixed32 flags = 3; + } +} diff --git a/vendor/google.golang.org/appengine/internal/metadata.go b/vendor/google.golang.org/appengine/internal/metadata.go new file mode 100644 index 000000000..b68fb7536 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/metadata.go @@ -0,0 +1,61 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +// This file has code for accessing metadata. +// +// References: +// https://cloud.google.com/compute/docs/metadata + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "net/url" +) + +const ( + metadataHost = "metadata" + metadataPath = "/computeMetadata/v1/" +) + +var ( + metadataRequestHeaders = http.Header{ + "X-Google-Metadata-Request": []string{"True"}, + } +) + +// TODO(dsymonds): Do we need to support default values, like Python? +func mustGetMetadata(key string) []byte { + b, err := getMetadata(key) + if err != nil { + log.Fatalf("Metadata fetch failed: %v", err) + } + return b +} + +func getMetadata(key string) ([]byte, error) { + // TODO(dsymonds): May need to use url.Parse to support keys with query args. + req := &http.Request{ + Method: "GET", + URL: &url.URL{ + Scheme: "http", + Host: metadataHost, + Path: metadataPath + key, + }, + Header: metadataRequestHeaders, + Host: metadataHost, + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return nil, fmt.Errorf("metadata server returned HTTP %d", resp.StatusCode) + } + return ioutil.ReadAll(resp.Body) +} diff --git a/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go b/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go new file mode 100644 index 000000000..a0145ed31 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go @@ -0,0 +1,375 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/modules/modules_service.proto +// DO NOT EDIT! + +/* +Package modules is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/modules/modules_service.proto + +It has these top-level messages: + ModulesServiceError + GetModulesRequest + GetModulesResponse + GetVersionsRequest + GetVersionsResponse + GetDefaultVersionRequest + GetDefaultVersionResponse + GetNumInstancesRequest + GetNumInstancesResponse + SetNumInstancesRequest + SetNumInstancesResponse + StartModuleRequest + StartModuleResponse + StopModuleRequest + StopModuleResponse + GetHostnameRequest + GetHostnameResponse +*/ +package modules + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type ModulesServiceError_ErrorCode int32 + +const ( + ModulesServiceError_OK ModulesServiceError_ErrorCode = 0 + ModulesServiceError_INVALID_MODULE ModulesServiceError_ErrorCode = 1 + ModulesServiceError_INVALID_VERSION ModulesServiceError_ErrorCode = 2 + ModulesServiceError_INVALID_INSTANCES ModulesServiceError_ErrorCode = 3 + ModulesServiceError_TRANSIENT_ERROR ModulesServiceError_ErrorCode = 4 + ModulesServiceError_UNEXPECTED_STATE ModulesServiceError_ErrorCode = 5 +) + +var ModulesServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INVALID_MODULE", + 2: "INVALID_VERSION", + 3: "INVALID_INSTANCES", + 4: "TRANSIENT_ERROR", + 5: "UNEXPECTED_STATE", +} +var ModulesServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INVALID_MODULE": 1, + "INVALID_VERSION": 2, + "INVALID_INSTANCES": 3, + "TRANSIENT_ERROR": 4, + "UNEXPECTED_STATE": 5, +} + +func (x ModulesServiceError_ErrorCode) Enum() *ModulesServiceError_ErrorCode { + p := new(ModulesServiceError_ErrorCode) + *p = x + return p +} +func (x ModulesServiceError_ErrorCode) String() string { + return proto.EnumName(ModulesServiceError_ErrorCode_name, int32(x)) +} +func (x *ModulesServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ModulesServiceError_ErrorCode_value, data, "ModulesServiceError_ErrorCode") + if err != nil { + return err + } + *x = ModulesServiceError_ErrorCode(value) + return nil +} + +type ModulesServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ModulesServiceError) Reset() { *m = ModulesServiceError{} } +func (m *ModulesServiceError) String() string { return proto.CompactTextString(m) } +func (*ModulesServiceError) ProtoMessage() {} + +type GetModulesRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetModulesRequest) Reset() { *m = GetModulesRequest{} } +func (m *GetModulesRequest) String() string { return proto.CompactTextString(m) } +func (*GetModulesRequest) ProtoMessage() {} + +type GetModulesResponse struct { + Module []string `protobuf:"bytes,1,rep,name=module" json:"module,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetModulesResponse) Reset() { *m = GetModulesResponse{} } +func (m *GetModulesResponse) String() string { return proto.CompactTextString(m) } +func (*GetModulesResponse) ProtoMessage() {} + +func (m *GetModulesResponse) GetModule() []string { + if m != nil { + return m.Module + } + return nil +} + +type GetVersionsRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetVersionsRequest) Reset() { *m = GetVersionsRequest{} } +func (m *GetVersionsRequest) String() string { return proto.CompactTextString(m) } +func (*GetVersionsRequest) ProtoMessage() {} + +func (m *GetVersionsRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +type GetVersionsResponse struct { + Version []string `protobuf:"bytes,1,rep,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetVersionsResponse) Reset() { *m = GetVersionsResponse{} } +func (m *GetVersionsResponse) String() string { return proto.CompactTextString(m) } +func (*GetVersionsResponse) ProtoMessage() {} + +func (m *GetVersionsResponse) GetVersion() []string { + if m != nil { + return m.Version + } + return nil +} + +type GetDefaultVersionRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetDefaultVersionRequest) Reset() { *m = GetDefaultVersionRequest{} } +func (m *GetDefaultVersionRequest) String() string { return proto.CompactTextString(m) } +func (*GetDefaultVersionRequest) ProtoMessage() {} + +func (m *GetDefaultVersionRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +type GetDefaultVersionResponse struct { + Version *string `protobuf:"bytes,1,req,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetDefaultVersionResponse) Reset() { *m = GetDefaultVersionResponse{} } +func (m *GetDefaultVersionResponse) String() string { return proto.CompactTextString(m) } +func (*GetDefaultVersionResponse) ProtoMessage() {} + +func (m *GetDefaultVersionResponse) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +type GetNumInstancesRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetNumInstancesRequest) Reset() { *m = GetNumInstancesRequest{} } +func (m *GetNumInstancesRequest) String() string { return proto.CompactTextString(m) } +func (*GetNumInstancesRequest) ProtoMessage() {} + +func (m *GetNumInstancesRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +func (m *GetNumInstancesRequest) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +type GetNumInstancesResponse struct { + Instances *int64 `protobuf:"varint,1,req,name=instances" json:"instances,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetNumInstancesResponse) Reset() { *m = GetNumInstancesResponse{} } +func (m *GetNumInstancesResponse) String() string { return proto.CompactTextString(m) } +func (*GetNumInstancesResponse) ProtoMessage() {} + +func (m *GetNumInstancesResponse) GetInstances() int64 { + if m != nil && m.Instances != nil { + return *m.Instances + } + return 0 +} + +type SetNumInstancesRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` + Instances *int64 `protobuf:"varint,3,req,name=instances" json:"instances,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetNumInstancesRequest) Reset() { *m = SetNumInstancesRequest{} } +func (m *SetNumInstancesRequest) String() string { return proto.CompactTextString(m) } +func (*SetNumInstancesRequest) ProtoMessage() {} + +func (m *SetNumInstancesRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +func (m *SetNumInstancesRequest) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +func (m *SetNumInstancesRequest) GetInstances() int64 { + if m != nil && m.Instances != nil { + return *m.Instances + } + return 0 +} + +type SetNumInstancesResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetNumInstancesResponse) Reset() { *m = SetNumInstancesResponse{} } +func (m *SetNumInstancesResponse) String() string { return proto.CompactTextString(m) } +func (*SetNumInstancesResponse) ProtoMessage() {} + +type StartModuleRequest struct { + Module *string `protobuf:"bytes,1,req,name=module" json:"module,omitempty"` + Version *string `protobuf:"bytes,2,req,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StartModuleRequest) Reset() { *m = StartModuleRequest{} } +func (m *StartModuleRequest) String() string { return proto.CompactTextString(m) } +func (*StartModuleRequest) ProtoMessage() {} + +func (m *StartModuleRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +func (m *StartModuleRequest) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +type StartModuleResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *StartModuleResponse) Reset() { *m = StartModuleResponse{} } +func (m *StartModuleResponse) String() string { return proto.CompactTextString(m) } +func (*StartModuleResponse) ProtoMessage() {} + +type StopModuleRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StopModuleRequest) Reset() { *m = StopModuleRequest{} } +func (m *StopModuleRequest) String() string { return proto.CompactTextString(m) } +func (*StopModuleRequest) ProtoMessage() {} + +func (m *StopModuleRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +func (m *StopModuleRequest) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +type StopModuleResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *StopModuleResponse) Reset() { *m = StopModuleResponse{} } +func (m *StopModuleResponse) String() string { return proto.CompactTextString(m) } +func (*StopModuleResponse) ProtoMessage() {} + +type GetHostnameRequest struct { + Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"` + Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` + Instance *string `protobuf:"bytes,3,opt,name=instance" json:"instance,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetHostnameRequest) Reset() { *m = GetHostnameRequest{} } +func (m *GetHostnameRequest) String() string { return proto.CompactTextString(m) } +func (*GetHostnameRequest) ProtoMessage() {} + +func (m *GetHostnameRequest) GetModule() string { + if m != nil && m.Module != nil { + return *m.Module + } + return "" +} + +func (m *GetHostnameRequest) GetVersion() string { + if m != nil && m.Version != nil { + return *m.Version + } + return "" +} + +func (m *GetHostnameRequest) GetInstance() string { + if m != nil && m.Instance != nil { + return *m.Instance + } + return "" +} + +type GetHostnameResponse struct { + Hostname *string `protobuf:"bytes,1,req,name=hostname" json:"hostname,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetHostnameResponse) Reset() { *m = GetHostnameResponse{} } +func (m *GetHostnameResponse) String() string { return proto.CompactTextString(m) } +func (*GetHostnameResponse) ProtoMessage() {} + +func (m *GetHostnameResponse) GetHostname() string { + if m != nil && m.Hostname != nil { + return *m.Hostname + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/modules/modules_service.proto b/vendor/google.golang.org/appengine/internal/modules/modules_service.proto new file mode 100644 index 000000000..d29f0065a --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/modules/modules_service.proto @@ -0,0 +1,80 @@ +syntax = "proto2"; +option go_package = "modules"; + +package appengine; + +message ModulesServiceError { + enum ErrorCode { + OK = 0; + INVALID_MODULE = 1; + INVALID_VERSION = 2; + INVALID_INSTANCES = 3; + TRANSIENT_ERROR = 4; + UNEXPECTED_STATE = 5; + } +} + +message GetModulesRequest { +} + +message GetModulesResponse { + repeated string module = 1; +} + +message GetVersionsRequest { + optional string module = 1; +} + +message GetVersionsResponse { + repeated string version = 1; +} + +message GetDefaultVersionRequest { + optional string module = 1; +} + +message GetDefaultVersionResponse { + required string version = 1; +} + +message GetNumInstancesRequest { + optional string module = 1; + optional string version = 2; +} + +message GetNumInstancesResponse { + required int64 instances = 1; +} + +message SetNumInstancesRequest { + optional string module = 1; + optional string version = 2; + required int64 instances = 3; +} + +message SetNumInstancesResponse {} + +message StartModuleRequest { + required string module = 1; + required string version = 2; +} + +message StartModuleResponse {} + +message StopModuleRequest { + optional string module = 1; + optional string version = 2; +} + +message StopModuleResponse {} + +message GetHostnameRequest { + optional string module = 1; + optional string version = 2; + optional string instance = 3; +} + +message GetHostnameResponse { + required string hostname = 1; +} + diff --git a/vendor/google.golang.org/appengine/internal/net.go b/vendor/google.golang.org/appengine/internal/net.go new file mode 100644 index 000000000..3b94cf0c6 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/net.go @@ -0,0 +1,56 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +// This file implements a network dialer that limits the number of concurrent connections. +// It is only used for API calls. + +import ( + "log" + "net" + "runtime" + "sync" + "time" +) + +var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable. + +func limitRelease() { + // non-blocking + select { + case <-limitSem: + default: + // This should not normally happen. + log.Print("appengine: unbalanced limitSem release!") + } +} + +func limitDial(network, addr string) (net.Conn, error) { + limitSem <- 1 + + // Dial with a timeout in case the API host is MIA. + // The connection should normally be very fast. + conn, err := net.DialTimeout(network, addr, 500*time.Millisecond) + if err != nil { + limitRelease() + return nil, err + } + lc := &limitConn{Conn: conn} + runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required + return lc, nil +} + +type limitConn struct { + close sync.Once + net.Conn +} + +func (lc *limitConn) Close() error { + defer lc.close.Do(func() { + limitRelease() + runtime.SetFinalizer(lc, nil) + }) + return lc.Conn.Close() +} diff --git a/vendor/google.golang.org/appengine/internal/regen.sh b/vendor/google.golang.org/appengine/internal/regen.sh new file mode 100644 index 000000000..2fdb546a6 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/regen.sh @@ -0,0 +1,40 @@ +#!/bin/bash -e +# +# This script rebuilds the generated code for the protocol buffers. +# To run this you will need protoc and goprotobuf installed; +# see https://github.com/golang/protobuf for instructions. + +PKG=google.golang.org/appengine + +function die() { + echo 1>&2 $* + exit 1 +} + +# Sanity check that the right tools are accessible. +for tool in go protoc protoc-gen-go; do + q=$(which $tool) || die "didn't find $tool" + echo 1>&2 "$tool: $q" +done + +echo -n 1>&2 "finding package dir... " +pkgdir=$(go list -f '{{.Dir}}' $PKG) +echo 1>&2 $pkgdir +base=$(echo $pkgdir | sed "s,/$PKG\$,,") +echo 1>&2 "base: $base" +cd $base + +# Run protoc once per package. +for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do + echo 1>&2 "* $dir" + protoc --go_out=. $dir/*.proto +done + +for f in $(find $PKG/internal -name '*.pb.go'); do + # Remove proto.RegisterEnum calls. + # These cause duplicate registration panics when these packages + # are used on classic App Engine. proto.RegisterEnum only affects + # parsing the text format; we don't care about that. + # https://code.google.com/p/googleappengine/issues/detail?id=11670#c17 + sed -i '/proto.RegisterEnum/d' $f +done diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go new file mode 100644 index 000000000..526bd39e6 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go @@ -0,0 +1,231 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/remote_api/remote_api.proto +// DO NOT EDIT! + +/* +Package remote_api is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/remote_api/remote_api.proto + +It has these top-level messages: + Request + ApplicationError + RpcError + Response +*/ +package remote_api + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type RpcError_ErrorCode int32 + +const ( + RpcError_UNKNOWN RpcError_ErrorCode = 0 + RpcError_CALL_NOT_FOUND RpcError_ErrorCode = 1 + RpcError_PARSE_ERROR RpcError_ErrorCode = 2 + RpcError_SECURITY_VIOLATION RpcError_ErrorCode = 3 + RpcError_OVER_QUOTA RpcError_ErrorCode = 4 + RpcError_REQUEST_TOO_LARGE RpcError_ErrorCode = 5 + RpcError_CAPABILITY_DISABLED RpcError_ErrorCode = 6 + RpcError_FEATURE_DISABLED RpcError_ErrorCode = 7 + RpcError_BAD_REQUEST RpcError_ErrorCode = 8 + RpcError_RESPONSE_TOO_LARGE RpcError_ErrorCode = 9 + RpcError_CANCELLED RpcError_ErrorCode = 10 + RpcError_REPLAY_ERROR RpcError_ErrorCode = 11 + RpcError_DEADLINE_EXCEEDED RpcError_ErrorCode = 12 +) + +var RpcError_ErrorCode_name = map[int32]string{ + 0: "UNKNOWN", + 1: "CALL_NOT_FOUND", + 2: "PARSE_ERROR", + 3: "SECURITY_VIOLATION", + 4: "OVER_QUOTA", + 5: "REQUEST_TOO_LARGE", + 6: "CAPABILITY_DISABLED", + 7: "FEATURE_DISABLED", + 8: "BAD_REQUEST", + 9: "RESPONSE_TOO_LARGE", + 10: "CANCELLED", + 11: "REPLAY_ERROR", + 12: "DEADLINE_EXCEEDED", +} +var RpcError_ErrorCode_value = map[string]int32{ + "UNKNOWN": 0, + "CALL_NOT_FOUND": 1, + "PARSE_ERROR": 2, + "SECURITY_VIOLATION": 3, + "OVER_QUOTA": 4, + "REQUEST_TOO_LARGE": 5, + "CAPABILITY_DISABLED": 6, + "FEATURE_DISABLED": 7, + "BAD_REQUEST": 8, + "RESPONSE_TOO_LARGE": 9, + "CANCELLED": 10, + "REPLAY_ERROR": 11, + "DEADLINE_EXCEEDED": 12, +} + +func (x RpcError_ErrorCode) Enum() *RpcError_ErrorCode { + p := new(RpcError_ErrorCode) + *p = x + return p +} +func (x RpcError_ErrorCode) String() string { + return proto.EnumName(RpcError_ErrorCode_name, int32(x)) +} +func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RpcError_ErrorCode_value, data, "RpcError_ErrorCode") + if err != nil { + return err + } + *x = RpcError_ErrorCode(value) + return nil +} + +type Request struct { + ServiceName *string `protobuf:"bytes,2,req,name=service_name" json:"service_name,omitempty"` + Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"` + Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"` + RequestId *string `protobuf:"bytes,5,opt,name=request_id" json:"request_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} + +func (m *Request) GetServiceName() string { + if m != nil && m.ServiceName != nil { + return *m.ServiceName + } + return "" +} + +func (m *Request) GetMethod() string { + if m != nil && m.Method != nil { + return *m.Method + } + return "" +} + +func (m *Request) GetRequest() []byte { + if m != nil { + return m.Request + } + return nil +} + +func (m *Request) GetRequestId() string { + if m != nil && m.RequestId != nil { + return *m.RequestId + } + return "" +} + +type ApplicationError struct { + Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"` + Detail *string `protobuf:"bytes,2,req,name=detail" json:"detail,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ApplicationError) Reset() { *m = ApplicationError{} } +func (m *ApplicationError) String() string { return proto.CompactTextString(m) } +func (*ApplicationError) ProtoMessage() {} + +func (m *ApplicationError) GetCode() int32 { + if m != nil && m.Code != nil { + return *m.Code + } + return 0 +} + +func (m *ApplicationError) GetDetail() string { + if m != nil && m.Detail != nil { + return *m.Detail + } + return "" +} + +type RpcError struct { + Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"` + Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RpcError) Reset() { *m = RpcError{} } +func (m *RpcError) String() string { return proto.CompactTextString(m) } +func (*RpcError) ProtoMessage() {} + +func (m *RpcError) GetCode() int32 { + if m != nil && m.Code != nil { + return *m.Code + } + return 0 +} + +func (m *RpcError) GetDetail() string { + if m != nil && m.Detail != nil { + return *m.Detail + } + return "" +} + +type Response struct { + Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"` + Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"` + ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error" json:"application_error,omitempty"` + JavaException []byte `protobuf:"bytes,4,opt,name=java_exception" json:"java_exception,omitempty"` + RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error" json:"rpc_error,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} + +func (m *Response) GetResponse() []byte { + if m != nil { + return m.Response + } + return nil +} + +func (m *Response) GetException() []byte { + if m != nil { + return m.Exception + } + return nil +} + +func (m *Response) GetApplicationError() *ApplicationError { + if m != nil { + return m.ApplicationError + } + return nil +} + +func (m *Response) GetJavaException() []byte { + if m != nil { + return m.JavaException + } + return nil +} + +func (m *Response) GetRpcError() *RpcError { + if m != nil { + return m.RpcError + } + return nil +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto new file mode 100644 index 000000000..f21763a4e --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto @@ -0,0 +1,44 @@ +syntax = "proto2"; +option go_package = "remote_api"; + +package remote_api; + +message Request { + required string service_name = 2; + required string method = 3; + required bytes request = 4; + optional string request_id = 5; +} + +message ApplicationError { + required int32 code = 1; + required string detail = 2; +} + +message RpcError { + enum ErrorCode { + UNKNOWN = 0; + CALL_NOT_FOUND = 1; + PARSE_ERROR = 2; + SECURITY_VIOLATION = 3; + OVER_QUOTA = 4; + REQUEST_TOO_LARGE = 5; + CAPABILITY_DISABLED = 6; + FEATURE_DISABLED = 7; + BAD_REQUEST = 8; + RESPONSE_TOO_LARGE = 9; + CANCELLED = 10; + REPLAY_ERROR = 11; + DEADLINE_EXCEEDED = 12; + } + required int32 code = 1; + optional string detail = 2; +} + +message Response { + optional bytes response = 1; + optional bytes exception = 2; + optional ApplicationError application_error = 3; + optional bytes java_exception = 4; + optional RpcError rpc_error = 5; +} diff --git a/vendor/google.golang.org/appengine/internal/search/search.pb.go b/vendor/google.golang.org/appengine/internal/search/search.pb.go new file mode 100644 index 000000000..7d8d11ddc --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/search/search.pb.go @@ -0,0 +1,2127 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/search/search.proto +// DO NOT EDIT! + +/* +Package search is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/search/search.proto + +It has these top-level messages: + Scope + Entry + AccessControlList + FieldValue + Field + FieldTypes + IndexShardSettings + FacetValue + Facet + DocumentMetadata + Document + SearchServiceError + RequestStatus + IndexSpec + IndexMetadata + IndexDocumentParams + IndexDocumentRequest + IndexDocumentResponse + DeleteDocumentParams + DeleteDocumentRequest + DeleteDocumentResponse + ListDocumentsParams + ListDocumentsRequest + ListDocumentsResponse + ListIndexesParams + ListIndexesRequest + ListIndexesResponse + DeleteSchemaParams + DeleteSchemaRequest + DeleteSchemaResponse + SortSpec + ScorerSpec + FieldSpec + FacetRange + FacetRequestParam + FacetAutoDetectParam + FacetRequest + FacetRefinement + SearchParams + SearchRequest + FacetResultValue + FacetResult + SearchResult + SearchResponse +*/ +package search + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Scope_Type int32 + +const ( + Scope_USER_BY_CANONICAL_ID Scope_Type = 1 + Scope_USER_BY_EMAIL Scope_Type = 2 + Scope_GROUP_BY_CANONICAL_ID Scope_Type = 3 + Scope_GROUP_BY_EMAIL Scope_Type = 4 + Scope_GROUP_BY_DOMAIN Scope_Type = 5 + Scope_ALL_USERS Scope_Type = 6 + Scope_ALL_AUTHENTICATED_USERS Scope_Type = 7 +) + +var Scope_Type_name = map[int32]string{ + 1: "USER_BY_CANONICAL_ID", + 2: "USER_BY_EMAIL", + 3: "GROUP_BY_CANONICAL_ID", + 4: "GROUP_BY_EMAIL", + 5: "GROUP_BY_DOMAIN", + 6: "ALL_USERS", + 7: "ALL_AUTHENTICATED_USERS", +} +var Scope_Type_value = map[string]int32{ + "USER_BY_CANONICAL_ID": 1, + "USER_BY_EMAIL": 2, + "GROUP_BY_CANONICAL_ID": 3, + "GROUP_BY_EMAIL": 4, + "GROUP_BY_DOMAIN": 5, + "ALL_USERS": 6, + "ALL_AUTHENTICATED_USERS": 7, +} + +func (x Scope_Type) Enum() *Scope_Type { + p := new(Scope_Type) + *p = x + return p +} +func (x Scope_Type) String() string { + return proto.EnumName(Scope_Type_name, int32(x)) +} +func (x *Scope_Type) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Scope_Type_value, data, "Scope_Type") + if err != nil { + return err + } + *x = Scope_Type(value) + return nil +} + +type Entry_Permission int32 + +const ( + Entry_READ Entry_Permission = 1 + Entry_WRITE Entry_Permission = 2 + Entry_FULL_CONTROL Entry_Permission = 3 +) + +var Entry_Permission_name = map[int32]string{ + 1: "READ", + 2: "WRITE", + 3: "FULL_CONTROL", +} +var Entry_Permission_value = map[string]int32{ + "READ": 1, + "WRITE": 2, + "FULL_CONTROL": 3, +} + +func (x Entry_Permission) Enum() *Entry_Permission { + p := new(Entry_Permission) + *p = x + return p +} +func (x Entry_Permission) String() string { + return proto.EnumName(Entry_Permission_name, int32(x)) +} +func (x *Entry_Permission) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Entry_Permission_value, data, "Entry_Permission") + if err != nil { + return err + } + *x = Entry_Permission(value) + return nil +} + +type FieldValue_ContentType int32 + +const ( + FieldValue_TEXT FieldValue_ContentType = 0 + FieldValue_HTML FieldValue_ContentType = 1 + FieldValue_ATOM FieldValue_ContentType = 2 + FieldValue_DATE FieldValue_ContentType = 3 + FieldValue_NUMBER FieldValue_ContentType = 4 + FieldValue_GEO FieldValue_ContentType = 5 +) + +var FieldValue_ContentType_name = map[int32]string{ + 0: "TEXT", + 1: "HTML", + 2: "ATOM", + 3: "DATE", + 4: "NUMBER", + 5: "GEO", +} +var FieldValue_ContentType_value = map[string]int32{ + "TEXT": 0, + "HTML": 1, + "ATOM": 2, + "DATE": 3, + "NUMBER": 4, + "GEO": 5, +} + +func (x FieldValue_ContentType) Enum() *FieldValue_ContentType { + p := new(FieldValue_ContentType) + *p = x + return p +} +func (x FieldValue_ContentType) String() string { + return proto.EnumName(FieldValue_ContentType_name, int32(x)) +} +func (x *FieldValue_ContentType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldValue_ContentType_value, data, "FieldValue_ContentType") + if err != nil { + return err + } + *x = FieldValue_ContentType(value) + return nil +} + +type FacetValue_ContentType int32 + +const ( + FacetValue_ATOM FacetValue_ContentType = 2 + FacetValue_NUMBER FacetValue_ContentType = 4 +) + +var FacetValue_ContentType_name = map[int32]string{ + 2: "ATOM", + 4: "NUMBER", +} +var FacetValue_ContentType_value = map[string]int32{ + "ATOM": 2, + "NUMBER": 4, +} + +func (x FacetValue_ContentType) Enum() *FacetValue_ContentType { + p := new(FacetValue_ContentType) + *p = x + return p +} +func (x FacetValue_ContentType) String() string { + return proto.EnumName(FacetValue_ContentType_name, int32(x)) +} +func (x *FacetValue_ContentType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FacetValue_ContentType_value, data, "FacetValue_ContentType") + if err != nil { + return err + } + *x = FacetValue_ContentType(value) + return nil +} + +type Document_Storage int32 + +const ( + Document_DISK Document_Storage = 0 +) + +var Document_Storage_name = map[int32]string{ + 0: "DISK", +} +var Document_Storage_value = map[string]int32{ + "DISK": 0, +} + +func (x Document_Storage) Enum() *Document_Storage { + p := new(Document_Storage) + *p = x + return p +} +func (x Document_Storage) String() string { + return proto.EnumName(Document_Storage_name, int32(x)) +} +func (x *Document_Storage) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Document_Storage_value, data, "Document_Storage") + if err != nil { + return err + } + *x = Document_Storage(value) + return nil +} + +type SearchServiceError_ErrorCode int32 + +const ( + SearchServiceError_OK SearchServiceError_ErrorCode = 0 + SearchServiceError_INVALID_REQUEST SearchServiceError_ErrorCode = 1 + SearchServiceError_TRANSIENT_ERROR SearchServiceError_ErrorCode = 2 + SearchServiceError_INTERNAL_ERROR SearchServiceError_ErrorCode = 3 + SearchServiceError_PERMISSION_DENIED SearchServiceError_ErrorCode = 4 + SearchServiceError_TIMEOUT SearchServiceError_ErrorCode = 5 + SearchServiceError_CONCURRENT_TRANSACTION SearchServiceError_ErrorCode = 6 +) + +var SearchServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INVALID_REQUEST", + 2: "TRANSIENT_ERROR", + 3: "INTERNAL_ERROR", + 4: "PERMISSION_DENIED", + 5: "TIMEOUT", + 6: "CONCURRENT_TRANSACTION", +} +var SearchServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INVALID_REQUEST": 1, + "TRANSIENT_ERROR": 2, + "INTERNAL_ERROR": 3, + "PERMISSION_DENIED": 4, + "TIMEOUT": 5, + "CONCURRENT_TRANSACTION": 6, +} + +func (x SearchServiceError_ErrorCode) Enum() *SearchServiceError_ErrorCode { + p := new(SearchServiceError_ErrorCode) + *p = x + return p +} +func (x SearchServiceError_ErrorCode) String() string { + return proto.EnumName(SearchServiceError_ErrorCode_name, int32(x)) +} +func (x *SearchServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SearchServiceError_ErrorCode_value, data, "SearchServiceError_ErrorCode") + if err != nil { + return err + } + *x = SearchServiceError_ErrorCode(value) + return nil +} + +type IndexSpec_Consistency int32 + +const ( + IndexSpec_GLOBAL IndexSpec_Consistency = 0 + IndexSpec_PER_DOCUMENT IndexSpec_Consistency = 1 +) + +var IndexSpec_Consistency_name = map[int32]string{ + 0: "GLOBAL", + 1: "PER_DOCUMENT", +} +var IndexSpec_Consistency_value = map[string]int32{ + "GLOBAL": 0, + "PER_DOCUMENT": 1, +} + +func (x IndexSpec_Consistency) Enum() *IndexSpec_Consistency { + p := new(IndexSpec_Consistency) + *p = x + return p +} +func (x IndexSpec_Consistency) String() string { + return proto.EnumName(IndexSpec_Consistency_name, int32(x)) +} +func (x *IndexSpec_Consistency) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(IndexSpec_Consistency_value, data, "IndexSpec_Consistency") + if err != nil { + return err + } + *x = IndexSpec_Consistency(value) + return nil +} + +type IndexSpec_Source int32 + +const ( + IndexSpec_SEARCH IndexSpec_Source = 0 + IndexSpec_DATASTORE IndexSpec_Source = 1 + IndexSpec_CLOUD_STORAGE IndexSpec_Source = 2 +) + +var IndexSpec_Source_name = map[int32]string{ + 0: "SEARCH", + 1: "DATASTORE", + 2: "CLOUD_STORAGE", +} +var IndexSpec_Source_value = map[string]int32{ + "SEARCH": 0, + "DATASTORE": 1, + "CLOUD_STORAGE": 2, +} + +func (x IndexSpec_Source) Enum() *IndexSpec_Source { + p := new(IndexSpec_Source) + *p = x + return p +} +func (x IndexSpec_Source) String() string { + return proto.EnumName(IndexSpec_Source_name, int32(x)) +} +func (x *IndexSpec_Source) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(IndexSpec_Source_value, data, "IndexSpec_Source") + if err != nil { + return err + } + *x = IndexSpec_Source(value) + return nil +} + +type IndexSpec_Mode int32 + +const ( + IndexSpec_PRIORITY IndexSpec_Mode = 0 + IndexSpec_BACKGROUND IndexSpec_Mode = 1 +) + +var IndexSpec_Mode_name = map[int32]string{ + 0: "PRIORITY", + 1: "BACKGROUND", +} +var IndexSpec_Mode_value = map[string]int32{ + "PRIORITY": 0, + "BACKGROUND": 1, +} + +func (x IndexSpec_Mode) Enum() *IndexSpec_Mode { + p := new(IndexSpec_Mode) + *p = x + return p +} +func (x IndexSpec_Mode) String() string { + return proto.EnumName(IndexSpec_Mode_name, int32(x)) +} +func (x *IndexSpec_Mode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(IndexSpec_Mode_value, data, "IndexSpec_Mode") + if err != nil { + return err + } + *x = IndexSpec_Mode(value) + return nil +} + +type IndexDocumentParams_Freshness int32 + +const ( + IndexDocumentParams_SYNCHRONOUSLY IndexDocumentParams_Freshness = 0 + IndexDocumentParams_WHEN_CONVENIENT IndexDocumentParams_Freshness = 1 +) + +var IndexDocumentParams_Freshness_name = map[int32]string{ + 0: "SYNCHRONOUSLY", + 1: "WHEN_CONVENIENT", +} +var IndexDocumentParams_Freshness_value = map[string]int32{ + "SYNCHRONOUSLY": 0, + "WHEN_CONVENIENT": 1, +} + +func (x IndexDocumentParams_Freshness) Enum() *IndexDocumentParams_Freshness { + p := new(IndexDocumentParams_Freshness) + *p = x + return p +} +func (x IndexDocumentParams_Freshness) String() string { + return proto.EnumName(IndexDocumentParams_Freshness_name, int32(x)) +} +func (x *IndexDocumentParams_Freshness) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(IndexDocumentParams_Freshness_value, data, "IndexDocumentParams_Freshness") + if err != nil { + return err + } + *x = IndexDocumentParams_Freshness(value) + return nil +} + +type ScorerSpec_Scorer int32 + +const ( + ScorerSpec_RESCORING_MATCH_SCORER ScorerSpec_Scorer = 0 + ScorerSpec_MATCH_SCORER ScorerSpec_Scorer = 2 +) + +var ScorerSpec_Scorer_name = map[int32]string{ + 0: "RESCORING_MATCH_SCORER", + 2: "MATCH_SCORER", +} +var ScorerSpec_Scorer_value = map[string]int32{ + "RESCORING_MATCH_SCORER": 0, + "MATCH_SCORER": 2, +} + +func (x ScorerSpec_Scorer) Enum() *ScorerSpec_Scorer { + p := new(ScorerSpec_Scorer) + *p = x + return p +} +func (x ScorerSpec_Scorer) String() string { + return proto.EnumName(ScorerSpec_Scorer_name, int32(x)) +} +func (x *ScorerSpec_Scorer) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ScorerSpec_Scorer_value, data, "ScorerSpec_Scorer") + if err != nil { + return err + } + *x = ScorerSpec_Scorer(value) + return nil +} + +type SearchParams_CursorType int32 + +const ( + SearchParams_NONE SearchParams_CursorType = 0 + SearchParams_SINGLE SearchParams_CursorType = 1 + SearchParams_PER_RESULT SearchParams_CursorType = 2 +) + +var SearchParams_CursorType_name = map[int32]string{ + 0: "NONE", + 1: "SINGLE", + 2: "PER_RESULT", +} +var SearchParams_CursorType_value = map[string]int32{ + "NONE": 0, + "SINGLE": 1, + "PER_RESULT": 2, +} + +func (x SearchParams_CursorType) Enum() *SearchParams_CursorType { + p := new(SearchParams_CursorType) + *p = x + return p +} +func (x SearchParams_CursorType) String() string { + return proto.EnumName(SearchParams_CursorType_name, int32(x)) +} +func (x *SearchParams_CursorType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SearchParams_CursorType_value, data, "SearchParams_CursorType") + if err != nil { + return err + } + *x = SearchParams_CursorType(value) + return nil +} + +type SearchParams_ParsingMode int32 + +const ( + SearchParams_STRICT SearchParams_ParsingMode = 0 + SearchParams_RELAXED SearchParams_ParsingMode = 1 +) + +var SearchParams_ParsingMode_name = map[int32]string{ + 0: "STRICT", + 1: "RELAXED", +} +var SearchParams_ParsingMode_value = map[string]int32{ + "STRICT": 0, + "RELAXED": 1, +} + +func (x SearchParams_ParsingMode) Enum() *SearchParams_ParsingMode { + p := new(SearchParams_ParsingMode) + *p = x + return p +} +func (x SearchParams_ParsingMode) String() string { + return proto.EnumName(SearchParams_ParsingMode_name, int32(x)) +} +func (x *SearchParams_ParsingMode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SearchParams_ParsingMode_value, data, "SearchParams_ParsingMode") + if err != nil { + return err + } + *x = SearchParams_ParsingMode(value) + return nil +} + +type Scope struct { + Type *Scope_Type `protobuf:"varint,1,opt,name=type,enum=search.Scope_Type" json:"type,omitempty"` + Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Scope) Reset() { *m = Scope{} } +func (m *Scope) String() string { return proto.CompactTextString(m) } +func (*Scope) ProtoMessage() {} + +func (m *Scope) GetType() Scope_Type { + if m != nil && m.Type != nil { + return *m.Type + } + return Scope_USER_BY_CANONICAL_ID +} + +func (m *Scope) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +type Entry struct { + Scope *Scope `protobuf:"bytes,1,opt,name=scope" json:"scope,omitempty"` + Permission *Entry_Permission `protobuf:"varint,2,opt,name=permission,enum=search.Entry_Permission" json:"permission,omitempty"` + DisplayName *string `protobuf:"bytes,3,opt,name=display_name" json:"display_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Entry) Reset() { *m = Entry{} } +func (m *Entry) String() string { return proto.CompactTextString(m) } +func (*Entry) ProtoMessage() {} + +func (m *Entry) GetScope() *Scope { + if m != nil { + return m.Scope + } + return nil +} + +func (m *Entry) GetPermission() Entry_Permission { + if m != nil && m.Permission != nil { + return *m.Permission + } + return Entry_READ +} + +func (m *Entry) GetDisplayName() string { + if m != nil && m.DisplayName != nil { + return *m.DisplayName + } + return "" +} + +type AccessControlList struct { + Owner *string `protobuf:"bytes,1,opt,name=owner" json:"owner,omitempty"` + Entries []*Entry `protobuf:"bytes,2,rep,name=entries" json:"entries,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AccessControlList) Reset() { *m = AccessControlList{} } +func (m *AccessControlList) String() string { return proto.CompactTextString(m) } +func (*AccessControlList) ProtoMessage() {} + +func (m *AccessControlList) GetOwner() string { + if m != nil && m.Owner != nil { + return *m.Owner + } + return "" +} + +func (m *AccessControlList) GetEntries() []*Entry { + if m != nil { + return m.Entries + } + return nil +} + +type FieldValue struct { + Type *FieldValue_ContentType `protobuf:"varint,1,opt,name=type,enum=search.FieldValue_ContentType,def=0" json:"type,omitempty"` + Language *string `protobuf:"bytes,2,opt,name=language,def=en" json:"language,omitempty"` + StringValue *string `protobuf:"bytes,3,opt,name=string_value" json:"string_value,omitempty"` + Geo *FieldValue_Geo `protobuf:"group,4,opt,name=Geo" json:"geo,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldValue) Reset() { *m = FieldValue{} } +func (m *FieldValue) String() string { return proto.CompactTextString(m) } +func (*FieldValue) ProtoMessage() {} + +const Default_FieldValue_Type FieldValue_ContentType = FieldValue_TEXT +const Default_FieldValue_Language string = "en" + +func (m *FieldValue) GetType() FieldValue_ContentType { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_FieldValue_Type +} + +func (m *FieldValue) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_FieldValue_Language +} + +func (m *FieldValue) GetStringValue() string { + if m != nil && m.StringValue != nil { + return *m.StringValue + } + return "" +} + +func (m *FieldValue) GetGeo() *FieldValue_Geo { + if m != nil { + return m.Geo + } + return nil +} + +type FieldValue_Geo struct { + Lat *float64 `protobuf:"fixed64,5,req,name=lat" json:"lat,omitempty"` + Lng *float64 `protobuf:"fixed64,6,req,name=lng" json:"lng,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldValue_Geo) Reset() { *m = FieldValue_Geo{} } +func (m *FieldValue_Geo) String() string { return proto.CompactTextString(m) } +func (*FieldValue_Geo) ProtoMessage() {} + +func (m *FieldValue_Geo) GetLat() float64 { + if m != nil && m.Lat != nil { + return *m.Lat + } + return 0 +} + +func (m *FieldValue_Geo) GetLng() float64 { + if m != nil && m.Lng != nil { + return *m.Lng + } + return 0 +} + +type Field struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Value *FieldValue `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Field) Reset() { *m = Field{} } +func (m *Field) String() string { return proto.CompactTextString(m) } +func (*Field) ProtoMessage() {} + +func (m *Field) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *Field) GetValue() *FieldValue { + if m != nil { + return m.Value + } + return nil +} + +type FieldTypes struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Type []FieldValue_ContentType `protobuf:"varint,2,rep,name=type,enum=search.FieldValue_ContentType" json:"type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldTypes) Reset() { *m = FieldTypes{} } +func (m *FieldTypes) String() string { return proto.CompactTextString(m) } +func (*FieldTypes) ProtoMessage() {} + +func (m *FieldTypes) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FieldTypes) GetType() []FieldValue_ContentType { + if m != nil { + return m.Type + } + return nil +} + +type IndexShardSettings struct { + PrevNumShards []int32 `protobuf:"varint,1,rep,name=prev_num_shards" json:"prev_num_shards,omitempty"` + NumShards *int32 `protobuf:"varint,2,req,name=num_shards,def=1" json:"num_shards,omitempty"` + PrevNumShardsSearchFalse []int32 `protobuf:"varint,3,rep,name=prev_num_shards_search_false" json:"prev_num_shards_search_false,omitempty"` + LocalReplica *string `protobuf:"bytes,4,opt,name=local_replica,def=" json:"local_replica,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexShardSettings) Reset() { *m = IndexShardSettings{} } +func (m *IndexShardSettings) String() string { return proto.CompactTextString(m) } +func (*IndexShardSettings) ProtoMessage() {} + +const Default_IndexShardSettings_NumShards int32 = 1 + +func (m *IndexShardSettings) GetPrevNumShards() []int32 { + if m != nil { + return m.PrevNumShards + } + return nil +} + +func (m *IndexShardSettings) GetNumShards() int32 { + if m != nil && m.NumShards != nil { + return *m.NumShards + } + return Default_IndexShardSettings_NumShards +} + +func (m *IndexShardSettings) GetPrevNumShardsSearchFalse() []int32 { + if m != nil { + return m.PrevNumShardsSearchFalse + } + return nil +} + +func (m *IndexShardSettings) GetLocalReplica() string { + if m != nil && m.LocalReplica != nil { + return *m.LocalReplica + } + return "" +} + +type FacetValue struct { + Type *FacetValue_ContentType `protobuf:"varint,1,opt,name=type,enum=search.FacetValue_ContentType,def=2" json:"type,omitempty"` + StringValue *string `protobuf:"bytes,3,opt,name=string_value" json:"string_value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetValue) Reset() { *m = FacetValue{} } +func (m *FacetValue) String() string { return proto.CompactTextString(m) } +func (*FacetValue) ProtoMessage() {} + +const Default_FacetValue_Type FacetValue_ContentType = FacetValue_ATOM + +func (m *FacetValue) GetType() FacetValue_ContentType { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_FacetValue_Type +} + +func (m *FacetValue) GetStringValue() string { + if m != nil && m.StringValue != nil { + return *m.StringValue + } + return "" +} + +type Facet struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Value *FacetValue `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Facet) Reset() { *m = Facet{} } +func (m *Facet) String() string { return proto.CompactTextString(m) } +func (*Facet) ProtoMessage() {} + +func (m *Facet) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *Facet) GetValue() *FacetValue { + if m != nil { + return m.Value + } + return nil +} + +type DocumentMetadata struct { + Version *int64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + CommittedStVersion *int64 `protobuf:"varint,2,opt,name=committed_st_version" json:"committed_st_version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DocumentMetadata) Reset() { *m = DocumentMetadata{} } +func (m *DocumentMetadata) String() string { return proto.CompactTextString(m) } +func (*DocumentMetadata) ProtoMessage() {} + +func (m *DocumentMetadata) GetVersion() int64 { + if m != nil && m.Version != nil { + return *m.Version + } + return 0 +} + +func (m *DocumentMetadata) GetCommittedStVersion() int64 { + if m != nil && m.CommittedStVersion != nil { + return *m.CommittedStVersion + } + return 0 +} + +type Document struct { + Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` + Language *string `protobuf:"bytes,2,opt,name=language,def=en" json:"language,omitempty"` + Field []*Field `protobuf:"bytes,3,rep,name=field" json:"field,omitempty"` + OrderId *int32 `protobuf:"varint,4,opt,name=order_id" json:"order_id,omitempty"` + Storage *Document_Storage `protobuf:"varint,5,opt,name=storage,enum=search.Document_Storage,def=0" json:"storage,omitempty"` + Facet []*Facet `protobuf:"bytes,8,rep,name=facet" json:"facet,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Document) Reset() { *m = Document{} } +func (m *Document) String() string { return proto.CompactTextString(m) } +func (*Document) ProtoMessage() {} + +const Default_Document_Language string = "en" +const Default_Document_Storage Document_Storage = Document_DISK + +func (m *Document) GetId() string { + if m != nil && m.Id != nil { + return *m.Id + } + return "" +} + +func (m *Document) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_Document_Language +} + +func (m *Document) GetField() []*Field { + if m != nil { + return m.Field + } + return nil +} + +func (m *Document) GetOrderId() int32 { + if m != nil && m.OrderId != nil { + return *m.OrderId + } + return 0 +} + +func (m *Document) GetStorage() Document_Storage { + if m != nil && m.Storage != nil { + return *m.Storage + } + return Default_Document_Storage +} + +func (m *Document) GetFacet() []*Facet { + if m != nil { + return m.Facet + } + return nil +} + +type SearchServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *SearchServiceError) Reset() { *m = SearchServiceError{} } +func (m *SearchServiceError) String() string { return proto.CompactTextString(m) } +func (*SearchServiceError) ProtoMessage() {} + +type RequestStatus struct { + Code *SearchServiceError_ErrorCode `protobuf:"varint,1,req,name=code,enum=search.SearchServiceError_ErrorCode" json:"code,omitempty"` + ErrorDetail *string `protobuf:"bytes,2,opt,name=error_detail" json:"error_detail,omitempty"` + CanonicalCode *int32 `protobuf:"varint,3,opt,name=canonical_code" json:"canonical_code,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RequestStatus) Reset() { *m = RequestStatus{} } +func (m *RequestStatus) String() string { return proto.CompactTextString(m) } +func (*RequestStatus) ProtoMessage() {} + +func (m *RequestStatus) GetCode() SearchServiceError_ErrorCode { + if m != nil && m.Code != nil { + return *m.Code + } + return SearchServiceError_OK +} + +func (m *RequestStatus) GetErrorDetail() string { + if m != nil && m.ErrorDetail != nil { + return *m.ErrorDetail + } + return "" +} + +func (m *RequestStatus) GetCanonicalCode() int32 { + if m != nil && m.CanonicalCode != nil { + return *m.CanonicalCode + } + return 0 +} + +type IndexSpec struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Consistency *IndexSpec_Consistency `protobuf:"varint,2,opt,name=consistency,enum=search.IndexSpec_Consistency,def=1" json:"consistency,omitempty"` + Namespace *string `protobuf:"bytes,3,opt,name=namespace" json:"namespace,omitempty"` + Version *int32 `protobuf:"varint,4,opt,name=version" json:"version,omitempty"` + Source *IndexSpec_Source `protobuf:"varint,5,opt,name=source,enum=search.IndexSpec_Source,def=0" json:"source,omitempty"` + Mode *IndexSpec_Mode `protobuf:"varint,6,opt,name=mode,enum=search.IndexSpec_Mode,def=0" json:"mode,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexSpec) Reset() { *m = IndexSpec{} } +func (m *IndexSpec) String() string { return proto.CompactTextString(m) } +func (*IndexSpec) ProtoMessage() {} + +const Default_IndexSpec_Consistency IndexSpec_Consistency = IndexSpec_PER_DOCUMENT +const Default_IndexSpec_Source IndexSpec_Source = IndexSpec_SEARCH +const Default_IndexSpec_Mode IndexSpec_Mode = IndexSpec_PRIORITY + +func (m *IndexSpec) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *IndexSpec) GetConsistency() IndexSpec_Consistency { + if m != nil && m.Consistency != nil { + return *m.Consistency + } + return Default_IndexSpec_Consistency +} + +func (m *IndexSpec) GetNamespace() string { + if m != nil && m.Namespace != nil { + return *m.Namespace + } + return "" +} + +func (m *IndexSpec) GetVersion() int32 { + if m != nil && m.Version != nil { + return *m.Version + } + return 0 +} + +func (m *IndexSpec) GetSource() IndexSpec_Source { + if m != nil && m.Source != nil { + return *m.Source + } + return Default_IndexSpec_Source +} + +func (m *IndexSpec) GetMode() IndexSpec_Mode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_IndexSpec_Mode +} + +type IndexMetadata struct { + IndexSpec *IndexSpec `protobuf:"bytes,1,req,name=index_spec" json:"index_spec,omitempty"` + Field []*FieldTypes `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` + Storage *IndexMetadata_Storage `protobuf:"bytes,3,opt,name=storage" json:"storage,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexMetadata) Reset() { *m = IndexMetadata{} } +func (m *IndexMetadata) String() string { return proto.CompactTextString(m) } +func (*IndexMetadata) ProtoMessage() {} + +func (m *IndexMetadata) GetIndexSpec() *IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +func (m *IndexMetadata) GetField() []*FieldTypes { + if m != nil { + return m.Field + } + return nil +} + +func (m *IndexMetadata) GetStorage() *IndexMetadata_Storage { + if m != nil { + return m.Storage + } + return nil +} + +type IndexMetadata_Storage struct { + AmountUsed *int64 `protobuf:"varint,1,opt,name=amount_used" json:"amount_used,omitempty"` + Limit *int64 `protobuf:"varint,2,opt,name=limit" json:"limit,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexMetadata_Storage) Reset() { *m = IndexMetadata_Storage{} } +func (m *IndexMetadata_Storage) String() string { return proto.CompactTextString(m) } +func (*IndexMetadata_Storage) ProtoMessage() {} + +func (m *IndexMetadata_Storage) GetAmountUsed() int64 { + if m != nil && m.AmountUsed != nil { + return *m.AmountUsed + } + return 0 +} + +func (m *IndexMetadata_Storage) GetLimit() int64 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return 0 +} + +type IndexDocumentParams struct { + Document []*Document `protobuf:"bytes,1,rep,name=document" json:"document,omitempty"` + Freshness *IndexDocumentParams_Freshness `protobuf:"varint,2,opt,name=freshness,enum=search.IndexDocumentParams_Freshness,def=0" json:"freshness,omitempty"` + IndexSpec *IndexSpec `protobuf:"bytes,3,req,name=index_spec" json:"index_spec,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexDocumentParams) Reset() { *m = IndexDocumentParams{} } +func (m *IndexDocumentParams) String() string { return proto.CompactTextString(m) } +func (*IndexDocumentParams) ProtoMessage() {} + +const Default_IndexDocumentParams_Freshness IndexDocumentParams_Freshness = IndexDocumentParams_SYNCHRONOUSLY + +func (m *IndexDocumentParams) GetDocument() []*Document { + if m != nil { + return m.Document + } + return nil +} + +func (m *IndexDocumentParams) GetFreshness() IndexDocumentParams_Freshness { + if m != nil && m.Freshness != nil { + return *m.Freshness + } + return Default_IndexDocumentParams_Freshness +} + +func (m *IndexDocumentParams) GetIndexSpec() *IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +type IndexDocumentRequest struct { + Params *IndexDocumentParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexDocumentRequest) Reset() { *m = IndexDocumentRequest{} } +func (m *IndexDocumentRequest) String() string { return proto.CompactTextString(m) } +func (*IndexDocumentRequest) ProtoMessage() {} + +func (m *IndexDocumentRequest) GetParams() *IndexDocumentParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *IndexDocumentRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type IndexDocumentResponse struct { + Status []*RequestStatus `protobuf:"bytes,1,rep,name=status" json:"status,omitempty"` + DocId []string `protobuf:"bytes,2,rep,name=doc_id" json:"doc_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *IndexDocumentResponse) Reset() { *m = IndexDocumentResponse{} } +func (m *IndexDocumentResponse) String() string { return proto.CompactTextString(m) } +func (*IndexDocumentResponse) ProtoMessage() {} + +func (m *IndexDocumentResponse) GetStatus() []*RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *IndexDocumentResponse) GetDocId() []string { + if m != nil { + return m.DocId + } + return nil +} + +type DeleteDocumentParams struct { + DocId []string `protobuf:"bytes,1,rep,name=doc_id" json:"doc_id,omitempty"` + IndexSpec *IndexSpec `protobuf:"bytes,2,req,name=index_spec" json:"index_spec,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteDocumentParams) Reset() { *m = DeleteDocumentParams{} } +func (m *DeleteDocumentParams) String() string { return proto.CompactTextString(m) } +func (*DeleteDocumentParams) ProtoMessage() {} + +func (m *DeleteDocumentParams) GetDocId() []string { + if m != nil { + return m.DocId + } + return nil +} + +func (m *DeleteDocumentParams) GetIndexSpec() *IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +type DeleteDocumentRequest struct { + Params *DeleteDocumentParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteDocumentRequest) Reset() { *m = DeleteDocumentRequest{} } +func (m *DeleteDocumentRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteDocumentRequest) ProtoMessage() {} + +func (m *DeleteDocumentRequest) GetParams() *DeleteDocumentParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *DeleteDocumentRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type DeleteDocumentResponse struct { + Status []*RequestStatus `protobuf:"bytes,1,rep,name=status" json:"status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteDocumentResponse) Reset() { *m = DeleteDocumentResponse{} } +func (m *DeleteDocumentResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteDocumentResponse) ProtoMessage() {} + +func (m *DeleteDocumentResponse) GetStatus() []*RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +type ListDocumentsParams struct { + IndexSpec *IndexSpec `protobuf:"bytes,1,req,name=index_spec" json:"index_spec,omitempty"` + StartDocId *string `protobuf:"bytes,2,opt,name=start_doc_id" json:"start_doc_id,omitempty"` + IncludeStartDoc *bool `protobuf:"varint,3,opt,name=include_start_doc,def=1" json:"include_start_doc,omitempty"` + Limit *int32 `protobuf:"varint,4,opt,name=limit,def=100" json:"limit,omitempty"` + KeysOnly *bool `protobuf:"varint,5,opt,name=keys_only" json:"keys_only,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListDocumentsParams) Reset() { *m = ListDocumentsParams{} } +func (m *ListDocumentsParams) String() string { return proto.CompactTextString(m) } +func (*ListDocumentsParams) ProtoMessage() {} + +const Default_ListDocumentsParams_IncludeStartDoc bool = true +const Default_ListDocumentsParams_Limit int32 = 100 + +func (m *ListDocumentsParams) GetIndexSpec() *IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +func (m *ListDocumentsParams) GetStartDocId() string { + if m != nil && m.StartDocId != nil { + return *m.StartDocId + } + return "" +} + +func (m *ListDocumentsParams) GetIncludeStartDoc() bool { + if m != nil && m.IncludeStartDoc != nil { + return *m.IncludeStartDoc + } + return Default_ListDocumentsParams_IncludeStartDoc +} + +func (m *ListDocumentsParams) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return Default_ListDocumentsParams_Limit +} + +func (m *ListDocumentsParams) GetKeysOnly() bool { + if m != nil && m.KeysOnly != nil { + return *m.KeysOnly + } + return false +} + +type ListDocumentsRequest struct { + Params *ListDocumentsParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,2,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListDocumentsRequest) Reset() { *m = ListDocumentsRequest{} } +func (m *ListDocumentsRequest) String() string { return proto.CompactTextString(m) } +func (*ListDocumentsRequest) ProtoMessage() {} + +func (m *ListDocumentsRequest) GetParams() *ListDocumentsParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *ListDocumentsRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type ListDocumentsResponse struct { + Status *RequestStatus `protobuf:"bytes,1,req,name=status" json:"status,omitempty"` + Document []*Document `protobuf:"bytes,2,rep,name=document" json:"document,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListDocumentsResponse) Reset() { *m = ListDocumentsResponse{} } +func (m *ListDocumentsResponse) String() string { return proto.CompactTextString(m) } +func (*ListDocumentsResponse) ProtoMessage() {} + +func (m *ListDocumentsResponse) GetStatus() *RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *ListDocumentsResponse) GetDocument() []*Document { + if m != nil { + return m.Document + } + return nil +} + +type ListIndexesParams struct { + FetchSchema *bool `protobuf:"varint,1,opt,name=fetch_schema" json:"fetch_schema,omitempty"` + Limit *int32 `protobuf:"varint,2,opt,name=limit,def=20" json:"limit,omitempty"` + Namespace *string `protobuf:"bytes,3,opt,name=namespace" json:"namespace,omitempty"` + StartIndexName *string `protobuf:"bytes,4,opt,name=start_index_name" json:"start_index_name,omitempty"` + IncludeStartIndex *bool `protobuf:"varint,5,opt,name=include_start_index,def=1" json:"include_start_index,omitempty"` + IndexNamePrefix *string `protobuf:"bytes,6,opt,name=index_name_prefix" json:"index_name_prefix,omitempty"` + Offset *int32 `protobuf:"varint,7,opt,name=offset" json:"offset,omitempty"` + Source *IndexSpec_Source `protobuf:"varint,8,opt,name=source,enum=search.IndexSpec_Source,def=0" json:"source,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListIndexesParams) Reset() { *m = ListIndexesParams{} } +func (m *ListIndexesParams) String() string { return proto.CompactTextString(m) } +func (*ListIndexesParams) ProtoMessage() {} + +const Default_ListIndexesParams_Limit int32 = 20 +const Default_ListIndexesParams_IncludeStartIndex bool = true +const Default_ListIndexesParams_Source IndexSpec_Source = IndexSpec_SEARCH + +func (m *ListIndexesParams) GetFetchSchema() bool { + if m != nil && m.FetchSchema != nil { + return *m.FetchSchema + } + return false +} + +func (m *ListIndexesParams) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return Default_ListIndexesParams_Limit +} + +func (m *ListIndexesParams) GetNamespace() string { + if m != nil && m.Namespace != nil { + return *m.Namespace + } + return "" +} + +func (m *ListIndexesParams) GetStartIndexName() string { + if m != nil && m.StartIndexName != nil { + return *m.StartIndexName + } + return "" +} + +func (m *ListIndexesParams) GetIncludeStartIndex() bool { + if m != nil && m.IncludeStartIndex != nil { + return *m.IncludeStartIndex + } + return Default_ListIndexesParams_IncludeStartIndex +} + +func (m *ListIndexesParams) GetIndexNamePrefix() string { + if m != nil && m.IndexNamePrefix != nil { + return *m.IndexNamePrefix + } + return "" +} + +func (m *ListIndexesParams) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return 0 +} + +func (m *ListIndexesParams) GetSource() IndexSpec_Source { + if m != nil && m.Source != nil { + return *m.Source + } + return Default_ListIndexesParams_Source +} + +type ListIndexesRequest struct { + Params *ListIndexesParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListIndexesRequest) Reset() { *m = ListIndexesRequest{} } +func (m *ListIndexesRequest) String() string { return proto.CompactTextString(m) } +func (*ListIndexesRequest) ProtoMessage() {} + +func (m *ListIndexesRequest) GetParams() *ListIndexesParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *ListIndexesRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type ListIndexesResponse struct { + Status *RequestStatus `protobuf:"bytes,1,req,name=status" json:"status,omitempty"` + IndexMetadata []*IndexMetadata `protobuf:"bytes,2,rep,name=index_metadata" json:"index_metadata,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListIndexesResponse) Reset() { *m = ListIndexesResponse{} } +func (m *ListIndexesResponse) String() string { return proto.CompactTextString(m) } +func (*ListIndexesResponse) ProtoMessage() {} + +func (m *ListIndexesResponse) GetStatus() *RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *ListIndexesResponse) GetIndexMetadata() []*IndexMetadata { + if m != nil { + return m.IndexMetadata + } + return nil +} + +type DeleteSchemaParams struct { + Source *IndexSpec_Source `protobuf:"varint,1,opt,name=source,enum=search.IndexSpec_Source,def=0" json:"source,omitempty"` + IndexSpec []*IndexSpec `protobuf:"bytes,2,rep,name=index_spec" json:"index_spec,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteSchemaParams) Reset() { *m = DeleteSchemaParams{} } +func (m *DeleteSchemaParams) String() string { return proto.CompactTextString(m) } +func (*DeleteSchemaParams) ProtoMessage() {} + +const Default_DeleteSchemaParams_Source IndexSpec_Source = IndexSpec_SEARCH + +func (m *DeleteSchemaParams) GetSource() IndexSpec_Source { + if m != nil && m.Source != nil { + return *m.Source + } + return Default_DeleteSchemaParams_Source +} + +func (m *DeleteSchemaParams) GetIndexSpec() []*IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +type DeleteSchemaRequest struct { + Params *DeleteSchemaParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteSchemaRequest) Reset() { *m = DeleteSchemaRequest{} } +func (m *DeleteSchemaRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteSchemaRequest) ProtoMessage() {} + +func (m *DeleteSchemaRequest) GetParams() *DeleteSchemaParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *DeleteSchemaRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type DeleteSchemaResponse struct { + Status []*RequestStatus `protobuf:"bytes,1,rep,name=status" json:"status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DeleteSchemaResponse) Reset() { *m = DeleteSchemaResponse{} } +func (m *DeleteSchemaResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteSchemaResponse) ProtoMessage() {} + +func (m *DeleteSchemaResponse) GetStatus() []*RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +type SortSpec struct { + SortExpression *string `protobuf:"bytes,1,req,name=sort_expression" json:"sort_expression,omitempty"` + SortDescending *bool `protobuf:"varint,2,opt,name=sort_descending,def=1" json:"sort_descending,omitempty"` + DefaultValueText *string `protobuf:"bytes,4,opt,name=default_value_text" json:"default_value_text,omitempty"` + DefaultValueNumeric *float64 `protobuf:"fixed64,5,opt,name=default_value_numeric" json:"default_value_numeric,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SortSpec) Reset() { *m = SortSpec{} } +func (m *SortSpec) String() string { return proto.CompactTextString(m) } +func (*SortSpec) ProtoMessage() {} + +const Default_SortSpec_SortDescending bool = true + +func (m *SortSpec) GetSortExpression() string { + if m != nil && m.SortExpression != nil { + return *m.SortExpression + } + return "" +} + +func (m *SortSpec) GetSortDescending() bool { + if m != nil && m.SortDescending != nil { + return *m.SortDescending + } + return Default_SortSpec_SortDescending +} + +func (m *SortSpec) GetDefaultValueText() string { + if m != nil && m.DefaultValueText != nil { + return *m.DefaultValueText + } + return "" +} + +func (m *SortSpec) GetDefaultValueNumeric() float64 { + if m != nil && m.DefaultValueNumeric != nil { + return *m.DefaultValueNumeric + } + return 0 +} + +type ScorerSpec struct { + Scorer *ScorerSpec_Scorer `protobuf:"varint,1,opt,name=scorer,enum=search.ScorerSpec_Scorer,def=2" json:"scorer,omitempty"` + Limit *int32 `protobuf:"varint,2,opt,name=limit,def=1000" json:"limit,omitempty"` + MatchScorerParameters *string `protobuf:"bytes,9,opt,name=match_scorer_parameters" json:"match_scorer_parameters,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ScorerSpec) Reset() { *m = ScorerSpec{} } +func (m *ScorerSpec) String() string { return proto.CompactTextString(m) } +func (*ScorerSpec) ProtoMessage() {} + +const Default_ScorerSpec_Scorer ScorerSpec_Scorer = ScorerSpec_MATCH_SCORER +const Default_ScorerSpec_Limit int32 = 1000 + +func (m *ScorerSpec) GetScorer() ScorerSpec_Scorer { + if m != nil && m.Scorer != nil { + return *m.Scorer + } + return Default_ScorerSpec_Scorer +} + +func (m *ScorerSpec) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return Default_ScorerSpec_Limit +} + +func (m *ScorerSpec) GetMatchScorerParameters() string { + if m != nil && m.MatchScorerParameters != nil { + return *m.MatchScorerParameters + } + return "" +} + +type FieldSpec struct { + Name []string `protobuf:"bytes,1,rep,name=name" json:"name,omitempty"` + Expression []*FieldSpec_Expression `protobuf:"group,2,rep,name=Expression" json:"expression,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldSpec) Reset() { *m = FieldSpec{} } +func (m *FieldSpec) String() string { return proto.CompactTextString(m) } +func (*FieldSpec) ProtoMessage() {} + +func (m *FieldSpec) GetName() []string { + if m != nil { + return m.Name + } + return nil +} + +func (m *FieldSpec) GetExpression() []*FieldSpec_Expression { + if m != nil { + return m.Expression + } + return nil +} + +type FieldSpec_Expression struct { + Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` + Expression *string `protobuf:"bytes,4,req,name=expression" json:"expression,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldSpec_Expression) Reset() { *m = FieldSpec_Expression{} } +func (m *FieldSpec_Expression) String() string { return proto.CompactTextString(m) } +func (*FieldSpec_Expression) ProtoMessage() {} + +func (m *FieldSpec_Expression) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FieldSpec_Expression) GetExpression() string { + if m != nil && m.Expression != nil { + return *m.Expression + } + return "" +} + +type FacetRange struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Start *string `protobuf:"bytes,2,opt,name=start" json:"start,omitempty"` + End *string `protobuf:"bytes,3,opt,name=end" json:"end,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetRange) Reset() { *m = FacetRange{} } +func (m *FacetRange) String() string { return proto.CompactTextString(m) } +func (*FacetRange) ProtoMessage() {} + +func (m *FacetRange) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FacetRange) GetStart() string { + if m != nil && m.Start != nil { + return *m.Start + } + return "" +} + +func (m *FacetRange) GetEnd() string { + if m != nil && m.End != nil { + return *m.End + } + return "" +} + +type FacetRequestParam struct { + ValueLimit *int32 `protobuf:"varint,1,opt,name=value_limit" json:"value_limit,omitempty"` + Range []*FacetRange `protobuf:"bytes,2,rep,name=range" json:"range,omitempty"` + ValueConstraint []string `protobuf:"bytes,3,rep,name=value_constraint" json:"value_constraint,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetRequestParam) Reset() { *m = FacetRequestParam{} } +func (m *FacetRequestParam) String() string { return proto.CompactTextString(m) } +func (*FacetRequestParam) ProtoMessage() {} + +func (m *FacetRequestParam) GetValueLimit() int32 { + if m != nil && m.ValueLimit != nil { + return *m.ValueLimit + } + return 0 +} + +func (m *FacetRequestParam) GetRange() []*FacetRange { + if m != nil { + return m.Range + } + return nil +} + +func (m *FacetRequestParam) GetValueConstraint() []string { + if m != nil { + return m.ValueConstraint + } + return nil +} + +type FacetAutoDetectParam struct { + ValueLimit *int32 `protobuf:"varint,1,opt,name=value_limit,def=10" json:"value_limit,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetAutoDetectParam) Reset() { *m = FacetAutoDetectParam{} } +func (m *FacetAutoDetectParam) String() string { return proto.CompactTextString(m) } +func (*FacetAutoDetectParam) ProtoMessage() {} + +const Default_FacetAutoDetectParam_ValueLimit int32 = 10 + +func (m *FacetAutoDetectParam) GetValueLimit() int32 { + if m != nil && m.ValueLimit != nil { + return *m.ValueLimit + } + return Default_FacetAutoDetectParam_ValueLimit +} + +type FacetRequest struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Params *FacetRequestParam `protobuf:"bytes,2,opt,name=params" json:"params,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetRequest) Reset() { *m = FacetRequest{} } +func (m *FacetRequest) String() string { return proto.CompactTextString(m) } +func (*FacetRequest) ProtoMessage() {} + +func (m *FacetRequest) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FacetRequest) GetParams() *FacetRequestParam { + if m != nil { + return m.Params + } + return nil +} + +type FacetRefinement struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + Range *FacetRefinement_Range `protobuf:"bytes,3,opt,name=range" json:"range,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetRefinement) Reset() { *m = FacetRefinement{} } +func (m *FacetRefinement) String() string { return proto.CompactTextString(m) } +func (*FacetRefinement) ProtoMessage() {} + +func (m *FacetRefinement) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FacetRefinement) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +func (m *FacetRefinement) GetRange() *FacetRefinement_Range { + if m != nil { + return m.Range + } + return nil +} + +type FacetRefinement_Range struct { + Start *string `protobuf:"bytes,1,opt,name=start" json:"start,omitempty"` + End *string `protobuf:"bytes,2,opt,name=end" json:"end,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetRefinement_Range) Reset() { *m = FacetRefinement_Range{} } +func (m *FacetRefinement_Range) String() string { return proto.CompactTextString(m) } +func (*FacetRefinement_Range) ProtoMessage() {} + +func (m *FacetRefinement_Range) GetStart() string { + if m != nil && m.Start != nil { + return *m.Start + } + return "" +} + +func (m *FacetRefinement_Range) GetEnd() string { + if m != nil && m.End != nil { + return *m.End + } + return "" +} + +type SearchParams struct { + IndexSpec *IndexSpec `protobuf:"bytes,1,req,name=index_spec" json:"index_spec,omitempty"` + Query *string `protobuf:"bytes,2,req,name=query" json:"query,omitempty"` + Cursor *string `protobuf:"bytes,4,opt,name=cursor" json:"cursor,omitempty"` + Offset *int32 `protobuf:"varint,11,opt,name=offset" json:"offset,omitempty"` + CursorType *SearchParams_CursorType `protobuf:"varint,5,opt,name=cursor_type,enum=search.SearchParams_CursorType,def=0" json:"cursor_type,omitempty"` + Limit *int32 `protobuf:"varint,6,opt,name=limit,def=20" json:"limit,omitempty"` + MatchedCountAccuracy *int32 `protobuf:"varint,7,opt,name=matched_count_accuracy" json:"matched_count_accuracy,omitempty"` + SortSpec []*SortSpec `protobuf:"bytes,8,rep,name=sort_spec" json:"sort_spec,omitempty"` + ScorerSpec *ScorerSpec `protobuf:"bytes,9,opt,name=scorer_spec" json:"scorer_spec,omitempty"` + FieldSpec *FieldSpec `protobuf:"bytes,10,opt,name=field_spec" json:"field_spec,omitempty"` + KeysOnly *bool `protobuf:"varint,12,opt,name=keys_only" json:"keys_only,omitempty"` + ParsingMode *SearchParams_ParsingMode `protobuf:"varint,13,opt,name=parsing_mode,enum=search.SearchParams_ParsingMode,def=0" json:"parsing_mode,omitempty"` + AutoDiscoverFacetCount *int32 `protobuf:"varint,15,opt,name=auto_discover_facet_count,def=0" json:"auto_discover_facet_count,omitempty"` + IncludeFacet []*FacetRequest `protobuf:"bytes,16,rep,name=include_facet" json:"include_facet,omitempty"` + FacetRefinement []*FacetRefinement `protobuf:"bytes,17,rep,name=facet_refinement" json:"facet_refinement,omitempty"` + FacetAutoDetectParam *FacetAutoDetectParam `protobuf:"bytes,18,opt,name=facet_auto_detect_param" json:"facet_auto_detect_param,omitempty"` + FacetDepth *int32 `protobuf:"varint,19,opt,name=facet_depth,def=1000" json:"facet_depth,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SearchParams) Reset() { *m = SearchParams{} } +func (m *SearchParams) String() string { return proto.CompactTextString(m) } +func (*SearchParams) ProtoMessage() {} + +const Default_SearchParams_CursorType SearchParams_CursorType = SearchParams_NONE +const Default_SearchParams_Limit int32 = 20 +const Default_SearchParams_ParsingMode SearchParams_ParsingMode = SearchParams_STRICT +const Default_SearchParams_AutoDiscoverFacetCount int32 = 0 +const Default_SearchParams_FacetDepth int32 = 1000 + +func (m *SearchParams) GetIndexSpec() *IndexSpec { + if m != nil { + return m.IndexSpec + } + return nil +} + +func (m *SearchParams) GetQuery() string { + if m != nil && m.Query != nil { + return *m.Query + } + return "" +} + +func (m *SearchParams) GetCursor() string { + if m != nil && m.Cursor != nil { + return *m.Cursor + } + return "" +} + +func (m *SearchParams) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return 0 +} + +func (m *SearchParams) GetCursorType() SearchParams_CursorType { + if m != nil && m.CursorType != nil { + return *m.CursorType + } + return Default_SearchParams_CursorType +} + +func (m *SearchParams) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return Default_SearchParams_Limit +} + +func (m *SearchParams) GetMatchedCountAccuracy() int32 { + if m != nil && m.MatchedCountAccuracy != nil { + return *m.MatchedCountAccuracy + } + return 0 +} + +func (m *SearchParams) GetSortSpec() []*SortSpec { + if m != nil { + return m.SortSpec + } + return nil +} + +func (m *SearchParams) GetScorerSpec() *ScorerSpec { + if m != nil { + return m.ScorerSpec + } + return nil +} + +func (m *SearchParams) GetFieldSpec() *FieldSpec { + if m != nil { + return m.FieldSpec + } + return nil +} + +func (m *SearchParams) GetKeysOnly() bool { + if m != nil && m.KeysOnly != nil { + return *m.KeysOnly + } + return false +} + +func (m *SearchParams) GetParsingMode() SearchParams_ParsingMode { + if m != nil && m.ParsingMode != nil { + return *m.ParsingMode + } + return Default_SearchParams_ParsingMode +} + +func (m *SearchParams) GetAutoDiscoverFacetCount() int32 { + if m != nil && m.AutoDiscoverFacetCount != nil { + return *m.AutoDiscoverFacetCount + } + return Default_SearchParams_AutoDiscoverFacetCount +} + +func (m *SearchParams) GetIncludeFacet() []*FacetRequest { + if m != nil { + return m.IncludeFacet + } + return nil +} + +func (m *SearchParams) GetFacetRefinement() []*FacetRefinement { + if m != nil { + return m.FacetRefinement + } + return nil +} + +func (m *SearchParams) GetFacetAutoDetectParam() *FacetAutoDetectParam { + if m != nil { + return m.FacetAutoDetectParam + } + return nil +} + +func (m *SearchParams) GetFacetDepth() int32 { + if m != nil && m.FacetDepth != nil { + return *m.FacetDepth + } + return Default_SearchParams_FacetDepth +} + +type SearchRequest struct { + Params *SearchParams `protobuf:"bytes,1,req,name=params" json:"params,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SearchRequest) Reset() { *m = SearchRequest{} } +func (m *SearchRequest) String() string { return proto.CompactTextString(m) } +func (*SearchRequest) ProtoMessage() {} + +func (m *SearchRequest) GetParams() *SearchParams { + if m != nil { + return m.Params + } + return nil +} + +func (m *SearchRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type FacetResultValue struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Count *int32 `protobuf:"varint,2,req,name=count" json:"count,omitempty"` + Refinement *FacetRefinement `protobuf:"bytes,3,req,name=refinement" json:"refinement,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetResultValue) Reset() { *m = FacetResultValue{} } +func (m *FacetResultValue) String() string { return proto.CompactTextString(m) } +func (*FacetResultValue) ProtoMessage() {} + +func (m *FacetResultValue) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FacetResultValue) GetCount() int32 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *FacetResultValue) GetRefinement() *FacetRefinement { + if m != nil { + return m.Refinement + } + return nil +} + +type FacetResult struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Value []*FacetResultValue `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FacetResult) Reset() { *m = FacetResult{} } +func (m *FacetResult) String() string { return proto.CompactTextString(m) } +func (*FacetResult) ProtoMessage() {} + +func (m *FacetResult) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FacetResult) GetValue() []*FacetResultValue { + if m != nil { + return m.Value + } + return nil +} + +type SearchResult struct { + Document *Document `protobuf:"bytes,1,req,name=document" json:"document,omitempty"` + Expression []*Field `protobuf:"bytes,4,rep,name=expression" json:"expression,omitempty"` + Score []float64 `protobuf:"fixed64,2,rep,name=score" json:"score,omitempty"` + Cursor *string `protobuf:"bytes,3,opt,name=cursor" json:"cursor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SearchResult) Reset() { *m = SearchResult{} } +func (m *SearchResult) String() string { return proto.CompactTextString(m) } +func (*SearchResult) ProtoMessage() {} + +func (m *SearchResult) GetDocument() *Document { + if m != nil { + return m.Document + } + return nil +} + +func (m *SearchResult) GetExpression() []*Field { + if m != nil { + return m.Expression + } + return nil +} + +func (m *SearchResult) GetScore() []float64 { + if m != nil { + return m.Score + } + return nil +} + +func (m *SearchResult) GetCursor() string { + if m != nil && m.Cursor != nil { + return *m.Cursor + } + return "" +} + +type SearchResponse struct { + Result []*SearchResult `protobuf:"bytes,1,rep,name=result" json:"result,omitempty"` + MatchedCount *int64 `protobuf:"varint,2,req,name=matched_count" json:"matched_count,omitempty"` + Status *RequestStatus `protobuf:"bytes,3,req,name=status" json:"status,omitempty"` + Cursor *string `protobuf:"bytes,4,opt,name=cursor" json:"cursor,omitempty"` + FacetResult []*FacetResult `protobuf:"bytes,5,rep,name=facet_result" json:"facet_result,omitempty"` + XXX_extensions map[int32]proto.Extension `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SearchResponse) Reset() { *m = SearchResponse{} } +func (m *SearchResponse) String() string { return proto.CompactTextString(m) } +func (*SearchResponse) ProtoMessage() {} + +var extRange_SearchResponse = []proto.ExtensionRange{ + {1000, 9999}, +} + +func (*SearchResponse) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_SearchResponse +} +func (m *SearchResponse) ExtensionMap() map[int32]proto.Extension { + if m.XXX_extensions == nil { + m.XXX_extensions = make(map[int32]proto.Extension) + } + return m.XXX_extensions +} + +func (m *SearchResponse) GetResult() []*SearchResult { + if m != nil { + return m.Result + } + return nil +} + +func (m *SearchResponse) GetMatchedCount() int64 { + if m != nil && m.MatchedCount != nil { + return *m.MatchedCount + } + return 0 +} + +func (m *SearchResponse) GetStatus() *RequestStatus { + if m != nil { + return m.Status + } + return nil +} + +func (m *SearchResponse) GetCursor() string { + if m != nil && m.Cursor != nil { + return *m.Cursor + } + return "" +} + +func (m *SearchResponse) GetFacetResult() []*FacetResult { + if m != nil { + return m.FacetResult + } + return nil +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/search/search.proto b/vendor/google.golang.org/appengine/internal/search/search.proto new file mode 100644 index 000000000..219f4c30a --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/search/search.proto @@ -0,0 +1,388 @@ +syntax = "proto2"; +option go_package = "search"; + +package search; + +message Scope { + enum Type { + USER_BY_CANONICAL_ID = 1; + USER_BY_EMAIL = 2; + GROUP_BY_CANONICAL_ID = 3; + GROUP_BY_EMAIL = 4; + GROUP_BY_DOMAIN = 5; + ALL_USERS = 6; + ALL_AUTHENTICATED_USERS = 7; + } + + optional Type type = 1; + optional string value = 2; +} + +message Entry { + enum Permission { + READ = 1; + WRITE = 2; + FULL_CONTROL = 3; + } + + optional Scope scope = 1; + optional Permission permission = 2; + optional string display_name = 3; +} + +message AccessControlList { + optional string owner = 1; + repeated Entry entries = 2; +} + +message FieldValue { + enum ContentType { + TEXT = 0; + HTML = 1; + ATOM = 2; + DATE = 3; + NUMBER = 4; + GEO = 5; + } + + optional ContentType type = 1 [default = TEXT]; + + optional string language = 2 [default = "en"]; + + optional string string_value = 3; + + optional group Geo = 4 { + required double lat = 5; + required double lng = 6; + } +} + +message Field { + required string name = 1; + required FieldValue value = 2; +} + +message FieldTypes { + required string name = 1; + repeated FieldValue.ContentType type = 2; +} + +message IndexShardSettings { + repeated int32 prev_num_shards = 1; + required int32 num_shards = 2 [default=1]; + repeated int32 prev_num_shards_search_false = 3; + optional string local_replica = 4 [default = ""]; +} + +message FacetValue { + enum ContentType { + ATOM = 2; + NUMBER = 4; + } + + optional ContentType type = 1 [default = ATOM]; + optional string string_value = 3; +} + +message Facet { + required string name = 1; + required FacetValue value = 2; +} + +message DocumentMetadata { + optional int64 version = 1; + optional int64 committed_st_version = 2; +} + +message Document { + optional string id = 1; + optional string language = 2 [default = "en"]; + repeated Field field = 3; + optional int32 order_id = 4; + + enum Storage { + DISK = 0; + } + + optional Storage storage = 5 [default = DISK]; + repeated Facet facet = 8; +} + +message SearchServiceError { + enum ErrorCode { + OK = 0; + INVALID_REQUEST = 1; + TRANSIENT_ERROR = 2; + INTERNAL_ERROR = 3; + PERMISSION_DENIED = 4; + TIMEOUT = 5; + CONCURRENT_TRANSACTION = 6; + } +} + +message RequestStatus { + required SearchServiceError.ErrorCode code = 1; + optional string error_detail = 2; + optional int32 canonical_code = 3; +} + +message IndexSpec { + required string name = 1; + + enum Consistency { + GLOBAL = 0; + PER_DOCUMENT = 1; + } + optional Consistency consistency = 2 [default = PER_DOCUMENT]; + + optional string namespace = 3; + optional int32 version = 4; + + enum Source { + SEARCH = 0; + DATASTORE = 1; + CLOUD_STORAGE = 2; + } + optional Source source = 5 [default = SEARCH]; + + enum Mode { + PRIORITY = 0; + BACKGROUND = 1; + } + optional Mode mode = 6 [default = PRIORITY]; +} + +message IndexMetadata { + required IndexSpec index_spec = 1; + + repeated FieldTypes field = 2; + + message Storage { + optional int64 amount_used = 1; + optional int64 limit = 2; + } + optional Storage storage = 3; +} + +message IndexDocumentParams { + repeated Document document = 1; + + enum Freshness { + SYNCHRONOUSLY = 0; + WHEN_CONVENIENT = 1; + } + optional Freshness freshness = 2 [default = SYNCHRONOUSLY, deprecated=true]; + + required IndexSpec index_spec = 3; +} + +message IndexDocumentRequest { + required IndexDocumentParams params = 1; + + optional bytes app_id = 3; +} + +message IndexDocumentResponse { + repeated RequestStatus status = 1; + + repeated string doc_id = 2; +} + +message DeleteDocumentParams { + repeated string doc_id = 1; + + required IndexSpec index_spec = 2; +} + +message DeleteDocumentRequest { + required DeleteDocumentParams params = 1; + + optional bytes app_id = 3; +} + +message DeleteDocumentResponse { + repeated RequestStatus status = 1; +} + +message ListDocumentsParams { + required IndexSpec index_spec = 1; + optional string start_doc_id = 2; + optional bool include_start_doc = 3 [default = true]; + optional int32 limit = 4 [default = 100]; + optional bool keys_only = 5; +} + +message ListDocumentsRequest { + required ListDocumentsParams params = 1; + + optional bytes app_id = 2; +} + +message ListDocumentsResponse { + required RequestStatus status = 1; + + repeated Document document = 2; +} + +message ListIndexesParams { + optional bool fetch_schema = 1; + optional int32 limit = 2 [default = 20]; + optional string namespace = 3; + optional string start_index_name = 4; + optional bool include_start_index = 5 [default = true]; + optional string index_name_prefix = 6; + optional int32 offset = 7; + optional IndexSpec.Source source = 8 [default = SEARCH]; +} + +message ListIndexesRequest { + required ListIndexesParams params = 1; + + optional bytes app_id = 3; +} + +message ListIndexesResponse { + required RequestStatus status = 1; + repeated IndexMetadata index_metadata = 2; +} + +message DeleteSchemaParams { + optional IndexSpec.Source source = 1 [default = SEARCH]; + repeated IndexSpec index_spec = 2; +} + +message DeleteSchemaRequest { + required DeleteSchemaParams params = 1; + + optional bytes app_id = 3; +} + +message DeleteSchemaResponse { + repeated RequestStatus status = 1; +} + +message SortSpec { + required string sort_expression = 1; + optional bool sort_descending = 2 [default = true]; + optional string default_value_text = 4; + optional double default_value_numeric = 5; +} + +message ScorerSpec { + enum Scorer { + RESCORING_MATCH_SCORER = 0; + MATCH_SCORER = 2; + } + optional Scorer scorer = 1 [default = MATCH_SCORER]; + + optional int32 limit = 2 [default = 1000]; + optional string match_scorer_parameters = 9; +} + +message FieldSpec { + repeated string name = 1; + + repeated group Expression = 2 { + required string name = 3; + required string expression = 4; + } +} + +message FacetRange { + optional string name = 1; + optional string start = 2; + optional string end = 3; +} + +message FacetRequestParam { + optional int32 value_limit = 1; + repeated FacetRange range = 2; + repeated string value_constraint = 3; +} + +message FacetAutoDetectParam { + optional int32 value_limit = 1 [default = 10]; +} + +message FacetRequest { + required string name = 1; + optional FacetRequestParam params = 2; +} + +message FacetRefinement { + required string name = 1; + optional string value = 2; + + message Range { + optional string start = 1; + optional string end = 2; + } + optional Range range = 3; +} + +message SearchParams { + required IndexSpec index_spec = 1; + required string query = 2; + optional string cursor = 4; + optional int32 offset = 11; + + enum CursorType { + NONE = 0; + SINGLE = 1; + PER_RESULT = 2; + } + optional CursorType cursor_type = 5 [default = NONE]; + + optional int32 limit = 6 [default = 20]; + optional int32 matched_count_accuracy = 7; + repeated SortSpec sort_spec = 8; + optional ScorerSpec scorer_spec = 9; + optional FieldSpec field_spec = 10; + optional bool keys_only = 12; + + enum ParsingMode { + STRICT = 0; + RELAXED = 1; + } + optional ParsingMode parsing_mode = 13 [default = STRICT]; + + optional int32 auto_discover_facet_count = 15 [default = 0]; + repeated FacetRequest include_facet = 16; + repeated FacetRefinement facet_refinement = 17; + optional FacetAutoDetectParam facet_auto_detect_param = 18; + optional int32 facet_depth = 19 [default=1000]; +} + +message SearchRequest { + required SearchParams params = 1; + + optional bytes app_id = 3; +} + +message FacetResultValue { + required string name = 1; + required int32 count = 2; + required FacetRefinement refinement = 3; +} + +message FacetResult { + required string name = 1; + repeated FacetResultValue value = 2; +} + +message SearchResult { + required Document document = 1; + repeated Field expression = 4; + repeated double score = 2; + optional string cursor = 3; +} + +message SearchResponse { + repeated SearchResult result = 1; + required int64 matched_count = 2; + required RequestStatus status = 3; + optional string cursor = 4; + repeated FacetResult facet_result = 5; + + extensions 1000 to 9999; +} diff --git a/vendor/google.golang.org/appengine/internal/socket/socket_service.pb.go b/vendor/google.golang.org/appengine/internal/socket/socket_service.pb.go new file mode 100644 index 000000000..60628ec9b --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/socket/socket_service.pb.go @@ -0,0 +1,1858 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/socket/socket_service.proto +// DO NOT EDIT! + +/* +Package socket is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/socket/socket_service.proto + +It has these top-level messages: + RemoteSocketServiceError + AddressPort + CreateSocketRequest + CreateSocketReply + BindRequest + BindReply + GetSocketNameRequest + GetSocketNameReply + GetPeerNameRequest + GetPeerNameReply + SocketOption + SetSocketOptionsRequest + SetSocketOptionsReply + GetSocketOptionsRequest + GetSocketOptionsReply + ConnectRequest + ConnectReply + ListenRequest + ListenReply + AcceptRequest + AcceptReply + ShutDownRequest + ShutDownReply + CloseRequest + CloseReply + SendRequest + SendReply + ReceiveRequest + ReceiveReply + PollEvent + PollRequest + PollReply + ResolveRequest + ResolveReply +*/ +package socket + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type RemoteSocketServiceError_ErrorCode int32 + +const ( + RemoteSocketServiceError_SYSTEM_ERROR RemoteSocketServiceError_ErrorCode = 1 + RemoteSocketServiceError_GAI_ERROR RemoteSocketServiceError_ErrorCode = 2 + RemoteSocketServiceError_FAILURE RemoteSocketServiceError_ErrorCode = 4 + RemoteSocketServiceError_PERMISSION_DENIED RemoteSocketServiceError_ErrorCode = 5 + RemoteSocketServiceError_INVALID_REQUEST RemoteSocketServiceError_ErrorCode = 6 + RemoteSocketServiceError_SOCKET_CLOSED RemoteSocketServiceError_ErrorCode = 7 +) + +var RemoteSocketServiceError_ErrorCode_name = map[int32]string{ + 1: "SYSTEM_ERROR", + 2: "GAI_ERROR", + 4: "FAILURE", + 5: "PERMISSION_DENIED", + 6: "INVALID_REQUEST", + 7: "SOCKET_CLOSED", +} +var RemoteSocketServiceError_ErrorCode_value = map[string]int32{ + "SYSTEM_ERROR": 1, + "GAI_ERROR": 2, + "FAILURE": 4, + "PERMISSION_DENIED": 5, + "INVALID_REQUEST": 6, + "SOCKET_CLOSED": 7, +} + +func (x RemoteSocketServiceError_ErrorCode) Enum() *RemoteSocketServiceError_ErrorCode { + p := new(RemoteSocketServiceError_ErrorCode) + *p = x + return p +} +func (x RemoteSocketServiceError_ErrorCode) String() string { + return proto.EnumName(RemoteSocketServiceError_ErrorCode_name, int32(x)) +} +func (x *RemoteSocketServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RemoteSocketServiceError_ErrorCode_value, data, "RemoteSocketServiceError_ErrorCode") + if err != nil { + return err + } + *x = RemoteSocketServiceError_ErrorCode(value) + return nil +} + +type RemoteSocketServiceError_SystemError int32 + +const ( + RemoteSocketServiceError_SYS_SUCCESS RemoteSocketServiceError_SystemError = 0 + RemoteSocketServiceError_SYS_EPERM RemoteSocketServiceError_SystemError = 1 + RemoteSocketServiceError_SYS_ENOENT RemoteSocketServiceError_SystemError = 2 + RemoteSocketServiceError_SYS_ESRCH RemoteSocketServiceError_SystemError = 3 + RemoteSocketServiceError_SYS_EINTR RemoteSocketServiceError_SystemError = 4 + RemoteSocketServiceError_SYS_EIO RemoteSocketServiceError_SystemError = 5 + RemoteSocketServiceError_SYS_ENXIO RemoteSocketServiceError_SystemError = 6 + RemoteSocketServiceError_SYS_E2BIG RemoteSocketServiceError_SystemError = 7 + RemoteSocketServiceError_SYS_ENOEXEC RemoteSocketServiceError_SystemError = 8 + RemoteSocketServiceError_SYS_EBADF RemoteSocketServiceError_SystemError = 9 + RemoteSocketServiceError_SYS_ECHILD RemoteSocketServiceError_SystemError = 10 + RemoteSocketServiceError_SYS_EAGAIN RemoteSocketServiceError_SystemError = 11 + RemoteSocketServiceError_SYS_EWOULDBLOCK RemoteSocketServiceError_SystemError = 11 + RemoteSocketServiceError_SYS_ENOMEM RemoteSocketServiceError_SystemError = 12 + RemoteSocketServiceError_SYS_EACCES RemoteSocketServiceError_SystemError = 13 + RemoteSocketServiceError_SYS_EFAULT RemoteSocketServiceError_SystemError = 14 + RemoteSocketServiceError_SYS_ENOTBLK RemoteSocketServiceError_SystemError = 15 + RemoteSocketServiceError_SYS_EBUSY RemoteSocketServiceError_SystemError = 16 + RemoteSocketServiceError_SYS_EEXIST RemoteSocketServiceError_SystemError = 17 + RemoteSocketServiceError_SYS_EXDEV RemoteSocketServiceError_SystemError = 18 + RemoteSocketServiceError_SYS_ENODEV RemoteSocketServiceError_SystemError = 19 + RemoteSocketServiceError_SYS_ENOTDIR RemoteSocketServiceError_SystemError = 20 + RemoteSocketServiceError_SYS_EISDIR RemoteSocketServiceError_SystemError = 21 + RemoteSocketServiceError_SYS_EINVAL RemoteSocketServiceError_SystemError = 22 + RemoteSocketServiceError_SYS_ENFILE RemoteSocketServiceError_SystemError = 23 + RemoteSocketServiceError_SYS_EMFILE RemoteSocketServiceError_SystemError = 24 + RemoteSocketServiceError_SYS_ENOTTY RemoteSocketServiceError_SystemError = 25 + RemoteSocketServiceError_SYS_ETXTBSY RemoteSocketServiceError_SystemError = 26 + RemoteSocketServiceError_SYS_EFBIG RemoteSocketServiceError_SystemError = 27 + RemoteSocketServiceError_SYS_ENOSPC RemoteSocketServiceError_SystemError = 28 + RemoteSocketServiceError_SYS_ESPIPE RemoteSocketServiceError_SystemError = 29 + RemoteSocketServiceError_SYS_EROFS RemoteSocketServiceError_SystemError = 30 + RemoteSocketServiceError_SYS_EMLINK RemoteSocketServiceError_SystemError = 31 + RemoteSocketServiceError_SYS_EPIPE RemoteSocketServiceError_SystemError = 32 + RemoteSocketServiceError_SYS_EDOM RemoteSocketServiceError_SystemError = 33 + RemoteSocketServiceError_SYS_ERANGE RemoteSocketServiceError_SystemError = 34 + RemoteSocketServiceError_SYS_EDEADLK RemoteSocketServiceError_SystemError = 35 + RemoteSocketServiceError_SYS_EDEADLOCK RemoteSocketServiceError_SystemError = 35 + RemoteSocketServiceError_SYS_ENAMETOOLONG RemoteSocketServiceError_SystemError = 36 + RemoteSocketServiceError_SYS_ENOLCK RemoteSocketServiceError_SystemError = 37 + RemoteSocketServiceError_SYS_ENOSYS RemoteSocketServiceError_SystemError = 38 + RemoteSocketServiceError_SYS_ENOTEMPTY RemoteSocketServiceError_SystemError = 39 + RemoteSocketServiceError_SYS_ELOOP RemoteSocketServiceError_SystemError = 40 + RemoteSocketServiceError_SYS_ENOMSG RemoteSocketServiceError_SystemError = 42 + RemoteSocketServiceError_SYS_EIDRM RemoteSocketServiceError_SystemError = 43 + RemoteSocketServiceError_SYS_ECHRNG RemoteSocketServiceError_SystemError = 44 + RemoteSocketServiceError_SYS_EL2NSYNC RemoteSocketServiceError_SystemError = 45 + RemoteSocketServiceError_SYS_EL3HLT RemoteSocketServiceError_SystemError = 46 + RemoteSocketServiceError_SYS_EL3RST RemoteSocketServiceError_SystemError = 47 + RemoteSocketServiceError_SYS_ELNRNG RemoteSocketServiceError_SystemError = 48 + RemoteSocketServiceError_SYS_EUNATCH RemoteSocketServiceError_SystemError = 49 + RemoteSocketServiceError_SYS_ENOCSI RemoteSocketServiceError_SystemError = 50 + RemoteSocketServiceError_SYS_EL2HLT RemoteSocketServiceError_SystemError = 51 + RemoteSocketServiceError_SYS_EBADE RemoteSocketServiceError_SystemError = 52 + RemoteSocketServiceError_SYS_EBADR RemoteSocketServiceError_SystemError = 53 + RemoteSocketServiceError_SYS_EXFULL RemoteSocketServiceError_SystemError = 54 + RemoteSocketServiceError_SYS_ENOANO RemoteSocketServiceError_SystemError = 55 + RemoteSocketServiceError_SYS_EBADRQC RemoteSocketServiceError_SystemError = 56 + RemoteSocketServiceError_SYS_EBADSLT RemoteSocketServiceError_SystemError = 57 + RemoteSocketServiceError_SYS_EBFONT RemoteSocketServiceError_SystemError = 59 + RemoteSocketServiceError_SYS_ENOSTR RemoteSocketServiceError_SystemError = 60 + RemoteSocketServiceError_SYS_ENODATA RemoteSocketServiceError_SystemError = 61 + RemoteSocketServiceError_SYS_ETIME RemoteSocketServiceError_SystemError = 62 + RemoteSocketServiceError_SYS_ENOSR RemoteSocketServiceError_SystemError = 63 + RemoteSocketServiceError_SYS_ENONET RemoteSocketServiceError_SystemError = 64 + RemoteSocketServiceError_SYS_ENOPKG RemoteSocketServiceError_SystemError = 65 + RemoteSocketServiceError_SYS_EREMOTE RemoteSocketServiceError_SystemError = 66 + RemoteSocketServiceError_SYS_ENOLINK RemoteSocketServiceError_SystemError = 67 + RemoteSocketServiceError_SYS_EADV RemoteSocketServiceError_SystemError = 68 + RemoteSocketServiceError_SYS_ESRMNT RemoteSocketServiceError_SystemError = 69 + RemoteSocketServiceError_SYS_ECOMM RemoteSocketServiceError_SystemError = 70 + RemoteSocketServiceError_SYS_EPROTO RemoteSocketServiceError_SystemError = 71 + RemoteSocketServiceError_SYS_EMULTIHOP RemoteSocketServiceError_SystemError = 72 + RemoteSocketServiceError_SYS_EDOTDOT RemoteSocketServiceError_SystemError = 73 + RemoteSocketServiceError_SYS_EBADMSG RemoteSocketServiceError_SystemError = 74 + RemoteSocketServiceError_SYS_EOVERFLOW RemoteSocketServiceError_SystemError = 75 + RemoteSocketServiceError_SYS_ENOTUNIQ RemoteSocketServiceError_SystemError = 76 + RemoteSocketServiceError_SYS_EBADFD RemoteSocketServiceError_SystemError = 77 + RemoteSocketServiceError_SYS_EREMCHG RemoteSocketServiceError_SystemError = 78 + RemoteSocketServiceError_SYS_ELIBACC RemoteSocketServiceError_SystemError = 79 + RemoteSocketServiceError_SYS_ELIBBAD RemoteSocketServiceError_SystemError = 80 + RemoteSocketServiceError_SYS_ELIBSCN RemoteSocketServiceError_SystemError = 81 + RemoteSocketServiceError_SYS_ELIBMAX RemoteSocketServiceError_SystemError = 82 + RemoteSocketServiceError_SYS_ELIBEXEC RemoteSocketServiceError_SystemError = 83 + RemoteSocketServiceError_SYS_EILSEQ RemoteSocketServiceError_SystemError = 84 + RemoteSocketServiceError_SYS_ERESTART RemoteSocketServiceError_SystemError = 85 + RemoteSocketServiceError_SYS_ESTRPIPE RemoteSocketServiceError_SystemError = 86 + RemoteSocketServiceError_SYS_EUSERS RemoteSocketServiceError_SystemError = 87 + RemoteSocketServiceError_SYS_ENOTSOCK RemoteSocketServiceError_SystemError = 88 + RemoteSocketServiceError_SYS_EDESTADDRREQ RemoteSocketServiceError_SystemError = 89 + RemoteSocketServiceError_SYS_EMSGSIZE RemoteSocketServiceError_SystemError = 90 + RemoteSocketServiceError_SYS_EPROTOTYPE RemoteSocketServiceError_SystemError = 91 + RemoteSocketServiceError_SYS_ENOPROTOOPT RemoteSocketServiceError_SystemError = 92 + RemoteSocketServiceError_SYS_EPROTONOSUPPORT RemoteSocketServiceError_SystemError = 93 + RemoteSocketServiceError_SYS_ESOCKTNOSUPPORT RemoteSocketServiceError_SystemError = 94 + RemoteSocketServiceError_SYS_EOPNOTSUPP RemoteSocketServiceError_SystemError = 95 + RemoteSocketServiceError_SYS_ENOTSUP RemoteSocketServiceError_SystemError = 95 + RemoteSocketServiceError_SYS_EPFNOSUPPORT RemoteSocketServiceError_SystemError = 96 + RemoteSocketServiceError_SYS_EAFNOSUPPORT RemoteSocketServiceError_SystemError = 97 + RemoteSocketServiceError_SYS_EADDRINUSE RemoteSocketServiceError_SystemError = 98 + RemoteSocketServiceError_SYS_EADDRNOTAVAIL RemoteSocketServiceError_SystemError = 99 + RemoteSocketServiceError_SYS_ENETDOWN RemoteSocketServiceError_SystemError = 100 + RemoteSocketServiceError_SYS_ENETUNREACH RemoteSocketServiceError_SystemError = 101 + RemoteSocketServiceError_SYS_ENETRESET RemoteSocketServiceError_SystemError = 102 + RemoteSocketServiceError_SYS_ECONNABORTED RemoteSocketServiceError_SystemError = 103 + RemoteSocketServiceError_SYS_ECONNRESET RemoteSocketServiceError_SystemError = 104 + RemoteSocketServiceError_SYS_ENOBUFS RemoteSocketServiceError_SystemError = 105 + RemoteSocketServiceError_SYS_EISCONN RemoteSocketServiceError_SystemError = 106 + RemoteSocketServiceError_SYS_ENOTCONN RemoteSocketServiceError_SystemError = 107 + RemoteSocketServiceError_SYS_ESHUTDOWN RemoteSocketServiceError_SystemError = 108 + RemoteSocketServiceError_SYS_ETOOMANYREFS RemoteSocketServiceError_SystemError = 109 + RemoteSocketServiceError_SYS_ETIMEDOUT RemoteSocketServiceError_SystemError = 110 + RemoteSocketServiceError_SYS_ECONNREFUSED RemoteSocketServiceError_SystemError = 111 + RemoteSocketServiceError_SYS_EHOSTDOWN RemoteSocketServiceError_SystemError = 112 + RemoteSocketServiceError_SYS_EHOSTUNREACH RemoteSocketServiceError_SystemError = 113 + RemoteSocketServiceError_SYS_EALREADY RemoteSocketServiceError_SystemError = 114 + RemoteSocketServiceError_SYS_EINPROGRESS RemoteSocketServiceError_SystemError = 115 + RemoteSocketServiceError_SYS_ESTALE RemoteSocketServiceError_SystemError = 116 + RemoteSocketServiceError_SYS_EUCLEAN RemoteSocketServiceError_SystemError = 117 + RemoteSocketServiceError_SYS_ENOTNAM RemoteSocketServiceError_SystemError = 118 + RemoteSocketServiceError_SYS_ENAVAIL RemoteSocketServiceError_SystemError = 119 + RemoteSocketServiceError_SYS_EISNAM RemoteSocketServiceError_SystemError = 120 + RemoteSocketServiceError_SYS_EREMOTEIO RemoteSocketServiceError_SystemError = 121 + RemoteSocketServiceError_SYS_EDQUOT RemoteSocketServiceError_SystemError = 122 + RemoteSocketServiceError_SYS_ENOMEDIUM RemoteSocketServiceError_SystemError = 123 + RemoteSocketServiceError_SYS_EMEDIUMTYPE RemoteSocketServiceError_SystemError = 124 + RemoteSocketServiceError_SYS_ECANCELED RemoteSocketServiceError_SystemError = 125 + RemoteSocketServiceError_SYS_ENOKEY RemoteSocketServiceError_SystemError = 126 + RemoteSocketServiceError_SYS_EKEYEXPIRED RemoteSocketServiceError_SystemError = 127 + RemoteSocketServiceError_SYS_EKEYREVOKED RemoteSocketServiceError_SystemError = 128 + RemoteSocketServiceError_SYS_EKEYREJECTED RemoteSocketServiceError_SystemError = 129 + RemoteSocketServiceError_SYS_EOWNERDEAD RemoteSocketServiceError_SystemError = 130 + RemoteSocketServiceError_SYS_ENOTRECOVERABLE RemoteSocketServiceError_SystemError = 131 + RemoteSocketServiceError_SYS_ERFKILL RemoteSocketServiceError_SystemError = 132 +) + +var RemoteSocketServiceError_SystemError_name = map[int32]string{ + 0: "SYS_SUCCESS", + 1: "SYS_EPERM", + 2: "SYS_ENOENT", + 3: "SYS_ESRCH", + 4: "SYS_EINTR", + 5: "SYS_EIO", + 6: "SYS_ENXIO", + 7: "SYS_E2BIG", + 8: "SYS_ENOEXEC", + 9: "SYS_EBADF", + 10: "SYS_ECHILD", + 11: "SYS_EAGAIN", + // Duplicate value: 11: "SYS_EWOULDBLOCK", + 12: "SYS_ENOMEM", + 13: "SYS_EACCES", + 14: "SYS_EFAULT", + 15: "SYS_ENOTBLK", + 16: "SYS_EBUSY", + 17: "SYS_EEXIST", + 18: "SYS_EXDEV", + 19: "SYS_ENODEV", + 20: "SYS_ENOTDIR", + 21: "SYS_EISDIR", + 22: "SYS_EINVAL", + 23: "SYS_ENFILE", + 24: "SYS_EMFILE", + 25: "SYS_ENOTTY", + 26: "SYS_ETXTBSY", + 27: "SYS_EFBIG", + 28: "SYS_ENOSPC", + 29: "SYS_ESPIPE", + 30: "SYS_EROFS", + 31: "SYS_EMLINK", + 32: "SYS_EPIPE", + 33: "SYS_EDOM", + 34: "SYS_ERANGE", + 35: "SYS_EDEADLK", + // Duplicate value: 35: "SYS_EDEADLOCK", + 36: "SYS_ENAMETOOLONG", + 37: "SYS_ENOLCK", + 38: "SYS_ENOSYS", + 39: "SYS_ENOTEMPTY", + 40: "SYS_ELOOP", + 42: "SYS_ENOMSG", + 43: "SYS_EIDRM", + 44: "SYS_ECHRNG", + 45: "SYS_EL2NSYNC", + 46: "SYS_EL3HLT", + 47: "SYS_EL3RST", + 48: "SYS_ELNRNG", + 49: "SYS_EUNATCH", + 50: "SYS_ENOCSI", + 51: "SYS_EL2HLT", + 52: "SYS_EBADE", + 53: "SYS_EBADR", + 54: "SYS_EXFULL", + 55: "SYS_ENOANO", + 56: "SYS_EBADRQC", + 57: "SYS_EBADSLT", + 59: "SYS_EBFONT", + 60: "SYS_ENOSTR", + 61: "SYS_ENODATA", + 62: "SYS_ETIME", + 63: "SYS_ENOSR", + 64: "SYS_ENONET", + 65: "SYS_ENOPKG", + 66: "SYS_EREMOTE", + 67: "SYS_ENOLINK", + 68: "SYS_EADV", + 69: "SYS_ESRMNT", + 70: "SYS_ECOMM", + 71: "SYS_EPROTO", + 72: "SYS_EMULTIHOP", + 73: "SYS_EDOTDOT", + 74: "SYS_EBADMSG", + 75: "SYS_EOVERFLOW", + 76: "SYS_ENOTUNIQ", + 77: "SYS_EBADFD", + 78: "SYS_EREMCHG", + 79: "SYS_ELIBACC", + 80: "SYS_ELIBBAD", + 81: "SYS_ELIBSCN", + 82: "SYS_ELIBMAX", + 83: "SYS_ELIBEXEC", + 84: "SYS_EILSEQ", + 85: "SYS_ERESTART", + 86: "SYS_ESTRPIPE", + 87: "SYS_EUSERS", + 88: "SYS_ENOTSOCK", + 89: "SYS_EDESTADDRREQ", + 90: "SYS_EMSGSIZE", + 91: "SYS_EPROTOTYPE", + 92: "SYS_ENOPROTOOPT", + 93: "SYS_EPROTONOSUPPORT", + 94: "SYS_ESOCKTNOSUPPORT", + 95: "SYS_EOPNOTSUPP", + // Duplicate value: 95: "SYS_ENOTSUP", + 96: "SYS_EPFNOSUPPORT", + 97: "SYS_EAFNOSUPPORT", + 98: "SYS_EADDRINUSE", + 99: "SYS_EADDRNOTAVAIL", + 100: "SYS_ENETDOWN", + 101: "SYS_ENETUNREACH", + 102: "SYS_ENETRESET", + 103: "SYS_ECONNABORTED", + 104: "SYS_ECONNRESET", + 105: "SYS_ENOBUFS", + 106: "SYS_EISCONN", + 107: "SYS_ENOTCONN", + 108: "SYS_ESHUTDOWN", + 109: "SYS_ETOOMANYREFS", + 110: "SYS_ETIMEDOUT", + 111: "SYS_ECONNREFUSED", + 112: "SYS_EHOSTDOWN", + 113: "SYS_EHOSTUNREACH", + 114: "SYS_EALREADY", + 115: "SYS_EINPROGRESS", + 116: "SYS_ESTALE", + 117: "SYS_EUCLEAN", + 118: "SYS_ENOTNAM", + 119: "SYS_ENAVAIL", + 120: "SYS_EISNAM", + 121: "SYS_EREMOTEIO", + 122: "SYS_EDQUOT", + 123: "SYS_ENOMEDIUM", + 124: "SYS_EMEDIUMTYPE", + 125: "SYS_ECANCELED", + 126: "SYS_ENOKEY", + 127: "SYS_EKEYEXPIRED", + 128: "SYS_EKEYREVOKED", + 129: "SYS_EKEYREJECTED", + 130: "SYS_EOWNERDEAD", + 131: "SYS_ENOTRECOVERABLE", + 132: "SYS_ERFKILL", +} +var RemoteSocketServiceError_SystemError_value = map[string]int32{ + "SYS_SUCCESS": 0, + "SYS_EPERM": 1, + "SYS_ENOENT": 2, + "SYS_ESRCH": 3, + "SYS_EINTR": 4, + "SYS_EIO": 5, + "SYS_ENXIO": 6, + "SYS_E2BIG": 7, + "SYS_ENOEXEC": 8, + "SYS_EBADF": 9, + "SYS_ECHILD": 10, + "SYS_EAGAIN": 11, + "SYS_EWOULDBLOCK": 11, + "SYS_ENOMEM": 12, + "SYS_EACCES": 13, + "SYS_EFAULT": 14, + "SYS_ENOTBLK": 15, + "SYS_EBUSY": 16, + "SYS_EEXIST": 17, + "SYS_EXDEV": 18, + "SYS_ENODEV": 19, + "SYS_ENOTDIR": 20, + "SYS_EISDIR": 21, + "SYS_EINVAL": 22, + "SYS_ENFILE": 23, + "SYS_EMFILE": 24, + "SYS_ENOTTY": 25, + "SYS_ETXTBSY": 26, + "SYS_EFBIG": 27, + "SYS_ENOSPC": 28, + "SYS_ESPIPE": 29, + "SYS_EROFS": 30, + "SYS_EMLINK": 31, + "SYS_EPIPE": 32, + "SYS_EDOM": 33, + "SYS_ERANGE": 34, + "SYS_EDEADLK": 35, + "SYS_EDEADLOCK": 35, + "SYS_ENAMETOOLONG": 36, + "SYS_ENOLCK": 37, + "SYS_ENOSYS": 38, + "SYS_ENOTEMPTY": 39, + "SYS_ELOOP": 40, + "SYS_ENOMSG": 42, + "SYS_EIDRM": 43, + "SYS_ECHRNG": 44, + "SYS_EL2NSYNC": 45, + "SYS_EL3HLT": 46, + "SYS_EL3RST": 47, + "SYS_ELNRNG": 48, + "SYS_EUNATCH": 49, + "SYS_ENOCSI": 50, + "SYS_EL2HLT": 51, + "SYS_EBADE": 52, + "SYS_EBADR": 53, + "SYS_EXFULL": 54, + "SYS_ENOANO": 55, + "SYS_EBADRQC": 56, + "SYS_EBADSLT": 57, + "SYS_EBFONT": 59, + "SYS_ENOSTR": 60, + "SYS_ENODATA": 61, + "SYS_ETIME": 62, + "SYS_ENOSR": 63, + "SYS_ENONET": 64, + "SYS_ENOPKG": 65, + "SYS_EREMOTE": 66, + "SYS_ENOLINK": 67, + "SYS_EADV": 68, + "SYS_ESRMNT": 69, + "SYS_ECOMM": 70, + "SYS_EPROTO": 71, + "SYS_EMULTIHOP": 72, + "SYS_EDOTDOT": 73, + "SYS_EBADMSG": 74, + "SYS_EOVERFLOW": 75, + "SYS_ENOTUNIQ": 76, + "SYS_EBADFD": 77, + "SYS_EREMCHG": 78, + "SYS_ELIBACC": 79, + "SYS_ELIBBAD": 80, + "SYS_ELIBSCN": 81, + "SYS_ELIBMAX": 82, + "SYS_ELIBEXEC": 83, + "SYS_EILSEQ": 84, + "SYS_ERESTART": 85, + "SYS_ESTRPIPE": 86, + "SYS_EUSERS": 87, + "SYS_ENOTSOCK": 88, + "SYS_EDESTADDRREQ": 89, + "SYS_EMSGSIZE": 90, + "SYS_EPROTOTYPE": 91, + "SYS_ENOPROTOOPT": 92, + "SYS_EPROTONOSUPPORT": 93, + "SYS_ESOCKTNOSUPPORT": 94, + "SYS_EOPNOTSUPP": 95, + "SYS_ENOTSUP": 95, + "SYS_EPFNOSUPPORT": 96, + "SYS_EAFNOSUPPORT": 97, + "SYS_EADDRINUSE": 98, + "SYS_EADDRNOTAVAIL": 99, + "SYS_ENETDOWN": 100, + "SYS_ENETUNREACH": 101, + "SYS_ENETRESET": 102, + "SYS_ECONNABORTED": 103, + "SYS_ECONNRESET": 104, + "SYS_ENOBUFS": 105, + "SYS_EISCONN": 106, + "SYS_ENOTCONN": 107, + "SYS_ESHUTDOWN": 108, + "SYS_ETOOMANYREFS": 109, + "SYS_ETIMEDOUT": 110, + "SYS_ECONNREFUSED": 111, + "SYS_EHOSTDOWN": 112, + "SYS_EHOSTUNREACH": 113, + "SYS_EALREADY": 114, + "SYS_EINPROGRESS": 115, + "SYS_ESTALE": 116, + "SYS_EUCLEAN": 117, + "SYS_ENOTNAM": 118, + "SYS_ENAVAIL": 119, + "SYS_EISNAM": 120, + "SYS_EREMOTEIO": 121, + "SYS_EDQUOT": 122, + "SYS_ENOMEDIUM": 123, + "SYS_EMEDIUMTYPE": 124, + "SYS_ECANCELED": 125, + "SYS_ENOKEY": 126, + "SYS_EKEYEXPIRED": 127, + "SYS_EKEYREVOKED": 128, + "SYS_EKEYREJECTED": 129, + "SYS_EOWNERDEAD": 130, + "SYS_ENOTRECOVERABLE": 131, + "SYS_ERFKILL": 132, +} + +func (x RemoteSocketServiceError_SystemError) Enum() *RemoteSocketServiceError_SystemError { + p := new(RemoteSocketServiceError_SystemError) + *p = x + return p +} +func (x RemoteSocketServiceError_SystemError) String() string { + return proto.EnumName(RemoteSocketServiceError_SystemError_name, int32(x)) +} +func (x *RemoteSocketServiceError_SystemError) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RemoteSocketServiceError_SystemError_value, data, "RemoteSocketServiceError_SystemError") + if err != nil { + return err + } + *x = RemoteSocketServiceError_SystemError(value) + return nil +} + +type CreateSocketRequest_SocketFamily int32 + +const ( + CreateSocketRequest_IPv4 CreateSocketRequest_SocketFamily = 1 + CreateSocketRequest_IPv6 CreateSocketRequest_SocketFamily = 2 +) + +var CreateSocketRequest_SocketFamily_name = map[int32]string{ + 1: "IPv4", + 2: "IPv6", +} +var CreateSocketRequest_SocketFamily_value = map[string]int32{ + "IPv4": 1, + "IPv6": 2, +} + +func (x CreateSocketRequest_SocketFamily) Enum() *CreateSocketRequest_SocketFamily { + p := new(CreateSocketRequest_SocketFamily) + *p = x + return p +} +func (x CreateSocketRequest_SocketFamily) String() string { + return proto.EnumName(CreateSocketRequest_SocketFamily_name, int32(x)) +} +func (x *CreateSocketRequest_SocketFamily) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CreateSocketRequest_SocketFamily_value, data, "CreateSocketRequest_SocketFamily") + if err != nil { + return err + } + *x = CreateSocketRequest_SocketFamily(value) + return nil +} + +type CreateSocketRequest_SocketProtocol int32 + +const ( + CreateSocketRequest_TCP CreateSocketRequest_SocketProtocol = 1 + CreateSocketRequest_UDP CreateSocketRequest_SocketProtocol = 2 +) + +var CreateSocketRequest_SocketProtocol_name = map[int32]string{ + 1: "TCP", + 2: "UDP", +} +var CreateSocketRequest_SocketProtocol_value = map[string]int32{ + "TCP": 1, + "UDP": 2, +} + +func (x CreateSocketRequest_SocketProtocol) Enum() *CreateSocketRequest_SocketProtocol { + p := new(CreateSocketRequest_SocketProtocol) + *p = x + return p +} +func (x CreateSocketRequest_SocketProtocol) String() string { + return proto.EnumName(CreateSocketRequest_SocketProtocol_name, int32(x)) +} +func (x *CreateSocketRequest_SocketProtocol) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CreateSocketRequest_SocketProtocol_value, data, "CreateSocketRequest_SocketProtocol") + if err != nil { + return err + } + *x = CreateSocketRequest_SocketProtocol(value) + return nil +} + +type SocketOption_SocketOptionLevel int32 + +const ( + SocketOption_SOCKET_SOL_IP SocketOption_SocketOptionLevel = 0 + SocketOption_SOCKET_SOL_SOCKET SocketOption_SocketOptionLevel = 1 + SocketOption_SOCKET_SOL_TCP SocketOption_SocketOptionLevel = 6 + SocketOption_SOCKET_SOL_UDP SocketOption_SocketOptionLevel = 17 +) + +var SocketOption_SocketOptionLevel_name = map[int32]string{ + 0: "SOCKET_SOL_IP", + 1: "SOCKET_SOL_SOCKET", + 6: "SOCKET_SOL_TCP", + 17: "SOCKET_SOL_UDP", +} +var SocketOption_SocketOptionLevel_value = map[string]int32{ + "SOCKET_SOL_IP": 0, + "SOCKET_SOL_SOCKET": 1, + "SOCKET_SOL_TCP": 6, + "SOCKET_SOL_UDP": 17, +} + +func (x SocketOption_SocketOptionLevel) Enum() *SocketOption_SocketOptionLevel { + p := new(SocketOption_SocketOptionLevel) + *p = x + return p +} +func (x SocketOption_SocketOptionLevel) String() string { + return proto.EnumName(SocketOption_SocketOptionLevel_name, int32(x)) +} +func (x *SocketOption_SocketOptionLevel) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SocketOption_SocketOptionLevel_value, data, "SocketOption_SocketOptionLevel") + if err != nil { + return err + } + *x = SocketOption_SocketOptionLevel(value) + return nil +} + +type SocketOption_SocketOptionName int32 + +const ( + SocketOption_SOCKET_SO_DEBUG SocketOption_SocketOptionName = 1 + SocketOption_SOCKET_SO_REUSEADDR SocketOption_SocketOptionName = 2 + SocketOption_SOCKET_SO_TYPE SocketOption_SocketOptionName = 3 + SocketOption_SOCKET_SO_ERROR SocketOption_SocketOptionName = 4 + SocketOption_SOCKET_SO_DONTROUTE SocketOption_SocketOptionName = 5 + SocketOption_SOCKET_SO_BROADCAST SocketOption_SocketOptionName = 6 + SocketOption_SOCKET_SO_SNDBUF SocketOption_SocketOptionName = 7 + SocketOption_SOCKET_SO_RCVBUF SocketOption_SocketOptionName = 8 + SocketOption_SOCKET_SO_KEEPALIVE SocketOption_SocketOptionName = 9 + SocketOption_SOCKET_SO_OOBINLINE SocketOption_SocketOptionName = 10 + SocketOption_SOCKET_SO_LINGER SocketOption_SocketOptionName = 13 + SocketOption_SOCKET_SO_RCVTIMEO SocketOption_SocketOptionName = 20 + SocketOption_SOCKET_SO_SNDTIMEO SocketOption_SocketOptionName = 21 + SocketOption_SOCKET_IP_TOS SocketOption_SocketOptionName = 1 + SocketOption_SOCKET_IP_TTL SocketOption_SocketOptionName = 2 + SocketOption_SOCKET_IP_HDRINCL SocketOption_SocketOptionName = 3 + SocketOption_SOCKET_IP_OPTIONS SocketOption_SocketOptionName = 4 + SocketOption_SOCKET_TCP_NODELAY SocketOption_SocketOptionName = 1 + SocketOption_SOCKET_TCP_MAXSEG SocketOption_SocketOptionName = 2 + SocketOption_SOCKET_TCP_CORK SocketOption_SocketOptionName = 3 + SocketOption_SOCKET_TCP_KEEPIDLE SocketOption_SocketOptionName = 4 + SocketOption_SOCKET_TCP_KEEPINTVL SocketOption_SocketOptionName = 5 + SocketOption_SOCKET_TCP_KEEPCNT SocketOption_SocketOptionName = 6 + SocketOption_SOCKET_TCP_SYNCNT SocketOption_SocketOptionName = 7 + SocketOption_SOCKET_TCP_LINGER2 SocketOption_SocketOptionName = 8 + SocketOption_SOCKET_TCP_DEFER_ACCEPT SocketOption_SocketOptionName = 9 + SocketOption_SOCKET_TCP_WINDOW_CLAMP SocketOption_SocketOptionName = 10 + SocketOption_SOCKET_TCP_INFO SocketOption_SocketOptionName = 11 + SocketOption_SOCKET_TCP_QUICKACK SocketOption_SocketOptionName = 12 +) + +var SocketOption_SocketOptionName_name = map[int32]string{ + 1: "SOCKET_SO_DEBUG", + 2: "SOCKET_SO_REUSEADDR", + 3: "SOCKET_SO_TYPE", + 4: "SOCKET_SO_ERROR", + 5: "SOCKET_SO_DONTROUTE", + 6: "SOCKET_SO_BROADCAST", + 7: "SOCKET_SO_SNDBUF", + 8: "SOCKET_SO_RCVBUF", + 9: "SOCKET_SO_KEEPALIVE", + 10: "SOCKET_SO_OOBINLINE", + 13: "SOCKET_SO_LINGER", + 20: "SOCKET_SO_RCVTIMEO", + 21: "SOCKET_SO_SNDTIMEO", + // Duplicate value: 1: "SOCKET_IP_TOS", + // Duplicate value: 2: "SOCKET_IP_TTL", + // Duplicate value: 3: "SOCKET_IP_HDRINCL", + // Duplicate value: 4: "SOCKET_IP_OPTIONS", + // Duplicate value: 1: "SOCKET_TCP_NODELAY", + // Duplicate value: 2: "SOCKET_TCP_MAXSEG", + // Duplicate value: 3: "SOCKET_TCP_CORK", + // Duplicate value: 4: "SOCKET_TCP_KEEPIDLE", + // Duplicate value: 5: "SOCKET_TCP_KEEPINTVL", + // Duplicate value: 6: "SOCKET_TCP_KEEPCNT", + // Duplicate value: 7: "SOCKET_TCP_SYNCNT", + // Duplicate value: 8: "SOCKET_TCP_LINGER2", + // Duplicate value: 9: "SOCKET_TCP_DEFER_ACCEPT", + // Duplicate value: 10: "SOCKET_TCP_WINDOW_CLAMP", + 11: "SOCKET_TCP_INFO", + 12: "SOCKET_TCP_QUICKACK", +} +var SocketOption_SocketOptionName_value = map[string]int32{ + "SOCKET_SO_DEBUG": 1, + "SOCKET_SO_REUSEADDR": 2, + "SOCKET_SO_TYPE": 3, + "SOCKET_SO_ERROR": 4, + "SOCKET_SO_DONTROUTE": 5, + "SOCKET_SO_BROADCAST": 6, + "SOCKET_SO_SNDBUF": 7, + "SOCKET_SO_RCVBUF": 8, + "SOCKET_SO_KEEPALIVE": 9, + "SOCKET_SO_OOBINLINE": 10, + "SOCKET_SO_LINGER": 13, + "SOCKET_SO_RCVTIMEO": 20, + "SOCKET_SO_SNDTIMEO": 21, + "SOCKET_IP_TOS": 1, + "SOCKET_IP_TTL": 2, + "SOCKET_IP_HDRINCL": 3, + "SOCKET_IP_OPTIONS": 4, + "SOCKET_TCP_NODELAY": 1, + "SOCKET_TCP_MAXSEG": 2, + "SOCKET_TCP_CORK": 3, + "SOCKET_TCP_KEEPIDLE": 4, + "SOCKET_TCP_KEEPINTVL": 5, + "SOCKET_TCP_KEEPCNT": 6, + "SOCKET_TCP_SYNCNT": 7, + "SOCKET_TCP_LINGER2": 8, + "SOCKET_TCP_DEFER_ACCEPT": 9, + "SOCKET_TCP_WINDOW_CLAMP": 10, + "SOCKET_TCP_INFO": 11, + "SOCKET_TCP_QUICKACK": 12, +} + +func (x SocketOption_SocketOptionName) Enum() *SocketOption_SocketOptionName { + p := new(SocketOption_SocketOptionName) + *p = x + return p +} +func (x SocketOption_SocketOptionName) String() string { + return proto.EnumName(SocketOption_SocketOptionName_name, int32(x)) +} +func (x *SocketOption_SocketOptionName) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SocketOption_SocketOptionName_value, data, "SocketOption_SocketOptionName") + if err != nil { + return err + } + *x = SocketOption_SocketOptionName(value) + return nil +} + +type ShutDownRequest_How int32 + +const ( + ShutDownRequest_SOCKET_SHUT_RD ShutDownRequest_How = 1 + ShutDownRequest_SOCKET_SHUT_WR ShutDownRequest_How = 2 + ShutDownRequest_SOCKET_SHUT_RDWR ShutDownRequest_How = 3 +) + +var ShutDownRequest_How_name = map[int32]string{ + 1: "SOCKET_SHUT_RD", + 2: "SOCKET_SHUT_WR", + 3: "SOCKET_SHUT_RDWR", +} +var ShutDownRequest_How_value = map[string]int32{ + "SOCKET_SHUT_RD": 1, + "SOCKET_SHUT_WR": 2, + "SOCKET_SHUT_RDWR": 3, +} + +func (x ShutDownRequest_How) Enum() *ShutDownRequest_How { + p := new(ShutDownRequest_How) + *p = x + return p +} +func (x ShutDownRequest_How) String() string { + return proto.EnumName(ShutDownRequest_How_name, int32(x)) +} +func (x *ShutDownRequest_How) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ShutDownRequest_How_value, data, "ShutDownRequest_How") + if err != nil { + return err + } + *x = ShutDownRequest_How(value) + return nil +} + +type ReceiveRequest_Flags int32 + +const ( + ReceiveRequest_MSG_OOB ReceiveRequest_Flags = 1 + ReceiveRequest_MSG_PEEK ReceiveRequest_Flags = 2 +) + +var ReceiveRequest_Flags_name = map[int32]string{ + 1: "MSG_OOB", + 2: "MSG_PEEK", +} +var ReceiveRequest_Flags_value = map[string]int32{ + "MSG_OOB": 1, + "MSG_PEEK": 2, +} + +func (x ReceiveRequest_Flags) Enum() *ReceiveRequest_Flags { + p := new(ReceiveRequest_Flags) + *p = x + return p +} +func (x ReceiveRequest_Flags) String() string { + return proto.EnumName(ReceiveRequest_Flags_name, int32(x)) +} +func (x *ReceiveRequest_Flags) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ReceiveRequest_Flags_value, data, "ReceiveRequest_Flags") + if err != nil { + return err + } + *x = ReceiveRequest_Flags(value) + return nil +} + +type PollEvent_PollEventFlag int32 + +const ( + PollEvent_SOCKET_POLLNONE PollEvent_PollEventFlag = 0 + PollEvent_SOCKET_POLLIN PollEvent_PollEventFlag = 1 + PollEvent_SOCKET_POLLPRI PollEvent_PollEventFlag = 2 + PollEvent_SOCKET_POLLOUT PollEvent_PollEventFlag = 4 + PollEvent_SOCKET_POLLERR PollEvent_PollEventFlag = 8 + PollEvent_SOCKET_POLLHUP PollEvent_PollEventFlag = 16 + PollEvent_SOCKET_POLLNVAL PollEvent_PollEventFlag = 32 + PollEvent_SOCKET_POLLRDNORM PollEvent_PollEventFlag = 64 + PollEvent_SOCKET_POLLRDBAND PollEvent_PollEventFlag = 128 + PollEvent_SOCKET_POLLWRNORM PollEvent_PollEventFlag = 256 + PollEvent_SOCKET_POLLWRBAND PollEvent_PollEventFlag = 512 + PollEvent_SOCKET_POLLMSG PollEvent_PollEventFlag = 1024 + PollEvent_SOCKET_POLLREMOVE PollEvent_PollEventFlag = 4096 + PollEvent_SOCKET_POLLRDHUP PollEvent_PollEventFlag = 8192 +) + +var PollEvent_PollEventFlag_name = map[int32]string{ + 0: "SOCKET_POLLNONE", + 1: "SOCKET_POLLIN", + 2: "SOCKET_POLLPRI", + 4: "SOCKET_POLLOUT", + 8: "SOCKET_POLLERR", + 16: "SOCKET_POLLHUP", + 32: "SOCKET_POLLNVAL", + 64: "SOCKET_POLLRDNORM", + 128: "SOCKET_POLLRDBAND", + 256: "SOCKET_POLLWRNORM", + 512: "SOCKET_POLLWRBAND", + 1024: "SOCKET_POLLMSG", + 4096: "SOCKET_POLLREMOVE", + 8192: "SOCKET_POLLRDHUP", +} +var PollEvent_PollEventFlag_value = map[string]int32{ + "SOCKET_POLLNONE": 0, + "SOCKET_POLLIN": 1, + "SOCKET_POLLPRI": 2, + "SOCKET_POLLOUT": 4, + "SOCKET_POLLERR": 8, + "SOCKET_POLLHUP": 16, + "SOCKET_POLLNVAL": 32, + "SOCKET_POLLRDNORM": 64, + "SOCKET_POLLRDBAND": 128, + "SOCKET_POLLWRNORM": 256, + "SOCKET_POLLWRBAND": 512, + "SOCKET_POLLMSG": 1024, + "SOCKET_POLLREMOVE": 4096, + "SOCKET_POLLRDHUP": 8192, +} + +func (x PollEvent_PollEventFlag) Enum() *PollEvent_PollEventFlag { + p := new(PollEvent_PollEventFlag) + *p = x + return p +} +func (x PollEvent_PollEventFlag) String() string { + return proto.EnumName(PollEvent_PollEventFlag_name, int32(x)) +} +func (x *PollEvent_PollEventFlag) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PollEvent_PollEventFlag_value, data, "PollEvent_PollEventFlag") + if err != nil { + return err + } + *x = PollEvent_PollEventFlag(value) + return nil +} + +type ResolveReply_ErrorCode int32 + +const ( + ResolveReply_SOCKET_EAI_ADDRFAMILY ResolveReply_ErrorCode = 1 + ResolveReply_SOCKET_EAI_AGAIN ResolveReply_ErrorCode = 2 + ResolveReply_SOCKET_EAI_BADFLAGS ResolveReply_ErrorCode = 3 + ResolveReply_SOCKET_EAI_FAIL ResolveReply_ErrorCode = 4 + ResolveReply_SOCKET_EAI_FAMILY ResolveReply_ErrorCode = 5 + ResolveReply_SOCKET_EAI_MEMORY ResolveReply_ErrorCode = 6 + ResolveReply_SOCKET_EAI_NODATA ResolveReply_ErrorCode = 7 + ResolveReply_SOCKET_EAI_NONAME ResolveReply_ErrorCode = 8 + ResolveReply_SOCKET_EAI_SERVICE ResolveReply_ErrorCode = 9 + ResolveReply_SOCKET_EAI_SOCKTYPE ResolveReply_ErrorCode = 10 + ResolveReply_SOCKET_EAI_SYSTEM ResolveReply_ErrorCode = 11 + ResolveReply_SOCKET_EAI_BADHINTS ResolveReply_ErrorCode = 12 + ResolveReply_SOCKET_EAI_PROTOCOL ResolveReply_ErrorCode = 13 + ResolveReply_SOCKET_EAI_OVERFLOW ResolveReply_ErrorCode = 14 + ResolveReply_SOCKET_EAI_MAX ResolveReply_ErrorCode = 15 +) + +var ResolveReply_ErrorCode_name = map[int32]string{ + 1: "SOCKET_EAI_ADDRFAMILY", + 2: "SOCKET_EAI_AGAIN", + 3: "SOCKET_EAI_BADFLAGS", + 4: "SOCKET_EAI_FAIL", + 5: "SOCKET_EAI_FAMILY", + 6: "SOCKET_EAI_MEMORY", + 7: "SOCKET_EAI_NODATA", + 8: "SOCKET_EAI_NONAME", + 9: "SOCKET_EAI_SERVICE", + 10: "SOCKET_EAI_SOCKTYPE", + 11: "SOCKET_EAI_SYSTEM", + 12: "SOCKET_EAI_BADHINTS", + 13: "SOCKET_EAI_PROTOCOL", + 14: "SOCKET_EAI_OVERFLOW", + 15: "SOCKET_EAI_MAX", +} +var ResolveReply_ErrorCode_value = map[string]int32{ + "SOCKET_EAI_ADDRFAMILY": 1, + "SOCKET_EAI_AGAIN": 2, + "SOCKET_EAI_BADFLAGS": 3, + "SOCKET_EAI_FAIL": 4, + "SOCKET_EAI_FAMILY": 5, + "SOCKET_EAI_MEMORY": 6, + "SOCKET_EAI_NODATA": 7, + "SOCKET_EAI_NONAME": 8, + "SOCKET_EAI_SERVICE": 9, + "SOCKET_EAI_SOCKTYPE": 10, + "SOCKET_EAI_SYSTEM": 11, + "SOCKET_EAI_BADHINTS": 12, + "SOCKET_EAI_PROTOCOL": 13, + "SOCKET_EAI_OVERFLOW": 14, + "SOCKET_EAI_MAX": 15, +} + +func (x ResolveReply_ErrorCode) Enum() *ResolveReply_ErrorCode { + p := new(ResolveReply_ErrorCode) + *p = x + return p +} +func (x ResolveReply_ErrorCode) String() string { + return proto.EnumName(ResolveReply_ErrorCode_name, int32(x)) +} +func (x *ResolveReply_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ResolveReply_ErrorCode_value, data, "ResolveReply_ErrorCode") + if err != nil { + return err + } + *x = ResolveReply_ErrorCode(value) + return nil +} + +type RemoteSocketServiceError struct { + SystemError *int32 `protobuf:"varint,1,opt,name=system_error,def=0" json:"system_error,omitempty"` + ErrorDetail *string `protobuf:"bytes,2,opt,name=error_detail" json:"error_detail,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RemoteSocketServiceError) Reset() { *m = RemoteSocketServiceError{} } +func (m *RemoteSocketServiceError) String() string { return proto.CompactTextString(m) } +func (*RemoteSocketServiceError) ProtoMessage() {} + +const Default_RemoteSocketServiceError_SystemError int32 = 0 + +func (m *RemoteSocketServiceError) GetSystemError() int32 { + if m != nil && m.SystemError != nil { + return *m.SystemError + } + return Default_RemoteSocketServiceError_SystemError +} + +func (m *RemoteSocketServiceError) GetErrorDetail() string { + if m != nil && m.ErrorDetail != nil { + return *m.ErrorDetail + } + return "" +} + +type AddressPort struct { + Port *int32 `protobuf:"varint,1,req,name=port" json:"port,omitempty"` + PackedAddress []byte `protobuf:"bytes,2,opt,name=packed_address" json:"packed_address,omitempty"` + HostnameHint *string `protobuf:"bytes,3,opt,name=hostname_hint" json:"hostname_hint,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AddressPort) Reset() { *m = AddressPort{} } +func (m *AddressPort) String() string { return proto.CompactTextString(m) } +func (*AddressPort) ProtoMessage() {} + +func (m *AddressPort) GetPort() int32 { + if m != nil && m.Port != nil { + return *m.Port + } + return 0 +} + +func (m *AddressPort) GetPackedAddress() []byte { + if m != nil { + return m.PackedAddress + } + return nil +} + +func (m *AddressPort) GetHostnameHint() string { + if m != nil && m.HostnameHint != nil { + return *m.HostnameHint + } + return "" +} + +type CreateSocketRequest struct { + Family *CreateSocketRequest_SocketFamily `protobuf:"varint,1,req,name=family,enum=appengine.CreateSocketRequest_SocketFamily" json:"family,omitempty"` + Protocol *CreateSocketRequest_SocketProtocol `protobuf:"varint,2,req,name=protocol,enum=appengine.CreateSocketRequest_SocketProtocol" json:"protocol,omitempty"` + SocketOptions []*SocketOption `protobuf:"bytes,3,rep,name=socket_options" json:"socket_options,omitempty"` + ProxyExternalIp *AddressPort `protobuf:"bytes,4,opt,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + ListenBacklog *int32 `protobuf:"varint,5,opt,name=listen_backlog,def=0" json:"listen_backlog,omitempty"` + RemoteIp *AddressPort `protobuf:"bytes,6,opt,name=remote_ip" json:"remote_ip,omitempty"` + AppId *string `protobuf:"bytes,9,opt,name=app_id" json:"app_id,omitempty"` + ProjectId *int64 `protobuf:"varint,10,opt,name=project_id" json:"project_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateSocketRequest) Reset() { *m = CreateSocketRequest{} } +func (m *CreateSocketRequest) String() string { return proto.CompactTextString(m) } +func (*CreateSocketRequest) ProtoMessage() {} + +const Default_CreateSocketRequest_ListenBacklog int32 = 0 + +func (m *CreateSocketRequest) GetFamily() CreateSocketRequest_SocketFamily { + if m != nil && m.Family != nil { + return *m.Family + } + return CreateSocketRequest_IPv4 +} + +func (m *CreateSocketRequest) GetProtocol() CreateSocketRequest_SocketProtocol { + if m != nil && m.Protocol != nil { + return *m.Protocol + } + return CreateSocketRequest_TCP +} + +func (m *CreateSocketRequest) GetSocketOptions() []*SocketOption { + if m != nil { + return m.SocketOptions + } + return nil +} + +func (m *CreateSocketRequest) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +func (m *CreateSocketRequest) GetListenBacklog() int32 { + if m != nil && m.ListenBacklog != nil { + return *m.ListenBacklog + } + return Default_CreateSocketRequest_ListenBacklog +} + +func (m *CreateSocketRequest) GetRemoteIp() *AddressPort { + if m != nil { + return m.RemoteIp + } + return nil +} + +func (m *CreateSocketRequest) GetAppId() string { + if m != nil && m.AppId != nil { + return *m.AppId + } + return "" +} + +func (m *CreateSocketRequest) GetProjectId() int64 { + if m != nil && m.ProjectId != nil { + return *m.ProjectId + } + return 0 +} + +type CreateSocketReply struct { + SocketDescriptor *string `protobuf:"bytes,1,opt,name=socket_descriptor" json:"socket_descriptor,omitempty"` + ServerAddress *AddressPort `protobuf:"bytes,3,opt,name=server_address" json:"server_address,omitempty"` + ProxyExternalIp *AddressPort `protobuf:"bytes,4,opt,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + XXX_extensions map[int32]proto.Extension `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateSocketReply) Reset() { *m = CreateSocketReply{} } +func (m *CreateSocketReply) String() string { return proto.CompactTextString(m) } +func (*CreateSocketReply) ProtoMessage() {} + +var extRange_CreateSocketReply = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*CreateSocketReply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_CreateSocketReply +} +func (m *CreateSocketReply) ExtensionMap() map[int32]proto.Extension { + if m.XXX_extensions == nil { + m.XXX_extensions = make(map[int32]proto.Extension) + } + return m.XXX_extensions +} + +func (m *CreateSocketReply) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *CreateSocketReply) GetServerAddress() *AddressPort { + if m != nil { + return m.ServerAddress + } + return nil +} + +func (m *CreateSocketReply) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +type BindRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + ProxyExternalIp *AddressPort `protobuf:"bytes,2,req,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BindRequest) Reset() { *m = BindRequest{} } +func (m *BindRequest) String() string { return proto.CompactTextString(m) } +func (*BindRequest) ProtoMessage() {} + +func (m *BindRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *BindRequest) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +type BindReply struct { + ProxyExternalIp *AddressPort `protobuf:"bytes,1,opt,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BindReply) Reset() { *m = BindReply{} } +func (m *BindReply) String() string { return proto.CompactTextString(m) } +func (*BindReply) ProtoMessage() {} + +func (m *BindReply) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +type GetSocketNameRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSocketNameRequest) Reset() { *m = GetSocketNameRequest{} } +func (m *GetSocketNameRequest) String() string { return proto.CompactTextString(m) } +func (*GetSocketNameRequest) ProtoMessage() {} + +func (m *GetSocketNameRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +type GetSocketNameReply struct { + ProxyExternalIp *AddressPort `protobuf:"bytes,2,opt,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSocketNameReply) Reset() { *m = GetSocketNameReply{} } +func (m *GetSocketNameReply) String() string { return proto.CompactTextString(m) } +func (*GetSocketNameReply) ProtoMessage() {} + +func (m *GetSocketNameReply) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +type GetPeerNameRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetPeerNameRequest) Reset() { *m = GetPeerNameRequest{} } +func (m *GetPeerNameRequest) String() string { return proto.CompactTextString(m) } +func (*GetPeerNameRequest) ProtoMessage() {} + +func (m *GetPeerNameRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +type GetPeerNameReply struct { + PeerIp *AddressPort `protobuf:"bytes,2,opt,name=peer_ip" json:"peer_ip,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetPeerNameReply) Reset() { *m = GetPeerNameReply{} } +func (m *GetPeerNameReply) String() string { return proto.CompactTextString(m) } +func (*GetPeerNameReply) ProtoMessage() {} + +func (m *GetPeerNameReply) GetPeerIp() *AddressPort { + if m != nil { + return m.PeerIp + } + return nil +} + +type SocketOption struct { + Level *SocketOption_SocketOptionLevel `protobuf:"varint,1,req,name=level,enum=appengine.SocketOption_SocketOptionLevel" json:"level,omitempty"` + Option *SocketOption_SocketOptionName `protobuf:"varint,2,req,name=option,enum=appengine.SocketOption_SocketOptionName" json:"option,omitempty"` + Value []byte `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SocketOption) Reset() { *m = SocketOption{} } +func (m *SocketOption) String() string { return proto.CompactTextString(m) } +func (*SocketOption) ProtoMessage() {} + +func (m *SocketOption) GetLevel() SocketOption_SocketOptionLevel { + if m != nil && m.Level != nil { + return *m.Level + } + return SocketOption_SOCKET_SOL_IP +} + +func (m *SocketOption) GetOption() SocketOption_SocketOptionName { + if m != nil && m.Option != nil { + return *m.Option + } + return SocketOption_SOCKET_SO_DEBUG +} + +func (m *SocketOption) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type SetSocketOptionsRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + Options []*SocketOption `protobuf:"bytes,2,rep,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetSocketOptionsRequest) Reset() { *m = SetSocketOptionsRequest{} } +func (m *SetSocketOptionsRequest) String() string { return proto.CompactTextString(m) } +func (*SetSocketOptionsRequest) ProtoMessage() {} + +func (m *SetSocketOptionsRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *SetSocketOptionsRequest) GetOptions() []*SocketOption { + if m != nil { + return m.Options + } + return nil +} + +type SetSocketOptionsReply struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *SetSocketOptionsReply) Reset() { *m = SetSocketOptionsReply{} } +func (m *SetSocketOptionsReply) String() string { return proto.CompactTextString(m) } +func (*SetSocketOptionsReply) ProtoMessage() {} + +type GetSocketOptionsRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + Options []*SocketOption `protobuf:"bytes,2,rep,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSocketOptionsRequest) Reset() { *m = GetSocketOptionsRequest{} } +func (m *GetSocketOptionsRequest) String() string { return proto.CompactTextString(m) } +func (*GetSocketOptionsRequest) ProtoMessage() {} + +func (m *GetSocketOptionsRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *GetSocketOptionsRequest) GetOptions() []*SocketOption { + if m != nil { + return m.Options + } + return nil +} + +type GetSocketOptionsReply struct { + Options []*SocketOption `protobuf:"bytes,2,rep,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSocketOptionsReply) Reset() { *m = GetSocketOptionsReply{} } +func (m *GetSocketOptionsReply) String() string { return proto.CompactTextString(m) } +func (*GetSocketOptionsReply) ProtoMessage() {} + +func (m *GetSocketOptionsReply) GetOptions() []*SocketOption { + if m != nil { + return m.Options + } + return nil +} + +type ConnectRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + RemoteIp *AddressPort `protobuf:"bytes,2,req,name=remote_ip" json:"remote_ip,omitempty"` + TimeoutSeconds *float64 `protobuf:"fixed64,3,opt,name=timeout_seconds,def=-1" json:"timeout_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ConnectRequest) Reset() { *m = ConnectRequest{} } +func (m *ConnectRequest) String() string { return proto.CompactTextString(m) } +func (*ConnectRequest) ProtoMessage() {} + +const Default_ConnectRequest_TimeoutSeconds float64 = -1 + +func (m *ConnectRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *ConnectRequest) GetRemoteIp() *AddressPort { + if m != nil { + return m.RemoteIp + } + return nil +} + +func (m *ConnectRequest) GetTimeoutSeconds() float64 { + if m != nil && m.TimeoutSeconds != nil { + return *m.TimeoutSeconds + } + return Default_ConnectRequest_TimeoutSeconds +} + +type ConnectReply struct { + ProxyExternalIp *AddressPort `protobuf:"bytes,1,opt,name=proxy_external_ip" json:"proxy_external_ip,omitempty"` + XXX_extensions map[int32]proto.Extension `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ConnectReply) Reset() { *m = ConnectReply{} } +func (m *ConnectReply) String() string { return proto.CompactTextString(m) } +func (*ConnectReply) ProtoMessage() {} + +var extRange_ConnectReply = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*ConnectReply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ConnectReply +} +func (m *ConnectReply) ExtensionMap() map[int32]proto.Extension { + if m.XXX_extensions == nil { + m.XXX_extensions = make(map[int32]proto.Extension) + } + return m.XXX_extensions +} + +func (m *ConnectReply) GetProxyExternalIp() *AddressPort { + if m != nil { + return m.ProxyExternalIp + } + return nil +} + +type ListenRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + Backlog *int32 `protobuf:"varint,2,req,name=backlog" json:"backlog,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListenRequest) Reset() { *m = ListenRequest{} } +func (m *ListenRequest) String() string { return proto.CompactTextString(m) } +func (*ListenRequest) ProtoMessage() {} + +func (m *ListenRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *ListenRequest) GetBacklog() int32 { + if m != nil && m.Backlog != nil { + return *m.Backlog + } + return 0 +} + +type ListenReply struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ListenReply) Reset() { *m = ListenReply{} } +func (m *ListenReply) String() string { return proto.CompactTextString(m) } +func (*ListenReply) ProtoMessage() {} + +type AcceptRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + TimeoutSeconds *float64 `protobuf:"fixed64,2,opt,name=timeout_seconds,def=-1" json:"timeout_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AcceptRequest) Reset() { *m = AcceptRequest{} } +func (m *AcceptRequest) String() string { return proto.CompactTextString(m) } +func (*AcceptRequest) ProtoMessage() {} + +const Default_AcceptRequest_TimeoutSeconds float64 = -1 + +func (m *AcceptRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *AcceptRequest) GetTimeoutSeconds() float64 { + if m != nil && m.TimeoutSeconds != nil { + return *m.TimeoutSeconds + } + return Default_AcceptRequest_TimeoutSeconds +} + +type AcceptReply struct { + NewSocketDescriptor []byte `protobuf:"bytes,2,opt,name=new_socket_descriptor" json:"new_socket_descriptor,omitempty"` + RemoteAddress *AddressPort `protobuf:"bytes,3,opt,name=remote_address" json:"remote_address,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AcceptReply) Reset() { *m = AcceptReply{} } +func (m *AcceptReply) String() string { return proto.CompactTextString(m) } +func (*AcceptReply) ProtoMessage() {} + +func (m *AcceptReply) GetNewSocketDescriptor() []byte { + if m != nil { + return m.NewSocketDescriptor + } + return nil +} + +func (m *AcceptReply) GetRemoteAddress() *AddressPort { + if m != nil { + return m.RemoteAddress + } + return nil +} + +type ShutDownRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + How *ShutDownRequest_How `protobuf:"varint,2,req,name=how,enum=appengine.ShutDownRequest_How" json:"how,omitempty"` + SendOffset *int64 `protobuf:"varint,3,req,name=send_offset" json:"send_offset,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ShutDownRequest) Reset() { *m = ShutDownRequest{} } +func (m *ShutDownRequest) String() string { return proto.CompactTextString(m) } +func (*ShutDownRequest) ProtoMessage() {} + +func (m *ShutDownRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *ShutDownRequest) GetHow() ShutDownRequest_How { + if m != nil && m.How != nil { + return *m.How + } + return ShutDownRequest_SOCKET_SHUT_RD +} + +func (m *ShutDownRequest) GetSendOffset() int64 { + if m != nil && m.SendOffset != nil { + return *m.SendOffset + } + return 0 +} + +type ShutDownReply struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ShutDownReply) Reset() { *m = ShutDownReply{} } +func (m *ShutDownReply) String() string { return proto.CompactTextString(m) } +func (*ShutDownReply) ProtoMessage() {} + +type CloseRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + SendOffset *int64 `protobuf:"varint,2,opt,name=send_offset,def=-1" json:"send_offset,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CloseRequest) Reset() { *m = CloseRequest{} } +func (m *CloseRequest) String() string { return proto.CompactTextString(m) } +func (*CloseRequest) ProtoMessage() {} + +const Default_CloseRequest_SendOffset int64 = -1 + +func (m *CloseRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *CloseRequest) GetSendOffset() int64 { + if m != nil && m.SendOffset != nil { + return *m.SendOffset + } + return Default_CloseRequest_SendOffset +} + +type CloseReply struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *CloseReply) Reset() { *m = CloseReply{} } +func (m *CloseReply) String() string { return proto.CompactTextString(m) } +func (*CloseReply) ProtoMessage() {} + +type SendRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + Data []byte `protobuf:"bytes,2,req,name=data" json:"data,omitempty"` + StreamOffset *int64 `protobuf:"varint,3,req,name=stream_offset" json:"stream_offset,omitempty"` + Flags *int32 `protobuf:"varint,4,opt,name=flags,def=0" json:"flags,omitempty"` + SendTo *AddressPort `protobuf:"bytes,5,opt,name=send_to" json:"send_to,omitempty"` + TimeoutSeconds *float64 `protobuf:"fixed64,6,opt,name=timeout_seconds,def=-1" json:"timeout_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SendRequest) Reset() { *m = SendRequest{} } +func (m *SendRequest) String() string { return proto.CompactTextString(m) } +func (*SendRequest) ProtoMessage() {} + +const Default_SendRequest_Flags int32 = 0 +const Default_SendRequest_TimeoutSeconds float64 = -1 + +func (m *SendRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *SendRequest) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *SendRequest) GetStreamOffset() int64 { + if m != nil && m.StreamOffset != nil { + return *m.StreamOffset + } + return 0 +} + +func (m *SendRequest) GetFlags() int32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return Default_SendRequest_Flags +} + +func (m *SendRequest) GetSendTo() *AddressPort { + if m != nil { + return m.SendTo + } + return nil +} + +func (m *SendRequest) GetTimeoutSeconds() float64 { + if m != nil && m.TimeoutSeconds != nil { + return *m.TimeoutSeconds + } + return Default_SendRequest_TimeoutSeconds +} + +type SendReply struct { + DataSent *int32 `protobuf:"varint,1,opt,name=data_sent" json:"data_sent,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SendReply) Reset() { *m = SendReply{} } +func (m *SendReply) String() string { return proto.CompactTextString(m) } +func (*SendReply) ProtoMessage() {} + +func (m *SendReply) GetDataSent() int32 { + if m != nil && m.DataSent != nil { + return *m.DataSent + } + return 0 +} + +type ReceiveRequest struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + DataSize *int32 `protobuf:"varint,2,req,name=data_size" json:"data_size,omitempty"` + Flags *int32 `protobuf:"varint,3,opt,name=flags,def=0" json:"flags,omitempty"` + TimeoutSeconds *float64 `protobuf:"fixed64,5,opt,name=timeout_seconds,def=-1" json:"timeout_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ReceiveRequest) Reset() { *m = ReceiveRequest{} } +func (m *ReceiveRequest) String() string { return proto.CompactTextString(m) } +func (*ReceiveRequest) ProtoMessage() {} + +const Default_ReceiveRequest_Flags int32 = 0 +const Default_ReceiveRequest_TimeoutSeconds float64 = -1 + +func (m *ReceiveRequest) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *ReceiveRequest) GetDataSize() int32 { + if m != nil && m.DataSize != nil { + return *m.DataSize + } + return 0 +} + +func (m *ReceiveRequest) GetFlags() int32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return Default_ReceiveRequest_Flags +} + +func (m *ReceiveRequest) GetTimeoutSeconds() float64 { + if m != nil && m.TimeoutSeconds != nil { + return *m.TimeoutSeconds + } + return Default_ReceiveRequest_TimeoutSeconds +} + +type ReceiveReply struct { + StreamOffset *int64 `protobuf:"varint,2,opt,name=stream_offset" json:"stream_offset,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"` + ReceivedFrom *AddressPort `protobuf:"bytes,4,opt,name=received_from" json:"received_from,omitempty"` + BufferSize *int32 `protobuf:"varint,5,opt,name=buffer_size" json:"buffer_size,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ReceiveReply) Reset() { *m = ReceiveReply{} } +func (m *ReceiveReply) String() string { return proto.CompactTextString(m) } +func (*ReceiveReply) ProtoMessage() {} + +func (m *ReceiveReply) GetStreamOffset() int64 { + if m != nil && m.StreamOffset != nil { + return *m.StreamOffset + } + return 0 +} + +func (m *ReceiveReply) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ReceiveReply) GetReceivedFrom() *AddressPort { + if m != nil { + return m.ReceivedFrom + } + return nil +} + +func (m *ReceiveReply) GetBufferSize() int32 { + if m != nil && m.BufferSize != nil { + return *m.BufferSize + } + return 0 +} + +type PollEvent struct { + SocketDescriptor *string `protobuf:"bytes,1,req,name=socket_descriptor" json:"socket_descriptor,omitempty"` + RequestedEvents *int32 `protobuf:"varint,2,req,name=requested_events" json:"requested_events,omitempty"` + ObservedEvents *int32 `protobuf:"varint,3,req,name=observed_events" json:"observed_events,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PollEvent) Reset() { *m = PollEvent{} } +func (m *PollEvent) String() string { return proto.CompactTextString(m) } +func (*PollEvent) ProtoMessage() {} + +func (m *PollEvent) GetSocketDescriptor() string { + if m != nil && m.SocketDescriptor != nil { + return *m.SocketDescriptor + } + return "" +} + +func (m *PollEvent) GetRequestedEvents() int32 { + if m != nil && m.RequestedEvents != nil { + return *m.RequestedEvents + } + return 0 +} + +func (m *PollEvent) GetObservedEvents() int32 { + if m != nil && m.ObservedEvents != nil { + return *m.ObservedEvents + } + return 0 +} + +type PollRequest struct { + Events []*PollEvent `protobuf:"bytes,1,rep,name=events" json:"events,omitempty"` + TimeoutSeconds *float64 `protobuf:"fixed64,2,opt,name=timeout_seconds,def=-1" json:"timeout_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PollRequest) Reset() { *m = PollRequest{} } +func (m *PollRequest) String() string { return proto.CompactTextString(m) } +func (*PollRequest) ProtoMessage() {} + +const Default_PollRequest_TimeoutSeconds float64 = -1 + +func (m *PollRequest) GetEvents() []*PollEvent { + if m != nil { + return m.Events + } + return nil +} + +func (m *PollRequest) GetTimeoutSeconds() float64 { + if m != nil && m.TimeoutSeconds != nil { + return *m.TimeoutSeconds + } + return Default_PollRequest_TimeoutSeconds +} + +type PollReply struct { + Events []*PollEvent `protobuf:"bytes,2,rep,name=events" json:"events,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PollReply) Reset() { *m = PollReply{} } +func (m *PollReply) String() string { return proto.CompactTextString(m) } +func (*PollReply) ProtoMessage() {} + +func (m *PollReply) GetEvents() []*PollEvent { + if m != nil { + return m.Events + } + return nil +} + +type ResolveRequest struct { + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + AddressFamilies []CreateSocketRequest_SocketFamily `protobuf:"varint,2,rep,name=address_families,enum=appengine.CreateSocketRequest_SocketFamily" json:"address_families,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ResolveRequest) Reset() { *m = ResolveRequest{} } +func (m *ResolveRequest) String() string { return proto.CompactTextString(m) } +func (*ResolveRequest) ProtoMessage() {} + +func (m *ResolveRequest) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *ResolveRequest) GetAddressFamilies() []CreateSocketRequest_SocketFamily { + if m != nil { + return m.AddressFamilies + } + return nil +} + +type ResolveReply struct { + PackedAddress [][]byte `protobuf:"bytes,2,rep,name=packed_address" json:"packed_address,omitempty"` + CanonicalName *string `protobuf:"bytes,3,opt,name=canonical_name" json:"canonical_name,omitempty"` + Aliases []string `protobuf:"bytes,4,rep,name=aliases" json:"aliases,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ResolveReply) Reset() { *m = ResolveReply{} } +func (m *ResolveReply) String() string { return proto.CompactTextString(m) } +func (*ResolveReply) ProtoMessage() {} + +func (m *ResolveReply) GetPackedAddress() [][]byte { + if m != nil { + return m.PackedAddress + } + return nil +} + +func (m *ResolveReply) GetCanonicalName() string { + if m != nil && m.CanonicalName != nil { + return *m.CanonicalName + } + return "" +} + +func (m *ResolveReply) GetAliases() []string { + if m != nil { + return m.Aliases + } + return nil +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/socket/socket_service.proto b/vendor/google.golang.org/appengine/internal/socket/socket_service.proto new file mode 100644 index 000000000..2fcc7953d --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/socket/socket_service.proto @@ -0,0 +1,460 @@ +syntax = "proto2"; +option go_package = "socket"; + +package appengine; + +message RemoteSocketServiceError { + enum ErrorCode { + SYSTEM_ERROR = 1; + GAI_ERROR = 2; + FAILURE = 4; + PERMISSION_DENIED = 5; + INVALID_REQUEST = 6; + SOCKET_CLOSED = 7; + } + + enum SystemError { + option allow_alias = true; + + SYS_SUCCESS = 0; + SYS_EPERM = 1; + SYS_ENOENT = 2; + SYS_ESRCH = 3; + SYS_EINTR = 4; + SYS_EIO = 5; + SYS_ENXIO = 6; + SYS_E2BIG = 7; + SYS_ENOEXEC = 8; + SYS_EBADF = 9; + SYS_ECHILD = 10; + SYS_EAGAIN = 11; + SYS_EWOULDBLOCK = 11; + SYS_ENOMEM = 12; + SYS_EACCES = 13; + SYS_EFAULT = 14; + SYS_ENOTBLK = 15; + SYS_EBUSY = 16; + SYS_EEXIST = 17; + SYS_EXDEV = 18; + SYS_ENODEV = 19; + SYS_ENOTDIR = 20; + SYS_EISDIR = 21; + SYS_EINVAL = 22; + SYS_ENFILE = 23; + SYS_EMFILE = 24; + SYS_ENOTTY = 25; + SYS_ETXTBSY = 26; + SYS_EFBIG = 27; + SYS_ENOSPC = 28; + SYS_ESPIPE = 29; + SYS_EROFS = 30; + SYS_EMLINK = 31; + SYS_EPIPE = 32; + SYS_EDOM = 33; + SYS_ERANGE = 34; + SYS_EDEADLK = 35; + SYS_EDEADLOCK = 35; + SYS_ENAMETOOLONG = 36; + SYS_ENOLCK = 37; + SYS_ENOSYS = 38; + SYS_ENOTEMPTY = 39; + SYS_ELOOP = 40; + SYS_ENOMSG = 42; + SYS_EIDRM = 43; + SYS_ECHRNG = 44; + SYS_EL2NSYNC = 45; + SYS_EL3HLT = 46; + SYS_EL3RST = 47; + SYS_ELNRNG = 48; + SYS_EUNATCH = 49; + SYS_ENOCSI = 50; + SYS_EL2HLT = 51; + SYS_EBADE = 52; + SYS_EBADR = 53; + SYS_EXFULL = 54; + SYS_ENOANO = 55; + SYS_EBADRQC = 56; + SYS_EBADSLT = 57; + SYS_EBFONT = 59; + SYS_ENOSTR = 60; + SYS_ENODATA = 61; + SYS_ETIME = 62; + SYS_ENOSR = 63; + SYS_ENONET = 64; + SYS_ENOPKG = 65; + SYS_EREMOTE = 66; + SYS_ENOLINK = 67; + SYS_EADV = 68; + SYS_ESRMNT = 69; + SYS_ECOMM = 70; + SYS_EPROTO = 71; + SYS_EMULTIHOP = 72; + SYS_EDOTDOT = 73; + SYS_EBADMSG = 74; + SYS_EOVERFLOW = 75; + SYS_ENOTUNIQ = 76; + SYS_EBADFD = 77; + SYS_EREMCHG = 78; + SYS_ELIBACC = 79; + SYS_ELIBBAD = 80; + SYS_ELIBSCN = 81; + SYS_ELIBMAX = 82; + SYS_ELIBEXEC = 83; + SYS_EILSEQ = 84; + SYS_ERESTART = 85; + SYS_ESTRPIPE = 86; + SYS_EUSERS = 87; + SYS_ENOTSOCK = 88; + SYS_EDESTADDRREQ = 89; + SYS_EMSGSIZE = 90; + SYS_EPROTOTYPE = 91; + SYS_ENOPROTOOPT = 92; + SYS_EPROTONOSUPPORT = 93; + SYS_ESOCKTNOSUPPORT = 94; + SYS_EOPNOTSUPP = 95; + SYS_ENOTSUP = 95; + SYS_EPFNOSUPPORT = 96; + SYS_EAFNOSUPPORT = 97; + SYS_EADDRINUSE = 98; + SYS_EADDRNOTAVAIL = 99; + SYS_ENETDOWN = 100; + SYS_ENETUNREACH = 101; + SYS_ENETRESET = 102; + SYS_ECONNABORTED = 103; + SYS_ECONNRESET = 104; + SYS_ENOBUFS = 105; + SYS_EISCONN = 106; + SYS_ENOTCONN = 107; + SYS_ESHUTDOWN = 108; + SYS_ETOOMANYREFS = 109; + SYS_ETIMEDOUT = 110; + SYS_ECONNREFUSED = 111; + SYS_EHOSTDOWN = 112; + SYS_EHOSTUNREACH = 113; + SYS_EALREADY = 114; + SYS_EINPROGRESS = 115; + SYS_ESTALE = 116; + SYS_EUCLEAN = 117; + SYS_ENOTNAM = 118; + SYS_ENAVAIL = 119; + SYS_EISNAM = 120; + SYS_EREMOTEIO = 121; + SYS_EDQUOT = 122; + SYS_ENOMEDIUM = 123; + SYS_EMEDIUMTYPE = 124; + SYS_ECANCELED = 125; + SYS_ENOKEY = 126; + SYS_EKEYEXPIRED = 127; + SYS_EKEYREVOKED = 128; + SYS_EKEYREJECTED = 129; + SYS_EOWNERDEAD = 130; + SYS_ENOTRECOVERABLE = 131; + SYS_ERFKILL = 132; + } + + optional int32 system_error = 1 [default=0]; + optional string error_detail = 2; +} + +message AddressPort { + required int32 port = 1; + optional bytes packed_address = 2; + + optional string hostname_hint = 3; +} + + + +message CreateSocketRequest { + enum SocketFamily { + IPv4 = 1; + IPv6 = 2; + } + + enum SocketProtocol { + TCP = 1; + UDP = 2; + } + + required SocketFamily family = 1; + required SocketProtocol protocol = 2; + + repeated SocketOption socket_options = 3; + + optional AddressPort proxy_external_ip = 4; + + optional int32 listen_backlog = 5 [default=0]; + + optional AddressPort remote_ip = 6; + + optional string app_id = 9; + + optional int64 project_id = 10; +} + +message CreateSocketReply { + optional string socket_descriptor = 1; + + optional AddressPort server_address = 3; + + optional AddressPort proxy_external_ip = 4; + + extensions 1000 to max; +} + + + +message BindRequest { + required string socket_descriptor = 1; + required AddressPort proxy_external_ip = 2; +} + +message BindReply { + optional AddressPort proxy_external_ip = 1; +} + + + +message GetSocketNameRequest { + required string socket_descriptor = 1; +} + +message GetSocketNameReply { + optional AddressPort proxy_external_ip = 2; +} + + + +message GetPeerNameRequest { + required string socket_descriptor = 1; +} + +message GetPeerNameReply { + optional AddressPort peer_ip = 2; +} + + +message SocketOption { + + enum SocketOptionLevel { + SOCKET_SOL_IP = 0; + SOCKET_SOL_SOCKET = 1; + SOCKET_SOL_TCP = 6; + SOCKET_SOL_UDP = 17; + } + + enum SocketOptionName { + option allow_alias = true; + + SOCKET_SO_DEBUG = 1; + SOCKET_SO_REUSEADDR = 2; + SOCKET_SO_TYPE = 3; + SOCKET_SO_ERROR = 4; + SOCKET_SO_DONTROUTE = 5; + SOCKET_SO_BROADCAST = 6; + SOCKET_SO_SNDBUF = 7; + SOCKET_SO_RCVBUF = 8; + SOCKET_SO_KEEPALIVE = 9; + SOCKET_SO_OOBINLINE = 10; + SOCKET_SO_LINGER = 13; + SOCKET_SO_RCVTIMEO = 20; + SOCKET_SO_SNDTIMEO = 21; + + SOCKET_IP_TOS = 1; + SOCKET_IP_TTL = 2; + SOCKET_IP_HDRINCL = 3; + SOCKET_IP_OPTIONS = 4; + + SOCKET_TCP_NODELAY = 1; + SOCKET_TCP_MAXSEG = 2; + SOCKET_TCP_CORK = 3; + SOCKET_TCP_KEEPIDLE = 4; + SOCKET_TCP_KEEPINTVL = 5; + SOCKET_TCP_KEEPCNT = 6; + SOCKET_TCP_SYNCNT = 7; + SOCKET_TCP_LINGER2 = 8; + SOCKET_TCP_DEFER_ACCEPT = 9; + SOCKET_TCP_WINDOW_CLAMP = 10; + SOCKET_TCP_INFO = 11; + SOCKET_TCP_QUICKACK = 12; + } + + required SocketOptionLevel level = 1; + required SocketOptionName option = 2; + required bytes value = 3; +} + + +message SetSocketOptionsRequest { + required string socket_descriptor = 1; + repeated SocketOption options = 2; +} + +message SetSocketOptionsReply { +} + +message GetSocketOptionsRequest { + required string socket_descriptor = 1; + repeated SocketOption options = 2; +} + +message GetSocketOptionsReply { + repeated SocketOption options = 2; +} + + +message ConnectRequest { + required string socket_descriptor = 1; + required AddressPort remote_ip = 2; + optional double timeout_seconds = 3 [default=-1]; +} + +message ConnectReply { + optional AddressPort proxy_external_ip = 1; + + extensions 1000 to max; +} + + +message ListenRequest { + required string socket_descriptor = 1; + required int32 backlog = 2; +} + +message ListenReply { +} + + +message AcceptRequest { + required string socket_descriptor = 1; + optional double timeout_seconds = 2 [default=-1]; +} + +message AcceptReply { + optional bytes new_socket_descriptor = 2; + optional AddressPort remote_address = 3; +} + + + +message ShutDownRequest { + enum How { + SOCKET_SHUT_RD = 1; + SOCKET_SHUT_WR = 2; + SOCKET_SHUT_RDWR = 3; + } + required string socket_descriptor = 1; + required How how = 2; + required int64 send_offset = 3; +} + +message ShutDownReply { +} + + + +message CloseRequest { + required string socket_descriptor = 1; + optional int64 send_offset = 2 [default=-1]; +} + +message CloseReply { +} + + + +message SendRequest { + required string socket_descriptor = 1; + required bytes data = 2 [ctype=CORD]; + required int64 stream_offset = 3; + optional int32 flags = 4 [default=0]; + optional AddressPort send_to = 5; + optional double timeout_seconds = 6 [default=-1]; +} + +message SendReply { + optional int32 data_sent = 1; +} + + +message ReceiveRequest { + enum Flags { + MSG_OOB = 1; + MSG_PEEK = 2; + } + required string socket_descriptor = 1; + required int32 data_size = 2; + optional int32 flags = 3 [default=0]; + optional double timeout_seconds = 5 [default=-1]; +} + +message ReceiveReply { + optional int64 stream_offset = 2; + optional bytes data = 3 [ctype=CORD]; + optional AddressPort received_from = 4; + optional int32 buffer_size = 5; +} + + + +message PollEvent { + + enum PollEventFlag { + SOCKET_POLLNONE = 0; + SOCKET_POLLIN = 1; + SOCKET_POLLPRI = 2; + SOCKET_POLLOUT = 4; + SOCKET_POLLERR = 8; + SOCKET_POLLHUP = 16; + SOCKET_POLLNVAL = 32; + SOCKET_POLLRDNORM = 64; + SOCKET_POLLRDBAND = 128; + SOCKET_POLLWRNORM = 256; + SOCKET_POLLWRBAND = 512; + SOCKET_POLLMSG = 1024; + SOCKET_POLLREMOVE = 4096; + SOCKET_POLLRDHUP = 8192; + }; + + required string socket_descriptor = 1; + required int32 requested_events = 2; + required int32 observed_events = 3; +} + +message PollRequest { + repeated PollEvent events = 1; + optional double timeout_seconds = 2 [default=-1]; +} + +message PollReply { + repeated PollEvent events = 2; +} + +message ResolveRequest { + required string name = 1; + repeated CreateSocketRequest.SocketFamily address_families = 2; +} + +message ResolveReply { + enum ErrorCode { + SOCKET_EAI_ADDRFAMILY = 1; + SOCKET_EAI_AGAIN = 2; + SOCKET_EAI_BADFLAGS = 3; + SOCKET_EAI_FAIL = 4; + SOCKET_EAI_FAMILY = 5; + SOCKET_EAI_MEMORY = 6; + SOCKET_EAI_NODATA = 7; + SOCKET_EAI_NONAME = 8; + SOCKET_EAI_SERVICE = 9; + SOCKET_EAI_SOCKTYPE = 10; + SOCKET_EAI_SYSTEM = 11; + SOCKET_EAI_BADHINTS = 12; + SOCKET_EAI_PROTOCOL = 13; + SOCKET_EAI_OVERFLOW = 14; + SOCKET_EAI_MAX = 15; + }; + + repeated bytes packed_address = 2; + optional string canonical_name = 3; + repeated string aliases = 4; +} diff --git a/vendor/google.golang.org/appengine/internal/system/system_service.pb.go b/vendor/google.golang.org/appengine/internal/system/system_service.pb.go new file mode 100644 index 000000000..56cc3f805 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/system/system_service.pb.go @@ -0,0 +1,198 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/system/system_service.proto +// DO NOT EDIT! + +/* +Package system is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/system/system_service.proto + +It has these top-level messages: + SystemServiceError + SystemStat + GetSystemStatsRequest + GetSystemStatsResponse + StartBackgroundRequestRequest + StartBackgroundRequestResponse +*/ +package system + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type SystemServiceError_ErrorCode int32 + +const ( + SystemServiceError_OK SystemServiceError_ErrorCode = 0 + SystemServiceError_INTERNAL_ERROR SystemServiceError_ErrorCode = 1 + SystemServiceError_BACKEND_REQUIRED SystemServiceError_ErrorCode = 2 + SystemServiceError_LIMIT_REACHED SystemServiceError_ErrorCode = 3 +) + +var SystemServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INTERNAL_ERROR", + 2: "BACKEND_REQUIRED", + 3: "LIMIT_REACHED", +} +var SystemServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INTERNAL_ERROR": 1, + "BACKEND_REQUIRED": 2, + "LIMIT_REACHED": 3, +} + +func (x SystemServiceError_ErrorCode) Enum() *SystemServiceError_ErrorCode { + p := new(SystemServiceError_ErrorCode) + *p = x + return p +} +func (x SystemServiceError_ErrorCode) String() string { + return proto.EnumName(SystemServiceError_ErrorCode_name, int32(x)) +} +func (x *SystemServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(SystemServiceError_ErrorCode_value, data, "SystemServiceError_ErrorCode") + if err != nil { + return err + } + *x = SystemServiceError_ErrorCode(value) + return nil +} + +type SystemServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *SystemServiceError) Reset() { *m = SystemServiceError{} } +func (m *SystemServiceError) String() string { return proto.CompactTextString(m) } +func (*SystemServiceError) ProtoMessage() {} + +type SystemStat struct { + // Instaneous value of this stat. + Current *float64 `protobuf:"fixed64,1,opt,name=current" json:"current,omitempty"` + // Average over time, if this stat has an instaneous value. + Average1M *float64 `protobuf:"fixed64,3,opt,name=average1m" json:"average1m,omitempty"` + Average10M *float64 `protobuf:"fixed64,4,opt,name=average10m" json:"average10m,omitempty"` + // Total value, if the stat accumulates over time. + Total *float64 `protobuf:"fixed64,2,opt,name=total" json:"total,omitempty"` + // Rate over time, if this stat accumulates. + Rate1M *float64 `protobuf:"fixed64,5,opt,name=rate1m" json:"rate1m,omitempty"` + Rate10M *float64 `protobuf:"fixed64,6,opt,name=rate10m" json:"rate10m,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SystemStat) Reset() { *m = SystemStat{} } +func (m *SystemStat) String() string { return proto.CompactTextString(m) } +func (*SystemStat) ProtoMessage() {} + +func (m *SystemStat) GetCurrent() float64 { + if m != nil && m.Current != nil { + return *m.Current + } + return 0 +} + +func (m *SystemStat) GetAverage1M() float64 { + if m != nil && m.Average1M != nil { + return *m.Average1M + } + return 0 +} + +func (m *SystemStat) GetAverage10M() float64 { + if m != nil && m.Average10M != nil { + return *m.Average10M + } + return 0 +} + +func (m *SystemStat) GetTotal() float64 { + if m != nil && m.Total != nil { + return *m.Total + } + return 0 +} + +func (m *SystemStat) GetRate1M() float64 { + if m != nil && m.Rate1M != nil { + return *m.Rate1M + } + return 0 +} + +func (m *SystemStat) GetRate10M() float64 { + if m != nil && m.Rate10M != nil { + return *m.Rate10M + } + return 0 +} + +type GetSystemStatsRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSystemStatsRequest) Reset() { *m = GetSystemStatsRequest{} } +func (m *GetSystemStatsRequest) String() string { return proto.CompactTextString(m) } +func (*GetSystemStatsRequest) ProtoMessage() {} + +type GetSystemStatsResponse struct { + // CPU used by this instance, in mcycles. + Cpu *SystemStat `protobuf:"bytes,1,opt,name=cpu" json:"cpu,omitempty"` + // Physical memory (RAM) used by this instance, in megabytes. + Memory *SystemStat `protobuf:"bytes,2,opt,name=memory" json:"memory,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetSystemStatsResponse) Reset() { *m = GetSystemStatsResponse{} } +func (m *GetSystemStatsResponse) String() string { return proto.CompactTextString(m) } +func (*GetSystemStatsResponse) ProtoMessage() {} + +func (m *GetSystemStatsResponse) GetCpu() *SystemStat { + if m != nil { + return m.Cpu + } + return nil +} + +func (m *GetSystemStatsResponse) GetMemory() *SystemStat { + if m != nil { + return m.Memory + } + return nil +} + +type StartBackgroundRequestRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *StartBackgroundRequestRequest) Reset() { *m = StartBackgroundRequestRequest{} } +func (m *StartBackgroundRequestRequest) String() string { return proto.CompactTextString(m) } +func (*StartBackgroundRequestRequest) ProtoMessage() {} + +type StartBackgroundRequestResponse struct { + // Every /_ah/background request will have an X-AppEngine-BackgroundRequest + // header, whose value will be equal to this parameter, the request_id. + RequestId *string `protobuf:"bytes,1,opt,name=request_id" json:"request_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StartBackgroundRequestResponse) Reset() { *m = StartBackgroundRequestResponse{} } +func (m *StartBackgroundRequestResponse) String() string { return proto.CompactTextString(m) } +func (*StartBackgroundRequestResponse) ProtoMessage() {} + +func (m *StartBackgroundRequestResponse) GetRequestId() string { + if m != nil && m.RequestId != nil { + return *m.RequestId + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/system/system_service.proto b/vendor/google.golang.org/appengine/internal/system/system_service.proto new file mode 100644 index 000000000..32c0bf859 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/system/system_service.proto @@ -0,0 +1,49 @@ +syntax = "proto2"; +option go_package = "system"; + +package appengine; + +message SystemServiceError { + enum ErrorCode { + OK = 0; + INTERNAL_ERROR = 1; + BACKEND_REQUIRED = 2; + LIMIT_REACHED = 3; + } +} + +message SystemStat { + // Instaneous value of this stat. + optional double current = 1; + + // Average over time, if this stat has an instaneous value. + optional double average1m = 3; + optional double average10m = 4; + + // Total value, if the stat accumulates over time. + optional double total = 2; + + // Rate over time, if this stat accumulates. + optional double rate1m = 5; + optional double rate10m = 6; +} + +message GetSystemStatsRequest { +} + +message GetSystemStatsResponse { + // CPU used by this instance, in mcycles. + optional SystemStat cpu = 1; + + // Physical memory (RAM) used by this instance, in megabytes. + optional SystemStat memory = 2; +} + +message StartBackgroundRequestRequest { +} + +message StartBackgroundRequestResponse { + // Every /_ah/background request will have an X-AppEngine-BackgroundRequest + // header, whose value will be equal to this parameter, the request_id. + optional string request_id = 1; +} diff --git a/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.pb.go b/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.pb.go new file mode 100644 index 000000000..c3d428ec5 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.pb.go @@ -0,0 +1,1888 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto +// DO NOT EDIT! + +/* +Package taskqueue is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto + +It has these top-level messages: + TaskQueueServiceError + TaskPayload + TaskQueueRetryParameters + TaskQueueAcl + TaskQueueHttpHeader + TaskQueueMode + TaskQueueAddRequest + TaskQueueAddResponse + TaskQueueBulkAddRequest + TaskQueueBulkAddResponse + TaskQueueDeleteRequest + TaskQueueDeleteResponse + TaskQueueForceRunRequest + TaskQueueForceRunResponse + TaskQueueUpdateQueueRequest + TaskQueueUpdateQueueResponse + TaskQueueFetchQueuesRequest + TaskQueueFetchQueuesResponse + TaskQueueFetchQueueStatsRequest + TaskQueueScannerQueueInfo + TaskQueueFetchQueueStatsResponse + TaskQueuePauseQueueRequest + TaskQueuePauseQueueResponse + TaskQueuePurgeQueueRequest + TaskQueuePurgeQueueResponse + TaskQueueDeleteQueueRequest + TaskQueueDeleteQueueResponse + TaskQueueDeleteGroupRequest + TaskQueueDeleteGroupResponse + TaskQueueQueryTasksRequest + TaskQueueQueryTasksResponse + TaskQueueFetchTaskRequest + TaskQueueFetchTaskResponse + TaskQueueUpdateStorageLimitRequest + TaskQueueUpdateStorageLimitResponse + TaskQueueQueryAndOwnTasksRequest + TaskQueueQueryAndOwnTasksResponse + TaskQueueModifyTaskLeaseRequest + TaskQueueModifyTaskLeaseResponse +*/ +package taskqueue + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import appengine "google.golang.org/appengine/internal/datastore" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type TaskQueueServiceError_ErrorCode int32 + +const ( + TaskQueueServiceError_OK TaskQueueServiceError_ErrorCode = 0 + TaskQueueServiceError_UNKNOWN_QUEUE TaskQueueServiceError_ErrorCode = 1 + TaskQueueServiceError_TRANSIENT_ERROR TaskQueueServiceError_ErrorCode = 2 + TaskQueueServiceError_INTERNAL_ERROR TaskQueueServiceError_ErrorCode = 3 + TaskQueueServiceError_TASK_TOO_LARGE TaskQueueServiceError_ErrorCode = 4 + TaskQueueServiceError_INVALID_TASK_NAME TaskQueueServiceError_ErrorCode = 5 + TaskQueueServiceError_INVALID_QUEUE_NAME TaskQueueServiceError_ErrorCode = 6 + TaskQueueServiceError_INVALID_URL TaskQueueServiceError_ErrorCode = 7 + TaskQueueServiceError_INVALID_QUEUE_RATE TaskQueueServiceError_ErrorCode = 8 + TaskQueueServiceError_PERMISSION_DENIED TaskQueueServiceError_ErrorCode = 9 + TaskQueueServiceError_TASK_ALREADY_EXISTS TaskQueueServiceError_ErrorCode = 10 + TaskQueueServiceError_TOMBSTONED_TASK TaskQueueServiceError_ErrorCode = 11 + TaskQueueServiceError_INVALID_ETA TaskQueueServiceError_ErrorCode = 12 + TaskQueueServiceError_INVALID_REQUEST TaskQueueServiceError_ErrorCode = 13 + TaskQueueServiceError_UNKNOWN_TASK TaskQueueServiceError_ErrorCode = 14 + TaskQueueServiceError_TOMBSTONED_QUEUE TaskQueueServiceError_ErrorCode = 15 + TaskQueueServiceError_DUPLICATE_TASK_NAME TaskQueueServiceError_ErrorCode = 16 + TaskQueueServiceError_SKIPPED TaskQueueServiceError_ErrorCode = 17 + TaskQueueServiceError_TOO_MANY_TASKS TaskQueueServiceError_ErrorCode = 18 + TaskQueueServiceError_INVALID_PAYLOAD TaskQueueServiceError_ErrorCode = 19 + TaskQueueServiceError_INVALID_RETRY_PARAMETERS TaskQueueServiceError_ErrorCode = 20 + TaskQueueServiceError_INVALID_QUEUE_MODE TaskQueueServiceError_ErrorCode = 21 + TaskQueueServiceError_ACL_LOOKUP_ERROR TaskQueueServiceError_ErrorCode = 22 + TaskQueueServiceError_TRANSACTIONAL_REQUEST_TOO_LARGE TaskQueueServiceError_ErrorCode = 23 + TaskQueueServiceError_INCORRECT_CREATOR_NAME TaskQueueServiceError_ErrorCode = 24 + TaskQueueServiceError_TASK_LEASE_EXPIRED TaskQueueServiceError_ErrorCode = 25 + TaskQueueServiceError_QUEUE_PAUSED TaskQueueServiceError_ErrorCode = 26 + TaskQueueServiceError_INVALID_TAG TaskQueueServiceError_ErrorCode = 27 + // Reserved range for the Datastore error codes. + // Original Datastore error code is shifted by DATASTORE_ERROR offset. + TaskQueueServiceError_DATASTORE_ERROR TaskQueueServiceError_ErrorCode = 10000 +) + +var TaskQueueServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "UNKNOWN_QUEUE", + 2: "TRANSIENT_ERROR", + 3: "INTERNAL_ERROR", + 4: "TASK_TOO_LARGE", + 5: "INVALID_TASK_NAME", + 6: "INVALID_QUEUE_NAME", + 7: "INVALID_URL", + 8: "INVALID_QUEUE_RATE", + 9: "PERMISSION_DENIED", + 10: "TASK_ALREADY_EXISTS", + 11: "TOMBSTONED_TASK", + 12: "INVALID_ETA", + 13: "INVALID_REQUEST", + 14: "UNKNOWN_TASK", + 15: "TOMBSTONED_QUEUE", + 16: "DUPLICATE_TASK_NAME", + 17: "SKIPPED", + 18: "TOO_MANY_TASKS", + 19: "INVALID_PAYLOAD", + 20: "INVALID_RETRY_PARAMETERS", + 21: "INVALID_QUEUE_MODE", + 22: "ACL_LOOKUP_ERROR", + 23: "TRANSACTIONAL_REQUEST_TOO_LARGE", + 24: "INCORRECT_CREATOR_NAME", + 25: "TASK_LEASE_EXPIRED", + 26: "QUEUE_PAUSED", + 27: "INVALID_TAG", + 10000: "DATASTORE_ERROR", +} +var TaskQueueServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "UNKNOWN_QUEUE": 1, + "TRANSIENT_ERROR": 2, + "INTERNAL_ERROR": 3, + "TASK_TOO_LARGE": 4, + "INVALID_TASK_NAME": 5, + "INVALID_QUEUE_NAME": 6, + "INVALID_URL": 7, + "INVALID_QUEUE_RATE": 8, + "PERMISSION_DENIED": 9, + "TASK_ALREADY_EXISTS": 10, + "TOMBSTONED_TASK": 11, + "INVALID_ETA": 12, + "INVALID_REQUEST": 13, + "UNKNOWN_TASK": 14, + "TOMBSTONED_QUEUE": 15, + "DUPLICATE_TASK_NAME": 16, + "SKIPPED": 17, + "TOO_MANY_TASKS": 18, + "INVALID_PAYLOAD": 19, + "INVALID_RETRY_PARAMETERS": 20, + "INVALID_QUEUE_MODE": 21, + "ACL_LOOKUP_ERROR": 22, + "TRANSACTIONAL_REQUEST_TOO_LARGE": 23, + "INCORRECT_CREATOR_NAME": 24, + "TASK_LEASE_EXPIRED": 25, + "QUEUE_PAUSED": 26, + "INVALID_TAG": 27, + "DATASTORE_ERROR": 10000, +} + +func (x TaskQueueServiceError_ErrorCode) Enum() *TaskQueueServiceError_ErrorCode { + p := new(TaskQueueServiceError_ErrorCode) + *p = x + return p +} +func (x TaskQueueServiceError_ErrorCode) String() string { + return proto.EnumName(TaskQueueServiceError_ErrorCode_name, int32(x)) +} +func (x *TaskQueueServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(TaskQueueServiceError_ErrorCode_value, data, "TaskQueueServiceError_ErrorCode") + if err != nil { + return err + } + *x = TaskQueueServiceError_ErrorCode(value) + return nil +} + +type TaskQueueMode_Mode int32 + +const ( + TaskQueueMode_PUSH TaskQueueMode_Mode = 0 + TaskQueueMode_PULL TaskQueueMode_Mode = 1 +) + +var TaskQueueMode_Mode_name = map[int32]string{ + 0: "PUSH", + 1: "PULL", +} +var TaskQueueMode_Mode_value = map[string]int32{ + "PUSH": 0, + "PULL": 1, +} + +func (x TaskQueueMode_Mode) Enum() *TaskQueueMode_Mode { + p := new(TaskQueueMode_Mode) + *p = x + return p +} +func (x TaskQueueMode_Mode) String() string { + return proto.EnumName(TaskQueueMode_Mode_name, int32(x)) +} +func (x *TaskQueueMode_Mode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(TaskQueueMode_Mode_value, data, "TaskQueueMode_Mode") + if err != nil { + return err + } + *x = TaskQueueMode_Mode(value) + return nil +} + +type TaskQueueAddRequest_RequestMethod int32 + +const ( + TaskQueueAddRequest_GET TaskQueueAddRequest_RequestMethod = 1 + TaskQueueAddRequest_POST TaskQueueAddRequest_RequestMethod = 2 + TaskQueueAddRequest_HEAD TaskQueueAddRequest_RequestMethod = 3 + TaskQueueAddRequest_PUT TaskQueueAddRequest_RequestMethod = 4 + TaskQueueAddRequest_DELETE TaskQueueAddRequest_RequestMethod = 5 +) + +var TaskQueueAddRequest_RequestMethod_name = map[int32]string{ + 1: "GET", + 2: "POST", + 3: "HEAD", + 4: "PUT", + 5: "DELETE", +} +var TaskQueueAddRequest_RequestMethod_value = map[string]int32{ + "GET": 1, + "POST": 2, + "HEAD": 3, + "PUT": 4, + "DELETE": 5, +} + +func (x TaskQueueAddRequest_RequestMethod) Enum() *TaskQueueAddRequest_RequestMethod { + p := new(TaskQueueAddRequest_RequestMethod) + *p = x + return p +} +func (x TaskQueueAddRequest_RequestMethod) String() string { + return proto.EnumName(TaskQueueAddRequest_RequestMethod_name, int32(x)) +} +func (x *TaskQueueAddRequest_RequestMethod) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(TaskQueueAddRequest_RequestMethod_value, data, "TaskQueueAddRequest_RequestMethod") + if err != nil { + return err + } + *x = TaskQueueAddRequest_RequestMethod(value) + return nil +} + +type TaskQueueQueryTasksResponse_Task_RequestMethod int32 + +const ( + TaskQueueQueryTasksResponse_Task_GET TaskQueueQueryTasksResponse_Task_RequestMethod = 1 + TaskQueueQueryTasksResponse_Task_POST TaskQueueQueryTasksResponse_Task_RequestMethod = 2 + TaskQueueQueryTasksResponse_Task_HEAD TaskQueueQueryTasksResponse_Task_RequestMethod = 3 + TaskQueueQueryTasksResponse_Task_PUT TaskQueueQueryTasksResponse_Task_RequestMethod = 4 + TaskQueueQueryTasksResponse_Task_DELETE TaskQueueQueryTasksResponse_Task_RequestMethod = 5 +) + +var TaskQueueQueryTasksResponse_Task_RequestMethod_name = map[int32]string{ + 1: "GET", + 2: "POST", + 3: "HEAD", + 4: "PUT", + 5: "DELETE", +} +var TaskQueueQueryTasksResponse_Task_RequestMethod_value = map[string]int32{ + "GET": 1, + "POST": 2, + "HEAD": 3, + "PUT": 4, + "DELETE": 5, +} + +func (x TaskQueueQueryTasksResponse_Task_RequestMethod) Enum() *TaskQueueQueryTasksResponse_Task_RequestMethod { + p := new(TaskQueueQueryTasksResponse_Task_RequestMethod) + *p = x + return p +} +func (x TaskQueueQueryTasksResponse_Task_RequestMethod) String() string { + return proto.EnumName(TaskQueueQueryTasksResponse_Task_RequestMethod_name, int32(x)) +} +func (x *TaskQueueQueryTasksResponse_Task_RequestMethod) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(TaskQueueQueryTasksResponse_Task_RequestMethod_value, data, "TaskQueueQueryTasksResponse_Task_RequestMethod") + if err != nil { + return err + } + *x = TaskQueueQueryTasksResponse_Task_RequestMethod(value) + return nil +} + +type TaskQueueServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueServiceError) Reset() { *m = TaskQueueServiceError{} } +func (m *TaskQueueServiceError) String() string { return proto.CompactTextString(m) } +func (*TaskQueueServiceError) ProtoMessage() {} + +type TaskPayload struct { + XXX_extensions map[int32]proto.Extension `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskPayload) Reset() { *m = TaskPayload{} } +func (m *TaskPayload) String() string { return proto.CompactTextString(m) } +func (*TaskPayload) ProtoMessage() {} + +func (m *TaskPayload) Marshal() ([]byte, error) { + return proto.MarshalMessageSet(m.ExtensionMap()) +} +func (m *TaskPayload) Unmarshal(buf []byte) error { + return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) +} +func (m *TaskPayload) MarshalJSON() ([]byte, error) { + return proto.MarshalMessageSetJSON(m.XXX_extensions) +} +func (m *TaskPayload) UnmarshalJSON(buf []byte) error { + return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) +} + +// ensure TaskPayload satisfies proto.Marshaler and proto.Unmarshaler +var _ proto.Marshaler = (*TaskPayload)(nil) +var _ proto.Unmarshaler = (*TaskPayload)(nil) + +var extRange_TaskPayload = []proto.ExtensionRange{ + {10, 2147483646}, +} + +func (*TaskPayload) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_TaskPayload +} +func (m *TaskPayload) ExtensionMap() map[int32]proto.Extension { + if m.XXX_extensions == nil { + m.XXX_extensions = make(map[int32]proto.Extension) + } + return m.XXX_extensions +} + +type TaskQueueRetryParameters struct { + RetryLimit *int32 `protobuf:"varint,1,opt,name=retry_limit" json:"retry_limit,omitempty"` + AgeLimitSec *int64 `protobuf:"varint,2,opt,name=age_limit_sec" json:"age_limit_sec,omitempty"` + MinBackoffSec *float64 `protobuf:"fixed64,3,opt,name=min_backoff_sec,def=0.1" json:"min_backoff_sec,omitempty"` + MaxBackoffSec *float64 `protobuf:"fixed64,4,opt,name=max_backoff_sec,def=3600" json:"max_backoff_sec,omitempty"` + MaxDoublings *int32 `protobuf:"varint,5,opt,name=max_doublings,def=16" json:"max_doublings,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueRetryParameters) Reset() { *m = TaskQueueRetryParameters{} } +func (m *TaskQueueRetryParameters) String() string { return proto.CompactTextString(m) } +func (*TaskQueueRetryParameters) ProtoMessage() {} + +const Default_TaskQueueRetryParameters_MinBackoffSec float64 = 0.1 +const Default_TaskQueueRetryParameters_MaxBackoffSec float64 = 3600 +const Default_TaskQueueRetryParameters_MaxDoublings int32 = 16 + +func (m *TaskQueueRetryParameters) GetRetryLimit() int32 { + if m != nil && m.RetryLimit != nil { + return *m.RetryLimit + } + return 0 +} + +func (m *TaskQueueRetryParameters) GetAgeLimitSec() int64 { + if m != nil && m.AgeLimitSec != nil { + return *m.AgeLimitSec + } + return 0 +} + +func (m *TaskQueueRetryParameters) GetMinBackoffSec() float64 { + if m != nil && m.MinBackoffSec != nil { + return *m.MinBackoffSec + } + return Default_TaskQueueRetryParameters_MinBackoffSec +} + +func (m *TaskQueueRetryParameters) GetMaxBackoffSec() float64 { + if m != nil && m.MaxBackoffSec != nil { + return *m.MaxBackoffSec + } + return Default_TaskQueueRetryParameters_MaxBackoffSec +} + +func (m *TaskQueueRetryParameters) GetMaxDoublings() int32 { + if m != nil && m.MaxDoublings != nil { + return *m.MaxDoublings + } + return Default_TaskQueueRetryParameters_MaxDoublings +} + +type TaskQueueAcl struct { + UserEmail [][]byte `protobuf:"bytes,1,rep,name=user_email" json:"user_email,omitempty"` + WriterEmail [][]byte `protobuf:"bytes,2,rep,name=writer_email" json:"writer_email,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueAcl) Reset() { *m = TaskQueueAcl{} } +func (m *TaskQueueAcl) String() string { return proto.CompactTextString(m) } +func (*TaskQueueAcl) ProtoMessage() {} + +func (m *TaskQueueAcl) GetUserEmail() [][]byte { + if m != nil { + return m.UserEmail + } + return nil +} + +func (m *TaskQueueAcl) GetWriterEmail() [][]byte { + if m != nil { + return m.WriterEmail + } + return nil +} + +type TaskQueueHttpHeader struct { + Key []byte `protobuf:"bytes,1,req,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueHttpHeader) Reset() { *m = TaskQueueHttpHeader{} } +func (m *TaskQueueHttpHeader) String() string { return proto.CompactTextString(m) } +func (*TaskQueueHttpHeader) ProtoMessage() {} + +func (m *TaskQueueHttpHeader) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *TaskQueueHttpHeader) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type TaskQueueMode struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueMode) Reset() { *m = TaskQueueMode{} } +func (m *TaskQueueMode) String() string { return proto.CompactTextString(m) } +func (*TaskQueueMode) ProtoMessage() {} + +type TaskQueueAddRequest struct { + QueueName []byte `protobuf:"bytes,1,req,name=queue_name" json:"queue_name,omitempty"` + TaskName []byte `protobuf:"bytes,2,req,name=task_name" json:"task_name,omitempty"` + EtaUsec *int64 `protobuf:"varint,3,req,name=eta_usec" json:"eta_usec,omitempty"` + Method *TaskQueueAddRequest_RequestMethod `protobuf:"varint,5,opt,name=method,enum=appengine.TaskQueueAddRequest_RequestMethod,def=2" json:"method,omitempty"` + Url []byte `protobuf:"bytes,4,opt,name=url" json:"url,omitempty"` + Header []*TaskQueueAddRequest_Header `protobuf:"group,6,rep,name=Header" json:"header,omitempty"` + Body []byte `protobuf:"bytes,9,opt,name=body" json:"body,omitempty"` + Transaction *appengine.Transaction `protobuf:"bytes,10,opt,name=transaction" json:"transaction,omitempty"` + AppId []byte `protobuf:"bytes,11,opt,name=app_id" json:"app_id,omitempty"` + Crontimetable *TaskQueueAddRequest_CronTimetable `protobuf:"group,12,opt,name=CronTimetable" json:"crontimetable,omitempty"` + Description []byte `protobuf:"bytes,15,opt,name=description" json:"description,omitempty"` + Payload *TaskPayload `protobuf:"bytes,16,opt,name=payload" json:"payload,omitempty"` + RetryParameters *TaskQueueRetryParameters `protobuf:"bytes,17,opt,name=retry_parameters" json:"retry_parameters,omitempty"` + Mode *TaskQueueMode_Mode `protobuf:"varint,18,opt,name=mode,enum=appengine.TaskQueueMode_Mode,def=0" json:"mode,omitempty"` + Tag []byte `protobuf:"bytes,19,opt,name=tag" json:"tag,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueAddRequest) Reset() { *m = TaskQueueAddRequest{} } +func (m *TaskQueueAddRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueAddRequest) ProtoMessage() {} + +const Default_TaskQueueAddRequest_Method TaskQueueAddRequest_RequestMethod = TaskQueueAddRequest_POST +const Default_TaskQueueAddRequest_Mode TaskQueueMode_Mode = TaskQueueMode_PUSH + +func (m *TaskQueueAddRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueAddRequest) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +func (m *TaskQueueAddRequest) GetEtaUsec() int64 { + if m != nil && m.EtaUsec != nil { + return *m.EtaUsec + } + return 0 +} + +func (m *TaskQueueAddRequest) GetMethod() TaskQueueAddRequest_RequestMethod { + if m != nil && m.Method != nil { + return *m.Method + } + return Default_TaskQueueAddRequest_Method +} + +func (m *TaskQueueAddRequest) GetUrl() []byte { + if m != nil { + return m.Url + } + return nil +} + +func (m *TaskQueueAddRequest) GetHeader() []*TaskQueueAddRequest_Header { + if m != nil { + return m.Header + } + return nil +} + +func (m *TaskQueueAddRequest) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +func (m *TaskQueueAddRequest) GetTransaction() *appengine.Transaction { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *TaskQueueAddRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueAddRequest) GetCrontimetable() *TaskQueueAddRequest_CronTimetable { + if m != nil { + return m.Crontimetable + } + return nil +} + +func (m *TaskQueueAddRequest) GetDescription() []byte { + if m != nil { + return m.Description + } + return nil +} + +func (m *TaskQueueAddRequest) GetPayload() *TaskPayload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *TaskQueueAddRequest) GetRetryParameters() *TaskQueueRetryParameters { + if m != nil { + return m.RetryParameters + } + return nil +} + +func (m *TaskQueueAddRequest) GetMode() TaskQueueMode_Mode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_TaskQueueAddRequest_Mode +} + +func (m *TaskQueueAddRequest) GetTag() []byte { + if m != nil { + return m.Tag + } + return nil +} + +type TaskQueueAddRequest_Header struct { + Key []byte `protobuf:"bytes,7,req,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,8,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueAddRequest_Header) Reset() { *m = TaskQueueAddRequest_Header{} } +func (m *TaskQueueAddRequest_Header) String() string { return proto.CompactTextString(m) } +func (*TaskQueueAddRequest_Header) ProtoMessage() {} + +func (m *TaskQueueAddRequest_Header) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *TaskQueueAddRequest_Header) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type TaskQueueAddRequest_CronTimetable struct { + Schedule []byte `protobuf:"bytes,13,req,name=schedule" json:"schedule,omitempty"` + Timezone []byte `protobuf:"bytes,14,req,name=timezone" json:"timezone,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueAddRequest_CronTimetable) Reset() { *m = TaskQueueAddRequest_CronTimetable{} } +func (m *TaskQueueAddRequest_CronTimetable) String() string { return proto.CompactTextString(m) } +func (*TaskQueueAddRequest_CronTimetable) ProtoMessage() {} + +func (m *TaskQueueAddRequest_CronTimetable) GetSchedule() []byte { + if m != nil { + return m.Schedule + } + return nil +} + +func (m *TaskQueueAddRequest_CronTimetable) GetTimezone() []byte { + if m != nil { + return m.Timezone + } + return nil +} + +type TaskQueueAddResponse struct { + ChosenTaskName []byte `protobuf:"bytes,1,opt,name=chosen_task_name" json:"chosen_task_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueAddResponse) Reset() { *m = TaskQueueAddResponse{} } +func (m *TaskQueueAddResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueAddResponse) ProtoMessage() {} + +func (m *TaskQueueAddResponse) GetChosenTaskName() []byte { + if m != nil { + return m.ChosenTaskName + } + return nil +} + +type TaskQueueBulkAddRequest struct { + AddRequest []*TaskQueueAddRequest `protobuf:"bytes,1,rep,name=add_request" json:"add_request,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueBulkAddRequest) Reset() { *m = TaskQueueBulkAddRequest{} } +func (m *TaskQueueBulkAddRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueBulkAddRequest) ProtoMessage() {} + +func (m *TaskQueueBulkAddRequest) GetAddRequest() []*TaskQueueAddRequest { + if m != nil { + return m.AddRequest + } + return nil +} + +type TaskQueueBulkAddResponse struct { + Taskresult []*TaskQueueBulkAddResponse_TaskResult `protobuf:"group,1,rep,name=TaskResult" json:"taskresult,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueBulkAddResponse) Reset() { *m = TaskQueueBulkAddResponse{} } +func (m *TaskQueueBulkAddResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueBulkAddResponse) ProtoMessage() {} + +func (m *TaskQueueBulkAddResponse) GetTaskresult() []*TaskQueueBulkAddResponse_TaskResult { + if m != nil { + return m.Taskresult + } + return nil +} + +type TaskQueueBulkAddResponse_TaskResult struct { + Result *TaskQueueServiceError_ErrorCode `protobuf:"varint,2,req,name=result,enum=appengine.TaskQueueServiceError_ErrorCode" json:"result,omitempty"` + ChosenTaskName []byte `protobuf:"bytes,3,opt,name=chosen_task_name" json:"chosen_task_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueBulkAddResponse_TaskResult) Reset() { *m = TaskQueueBulkAddResponse_TaskResult{} } +func (m *TaskQueueBulkAddResponse_TaskResult) String() string { return proto.CompactTextString(m) } +func (*TaskQueueBulkAddResponse_TaskResult) ProtoMessage() {} + +func (m *TaskQueueBulkAddResponse_TaskResult) GetResult() TaskQueueServiceError_ErrorCode { + if m != nil && m.Result != nil { + return *m.Result + } + return TaskQueueServiceError_OK +} + +func (m *TaskQueueBulkAddResponse_TaskResult) GetChosenTaskName() []byte { + if m != nil { + return m.ChosenTaskName + } + return nil +} + +type TaskQueueDeleteRequest struct { + QueueName []byte `protobuf:"bytes,1,req,name=queue_name" json:"queue_name,omitempty"` + TaskName [][]byte `protobuf:"bytes,2,rep,name=task_name" json:"task_name,omitempty"` + AppId []byte `protobuf:"bytes,3,opt,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteRequest) Reset() { *m = TaskQueueDeleteRequest{} } +func (m *TaskQueueDeleteRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteRequest) ProtoMessage() {} + +func (m *TaskQueueDeleteRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueDeleteRequest) GetTaskName() [][]byte { + if m != nil { + return m.TaskName + } + return nil +} + +func (m *TaskQueueDeleteRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type TaskQueueDeleteResponse struct { + Result []TaskQueueServiceError_ErrorCode `protobuf:"varint,3,rep,name=result,enum=appengine.TaskQueueServiceError_ErrorCode" json:"result,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteResponse) Reset() { *m = TaskQueueDeleteResponse{} } +func (m *TaskQueueDeleteResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteResponse) ProtoMessage() {} + +func (m *TaskQueueDeleteResponse) GetResult() []TaskQueueServiceError_ErrorCode { + if m != nil { + return m.Result + } + return nil +} + +type TaskQueueForceRunRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + TaskName []byte `protobuf:"bytes,3,req,name=task_name" json:"task_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueForceRunRequest) Reset() { *m = TaskQueueForceRunRequest{} } +func (m *TaskQueueForceRunRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueForceRunRequest) ProtoMessage() {} + +func (m *TaskQueueForceRunRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueForceRunRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueForceRunRequest) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +type TaskQueueForceRunResponse struct { + Result *TaskQueueServiceError_ErrorCode `protobuf:"varint,3,req,name=result,enum=appengine.TaskQueueServiceError_ErrorCode" json:"result,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueForceRunResponse) Reset() { *m = TaskQueueForceRunResponse{} } +func (m *TaskQueueForceRunResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueForceRunResponse) ProtoMessage() {} + +func (m *TaskQueueForceRunResponse) GetResult() TaskQueueServiceError_ErrorCode { + if m != nil && m.Result != nil { + return *m.Result + } + return TaskQueueServiceError_OK +} + +type TaskQueueUpdateQueueRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + BucketRefillPerSecond *float64 `protobuf:"fixed64,3,req,name=bucket_refill_per_second" json:"bucket_refill_per_second,omitempty"` + BucketCapacity *int32 `protobuf:"varint,4,req,name=bucket_capacity" json:"bucket_capacity,omitempty"` + UserSpecifiedRate *string `protobuf:"bytes,5,opt,name=user_specified_rate" json:"user_specified_rate,omitempty"` + RetryParameters *TaskQueueRetryParameters `protobuf:"bytes,6,opt,name=retry_parameters" json:"retry_parameters,omitempty"` + MaxConcurrentRequests *int32 `protobuf:"varint,7,opt,name=max_concurrent_requests" json:"max_concurrent_requests,omitempty"` + Mode *TaskQueueMode_Mode `protobuf:"varint,8,opt,name=mode,enum=appengine.TaskQueueMode_Mode,def=0" json:"mode,omitempty"` + Acl *TaskQueueAcl `protobuf:"bytes,9,opt,name=acl" json:"acl,omitempty"` + HeaderOverride []*TaskQueueHttpHeader `protobuf:"bytes,10,rep,name=header_override" json:"header_override,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueUpdateQueueRequest) Reset() { *m = TaskQueueUpdateQueueRequest{} } +func (m *TaskQueueUpdateQueueRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueUpdateQueueRequest) ProtoMessage() {} + +const Default_TaskQueueUpdateQueueRequest_Mode TaskQueueMode_Mode = TaskQueueMode_PUSH + +func (m *TaskQueueUpdateQueueRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueUpdateQueueRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueUpdateQueueRequest) GetBucketRefillPerSecond() float64 { + if m != nil && m.BucketRefillPerSecond != nil { + return *m.BucketRefillPerSecond + } + return 0 +} + +func (m *TaskQueueUpdateQueueRequest) GetBucketCapacity() int32 { + if m != nil && m.BucketCapacity != nil { + return *m.BucketCapacity + } + return 0 +} + +func (m *TaskQueueUpdateQueueRequest) GetUserSpecifiedRate() string { + if m != nil && m.UserSpecifiedRate != nil { + return *m.UserSpecifiedRate + } + return "" +} + +func (m *TaskQueueUpdateQueueRequest) GetRetryParameters() *TaskQueueRetryParameters { + if m != nil { + return m.RetryParameters + } + return nil +} + +func (m *TaskQueueUpdateQueueRequest) GetMaxConcurrentRequests() int32 { + if m != nil && m.MaxConcurrentRequests != nil { + return *m.MaxConcurrentRequests + } + return 0 +} + +func (m *TaskQueueUpdateQueueRequest) GetMode() TaskQueueMode_Mode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_TaskQueueUpdateQueueRequest_Mode +} + +func (m *TaskQueueUpdateQueueRequest) GetAcl() *TaskQueueAcl { + if m != nil { + return m.Acl + } + return nil +} + +func (m *TaskQueueUpdateQueueRequest) GetHeaderOverride() []*TaskQueueHttpHeader { + if m != nil { + return m.HeaderOverride + } + return nil +} + +type TaskQueueUpdateQueueResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueUpdateQueueResponse) Reset() { *m = TaskQueueUpdateQueueResponse{} } +func (m *TaskQueueUpdateQueueResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueUpdateQueueResponse) ProtoMessage() {} + +type TaskQueueFetchQueuesRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + MaxRows *int32 `protobuf:"varint,2,req,name=max_rows" json:"max_rows,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueuesRequest) Reset() { *m = TaskQueueFetchQueuesRequest{} } +func (m *TaskQueueFetchQueuesRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchQueuesRequest) ProtoMessage() {} + +func (m *TaskQueueFetchQueuesRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueFetchQueuesRequest) GetMaxRows() int32 { + if m != nil && m.MaxRows != nil { + return *m.MaxRows + } + return 0 +} + +type TaskQueueFetchQueuesResponse struct { + Queue []*TaskQueueFetchQueuesResponse_Queue `protobuf:"group,1,rep,name=Queue" json:"queue,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueuesResponse) Reset() { *m = TaskQueueFetchQueuesResponse{} } +func (m *TaskQueueFetchQueuesResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchQueuesResponse) ProtoMessage() {} + +func (m *TaskQueueFetchQueuesResponse) GetQueue() []*TaskQueueFetchQueuesResponse_Queue { + if m != nil { + return m.Queue + } + return nil +} + +type TaskQueueFetchQueuesResponse_Queue struct { + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + BucketRefillPerSecond *float64 `protobuf:"fixed64,3,req,name=bucket_refill_per_second" json:"bucket_refill_per_second,omitempty"` + BucketCapacity *float64 `protobuf:"fixed64,4,req,name=bucket_capacity" json:"bucket_capacity,omitempty"` + UserSpecifiedRate *string `protobuf:"bytes,5,opt,name=user_specified_rate" json:"user_specified_rate,omitempty"` + Paused *bool `protobuf:"varint,6,req,name=paused,def=0" json:"paused,omitempty"` + RetryParameters *TaskQueueRetryParameters `protobuf:"bytes,7,opt,name=retry_parameters" json:"retry_parameters,omitempty"` + MaxConcurrentRequests *int32 `protobuf:"varint,8,opt,name=max_concurrent_requests" json:"max_concurrent_requests,omitempty"` + Mode *TaskQueueMode_Mode `protobuf:"varint,9,opt,name=mode,enum=appengine.TaskQueueMode_Mode,def=0" json:"mode,omitempty"` + Acl *TaskQueueAcl `protobuf:"bytes,10,opt,name=acl" json:"acl,omitempty"` + HeaderOverride []*TaskQueueHttpHeader `protobuf:"bytes,11,rep,name=header_override" json:"header_override,omitempty"` + CreatorName *string `protobuf:"bytes,12,opt,name=creator_name,def=apphosting" json:"creator_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueuesResponse_Queue) Reset() { *m = TaskQueueFetchQueuesResponse_Queue{} } +func (m *TaskQueueFetchQueuesResponse_Queue) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchQueuesResponse_Queue) ProtoMessage() {} + +const Default_TaskQueueFetchQueuesResponse_Queue_Paused bool = false +const Default_TaskQueueFetchQueuesResponse_Queue_Mode TaskQueueMode_Mode = TaskQueueMode_PUSH +const Default_TaskQueueFetchQueuesResponse_Queue_CreatorName string = "apphosting" + +func (m *TaskQueueFetchQueuesResponse_Queue) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetBucketRefillPerSecond() float64 { + if m != nil && m.BucketRefillPerSecond != nil { + return *m.BucketRefillPerSecond + } + return 0 +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetBucketCapacity() float64 { + if m != nil && m.BucketCapacity != nil { + return *m.BucketCapacity + } + return 0 +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetUserSpecifiedRate() string { + if m != nil && m.UserSpecifiedRate != nil { + return *m.UserSpecifiedRate + } + return "" +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetPaused() bool { + if m != nil && m.Paused != nil { + return *m.Paused + } + return Default_TaskQueueFetchQueuesResponse_Queue_Paused +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetRetryParameters() *TaskQueueRetryParameters { + if m != nil { + return m.RetryParameters + } + return nil +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetMaxConcurrentRequests() int32 { + if m != nil && m.MaxConcurrentRequests != nil { + return *m.MaxConcurrentRequests + } + return 0 +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetMode() TaskQueueMode_Mode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_TaskQueueFetchQueuesResponse_Queue_Mode +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetAcl() *TaskQueueAcl { + if m != nil { + return m.Acl + } + return nil +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetHeaderOverride() []*TaskQueueHttpHeader { + if m != nil { + return m.HeaderOverride + } + return nil +} + +func (m *TaskQueueFetchQueuesResponse_Queue) GetCreatorName() string { + if m != nil && m.CreatorName != nil { + return *m.CreatorName + } + return Default_TaskQueueFetchQueuesResponse_Queue_CreatorName +} + +type TaskQueueFetchQueueStatsRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName [][]byte `protobuf:"bytes,2,rep,name=queue_name" json:"queue_name,omitempty"` + MaxNumTasks *int32 `protobuf:"varint,3,opt,name=max_num_tasks,def=0" json:"max_num_tasks,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueueStatsRequest) Reset() { *m = TaskQueueFetchQueueStatsRequest{} } +func (m *TaskQueueFetchQueueStatsRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchQueueStatsRequest) ProtoMessage() {} + +const Default_TaskQueueFetchQueueStatsRequest_MaxNumTasks int32 = 0 + +func (m *TaskQueueFetchQueueStatsRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueFetchQueueStatsRequest) GetQueueName() [][]byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueFetchQueueStatsRequest) GetMaxNumTasks() int32 { + if m != nil && m.MaxNumTasks != nil { + return *m.MaxNumTasks + } + return Default_TaskQueueFetchQueueStatsRequest_MaxNumTasks +} + +type TaskQueueScannerQueueInfo struct { + ExecutedLastMinute *int64 `protobuf:"varint,1,req,name=executed_last_minute" json:"executed_last_minute,omitempty"` + ExecutedLastHour *int64 `protobuf:"varint,2,req,name=executed_last_hour" json:"executed_last_hour,omitempty"` + SamplingDurationSeconds *float64 `protobuf:"fixed64,3,req,name=sampling_duration_seconds" json:"sampling_duration_seconds,omitempty"` + RequestsInFlight *int32 `protobuf:"varint,4,opt,name=requests_in_flight" json:"requests_in_flight,omitempty"` + EnforcedRate *float64 `protobuf:"fixed64,5,opt,name=enforced_rate" json:"enforced_rate,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueScannerQueueInfo) Reset() { *m = TaskQueueScannerQueueInfo{} } +func (m *TaskQueueScannerQueueInfo) String() string { return proto.CompactTextString(m) } +func (*TaskQueueScannerQueueInfo) ProtoMessage() {} + +func (m *TaskQueueScannerQueueInfo) GetExecutedLastMinute() int64 { + if m != nil && m.ExecutedLastMinute != nil { + return *m.ExecutedLastMinute + } + return 0 +} + +func (m *TaskQueueScannerQueueInfo) GetExecutedLastHour() int64 { + if m != nil && m.ExecutedLastHour != nil { + return *m.ExecutedLastHour + } + return 0 +} + +func (m *TaskQueueScannerQueueInfo) GetSamplingDurationSeconds() float64 { + if m != nil && m.SamplingDurationSeconds != nil { + return *m.SamplingDurationSeconds + } + return 0 +} + +func (m *TaskQueueScannerQueueInfo) GetRequestsInFlight() int32 { + if m != nil && m.RequestsInFlight != nil { + return *m.RequestsInFlight + } + return 0 +} + +func (m *TaskQueueScannerQueueInfo) GetEnforcedRate() float64 { + if m != nil && m.EnforcedRate != nil { + return *m.EnforcedRate + } + return 0 +} + +type TaskQueueFetchQueueStatsResponse struct { + Queuestats []*TaskQueueFetchQueueStatsResponse_QueueStats `protobuf:"group,1,rep,name=QueueStats" json:"queuestats,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueueStatsResponse) Reset() { *m = TaskQueueFetchQueueStatsResponse{} } +func (m *TaskQueueFetchQueueStatsResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchQueueStatsResponse) ProtoMessage() {} + +func (m *TaskQueueFetchQueueStatsResponse) GetQueuestats() []*TaskQueueFetchQueueStatsResponse_QueueStats { + if m != nil { + return m.Queuestats + } + return nil +} + +type TaskQueueFetchQueueStatsResponse_QueueStats struct { + NumTasks *int32 `protobuf:"varint,2,req,name=num_tasks" json:"num_tasks,omitempty"` + OldestEtaUsec *int64 `protobuf:"varint,3,req,name=oldest_eta_usec" json:"oldest_eta_usec,omitempty"` + ScannerInfo *TaskQueueScannerQueueInfo `protobuf:"bytes,4,opt,name=scanner_info" json:"scanner_info,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchQueueStatsResponse_QueueStats) Reset() { + *m = TaskQueueFetchQueueStatsResponse_QueueStats{} +} +func (m *TaskQueueFetchQueueStatsResponse_QueueStats) String() string { + return proto.CompactTextString(m) +} +func (*TaskQueueFetchQueueStatsResponse_QueueStats) ProtoMessage() {} + +func (m *TaskQueueFetchQueueStatsResponse_QueueStats) GetNumTasks() int32 { + if m != nil && m.NumTasks != nil { + return *m.NumTasks + } + return 0 +} + +func (m *TaskQueueFetchQueueStatsResponse_QueueStats) GetOldestEtaUsec() int64 { + if m != nil && m.OldestEtaUsec != nil { + return *m.OldestEtaUsec + } + return 0 +} + +func (m *TaskQueueFetchQueueStatsResponse_QueueStats) GetScannerInfo() *TaskQueueScannerQueueInfo { + if m != nil { + return m.ScannerInfo + } + return nil +} + +type TaskQueuePauseQueueRequest struct { + AppId []byte `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + Pause *bool `protobuf:"varint,3,req,name=pause" json:"pause,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueuePauseQueueRequest) Reset() { *m = TaskQueuePauseQueueRequest{} } +func (m *TaskQueuePauseQueueRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueuePauseQueueRequest) ProtoMessage() {} + +func (m *TaskQueuePauseQueueRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueuePauseQueueRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueuePauseQueueRequest) GetPause() bool { + if m != nil && m.Pause != nil { + return *m.Pause + } + return false +} + +type TaskQueuePauseQueueResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueuePauseQueueResponse) Reset() { *m = TaskQueuePauseQueueResponse{} } +func (m *TaskQueuePauseQueueResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueuePauseQueueResponse) ProtoMessage() {} + +type TaskQueuePurgeQueueRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueuePurgeQueueRequest) Reset() { *m = TaskQueuePurgeQueueRequest{} } +func (m *TaskQueuePurgeQueueRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueuePurgeQueueRequest) ProtoMessage() {} + +func (m *TaskQueuePurgeQueueRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueuePurgeQueueRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +type TaskQueuePurgeQueueResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueuePurgeQueueResponse) Reset() { *m = TaskQueuePurgeQueueResponse{} } +func (m *TaskQueuePurgeQueueResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueuePurgeQueueResponse) ProtoMessage() {} + +type TaskQueueDeleteQueueRequest struct { + AppId []byte `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteQueueRequest) Reset() { *m = TaskQueueDeleteQueueRequest{} } +func (m *TaskQueueDeleteQueueRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteQueueRequest) ProtoMessage() {} + +func (m *TaskQueueDeleteQueueRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueDeleteQueueRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +type TaskQueueDeleteQueueResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteQueueResponse) Reset() { *m = TaskQueueDeleteQueueResponse{} } +func (m *TaskQueueDeleteQueueResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteQueueResponse) ProtoMessage() {} + +type TaskQueueDeleteGroupRequest struct { + AppId []byte `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteGroupRequest) Reset() { *m = TaskQueueDeleteGroupRequest{} } +func (m *TaskQueueDeleteGroupRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteGroupRequest) ProtoMessage() {} + +func (m *TaskQueueDeleteGroupRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +type TaskQueueDeleteGroupResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueDeleteGroupResponse) Reset() { *m = TaskQueueDeleteGroupResponse{} } +func (m *TaskQueueDeleteGroupResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueDeleteGroupResponse) ProtoMessage() {} + +type TaskQueueQueryTasksRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + StartTaskName []byte `protobuf:"bytes,3,opt,name=start_task_name" json:"start_task_name,omitempty"` + StartEtaUsec *int64 `protobuf:"varint,4,opt,name=start_eta_usec" json:"start_eta_usec,omitempty"` + StartTag []byte `protobuf:"bytes,6,opt,name=start_tag" json:"start_tag,omitempty"` + MaxRows *int32 `protobuf:"varint,5,opt,name=max_rows,def=1" json:"max_rows,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksRequest) Reset() { *m = TaskQueueQueryTasksRequest{} } +func (m *TaskQueueQueryTasksRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryTasksRequest) ProtoMessage() {} + +const Default_TaskQueueQueryTasksRequest_MaxRows int32 = 1 + +func (m *TaskQueueQueryTasksRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueQueryTasksRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueQueryTasksRequest) GetStartTaskName() []byte { + if m != nil { + return m.StartTaskName + } + return nil +} + +func (m *TaskQueueQueryTasksRequest) GetStartEtaUsec() int64 { + if m != nil && m.StartEtaUsec != nil { + return *m.StartEtaUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksRequest) GetStartTag() []byte { + if m != nil { + return m.StartTag + } + return nil +} + +func (m *TaskQueueQueryTasksRequest) GetMaxRows() int32 { + if m != nil && m.MaxRows != nil { + return *m.MaxRows + } + return Default_TaskQueueQueryTasksRequest_MaxRows +} + +type TaskQueueQueryTasksResponse struct { + Task []*TaskQueueQueryTasksResponse_Task `protobuf:"group,1,rep,name=Task" json:"task,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksResponse) Reset() { *m = TaskQueueQueryTasksResponse{} } +func (m *TaskQueueQueryTasksResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryTasksResponse) ProtoMessage() {} + +func (m *TaskQueueQueryTasksResponse) GetTask() []*TaskQueueQueryTasksResponse_Task { + if m != nil { + return m.Task + } + return nil +} + +type TaskQueueQueryTasksResponse_Task struct { + TaskName []byte `protobuf:"bytes,2,req,name=task_name" json:"task_name,omitempty"` + EtaUsec *int64 `protobuf:"varint,3,req,name=eta_usec" json:"eta_usec,omitempty"` + Url []byte `protobuf:"bytes,4,opt,name=url" json:"url,omitempty"` + Method *TaskQueueQueryTasksResponse_Task_RequestMethod `protobuf:"varint,5,opt,name=method,enum=appengine.TaskQueueQueryTasksResponse_Task_RequestMethod" json:"method,omitempty"` + RetryCount *int32 `protobuf:"varint,6,opt,name=retry_count,def=0" json:"retry_count,omitempty"` + Header []*TaskQueueQueryTasksResponse_Task_Header `protobuf:"group,7,rep,name=Header" json:"header,omitempty"` + BodySize *int32 `protobuf:"varint,10,opt,name=body_size" json:"body_size,omitempty"` + Body []byte `protobuf:"bytes,11,opt,name=body" json:"body,omitempty"` + CreationTimeUsec *int64 `protobuf:"varint,12,req,name=creation_time_usec" json:"creation_time_usec,omitempty"` + Crontimetable *TaskQueueQueryTasksResponse_Task_CronTimetable `protobuf:"group,13,opt,name=CronTimetable" json:"crontimetable,omitempty"` + Runlog *TaskQueueQueryTasksResponse_Task_RunLog `protobuf:"group,16,opt,name=RunLog" json:"runlog,omitempty"` + Description []byte `protobuf:"bytes,21,opt,name=description" json:"description,omitempty"` + Payload *TaskPayload `protobuf:"bytes,22,opt,name=payload" json:"payload,omitempty"` + RetryParameters *TaskQueueRetryParameters `protobuf:"bytes,23,opt,name=retry_parameters" json:"retry_parameters,omitempty"` + FirstTryUsec *int64 `protobuf:"varint,24,opt,name=first_try_usec" json:"first_try_usec,omitempty"` + Tag []byte `protobuf:"bytes,25,opt,name=tag" json:"tag,omitempty"` + ExecutionCount *int32 `protobuf:"varint,26,opt,name=execution_count,def=0" json:"execution_count,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksResponse_Task) Reset() { *m = TaskQueueQueryTasksResponse_Task{} } +func (m *TaskQueueQueryTasksResponse_Task) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryTasksResponse_Task) ProtoMessage() {} + +const Default_TaskQueueQueryTasksResponse_Task_RetryCount int32 = 0 +const Default_TaskQueueQueryTasksResponse_Task_ExecutionCount int32 = 0 + +func (m *TaskQueueQueryTasksResponse_Task) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetEtaUsec() int64 { + if m != nil && m.EtaUsec != nil { + return *m.EtaUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task) GetUrl() []byte { + if m != nil { + return m.Url + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetMethod() TaskQueueQueryTasksResponse_Task_RequestMethod { + if m != nil && m.Method != nil { + return *m.Method + } + return TaskQueueQueryTasksResponse_Task_GET +} + +func (m *TaskQueueQueryTasksResponse_Task) GetRetryCount() int32 { + if m != nil && m.RetryCount != nil { + return *m.RetryCount + } + return Default_TaskQueueQueryTasksResponse_Task_RetryCount +} + +func (m *TaskQueueQueryTasksResponse_Task) GetHeader() []*TaskQueueQueryTasksResponse_Task_Header { + if m != nil { + return m.Header + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetBodySize() int32 { + if m != nil && m.BodySize != nil { + return *m.BodySize + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetCreationTimeUsec() int64 { + if m != nil && m.CreationTimeUsec != nil { + return *m.CreationTimeUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task) GetCrontimetable() *TaskQueueQueryTasksResponse_Task_CronTimetable { + if m != nil { + return m.Crontimetable + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetRunlog() *TaskQueueQueryTasksResponse_Task_RunLog { + if m != nil { + return m.Runlog + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetDescription() []byte { + if m != nil { + return m.Description + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetPayload() *TaskPayload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetRetryParameters() *TaskQueueRetryParameters { + if m != nil { + return m.RetryParameters + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetFirstTryUsec() int64 { + if m != nil && m.FirstTryUsec != nil { + return *m.FirstTryUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task) GetTag() []byte { + if m != nil { + return m.Tag + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task) GetExecutionCount() int32 { + if m != nil && m.ExecutionCount != nil { + return *m.ExecutionCount + } + return Default_TaskQueueQueryTasksResponse_Task_ExecutionCount +} + +type TaskQueueQueryTasksResponse_Task_Header struct { + Key []byte `protobuf:"bytes,8,req,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,9,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksResponse_Task_Header) Reset() { + *m = TaskQueueQueryTasksResponse_Task_Header{} +} +func (m *TaskQueueQueryTasksResponse_Task_Header) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryTasksResponse_Task_Header) ProtoMessage() {} + +func (m *TaskQueueQueryTasksResponse_Task_Header) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task_Header) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type TaskQueueQueryTasksResponse_Task_CronTimetable struct { + Schedule []byte `protobuf:"bytes,14,req,name=schedule" json:"schedule,omitempty"` + Timezone []byte `protobuf:"bytes,15,req,name=timezone" json:"timezone,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksResponse_Task_CronTimetable) Reset() { + *m = TaskQueueQueryTasksResponse_Task_CronTimetable{} +} +func (m *TaskQueueQueryTasksResponse_Task_CronTimetable) String() string { + return proto.CompactTextString(m) +} +func (*TaskQueueQueryTasksResponse_Task_CronTimetable) ProtoMessage() {} + +func (m *TaskQueueQueryTasksResponse_Task_CronTimetable) GetSchedule() []byte { + if m != nil { + return m.Schedule + } + return nil +} + +func (m *TaskQueueQueryTasksResponse_Task_CronTimetable) GetTimezone() []byte { + if m != nil { + return m.Timezone + } + return nil +} + +type TaskQueueQueryTasksResponse_Task_RunLog struct { + DispatchedUsec *int64 `protobuf:"varint,17,req,name=dispatched_usec" json:"dispatched_usec,omitempty"` + LagUsec *int64 `protobuf:"varint,18,req,name=lag_usec" json:"lag_usec,omitempty"` + ElapsedUsec *int64 `protobuf:"varint,19,req,name=elapsed_usec" json:"elapsed_usec,omitempty"` + ResponseCode *int64 `protobuf:"varint,20,opt,name=response_code" json:"response_code,omitempty"` + RetryReason *string `protobuf:"bytes,27,opt,name=retry_reason" json:"retry_reason,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) Reset() { + *m = TaskQueueQueryTasksResponse_Task_RunLog{} +} +func (m *TaskQueueQueryTasksResponse_Task_RunLog) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryTasksResponse_Task_RunLog) ProtoMessage() {} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) GetDispatchedUsec() int64 { + if m != nil && m.DispatchedUsec != nil { + return *m.DispatchedUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) GetLagUsec() int64 { + if m != nil && m.LagUsec != nil { + return *m.LagUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) GetElapsedUsec() int64 { + if m != nil && m.ElapsedUsec != nil { + return *m.ElapsedUsec + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) GetResponseCode() int64 { + if m != nil && m.ResponseCode != nil { + return *m.ResponseCode + } + return 0 +} + +func (m *TaskQueueQueryTasksResponse_Task_RunLog) GetRetryReason() string { + if m != nil && m.RetryReason != nil { + return *m.RetryReason + } + return "" +} + +type TaskQueueFetchTaskRequest struct { + AppId []byte `protobuf:"bytes,1,opt,name=app_id" json:"app_id,omitempty"` + QueueName []byte `protobuf:"bytes,2,req,name=queue_name" json:"queue_name,omitempty"` + TaskName []byte `protobuf:"bytes,3,req,name=task_name" json:"task_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchTaskRequest) Reset() { *m = TaskQueueFetchTaskRequest{} } +func (m *TaskQueueFetchTaskRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchTaskRequest) ProtoMessage() {} + +func (m *TaskQueueFetchTaskRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueFetchTaskRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueFetchTaskRequest) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +type TaskQueueFetchTaskResponse struct { + Task *TaskQueueQueryTasksResponse `protobuf:"bytes,1,req,name=task" json:"task,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueFetchTaskResponse) Reset() { *m = TaskQueueFetchTaskResponse{} } +func (m *TaskQueueFetchTaskResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueFetchTaskResponse) ProtoMessage() {} + +func (m *TaskQueueFetchTaskResponse) GetTask() *TaskQueueQueryTasksResponse { + if m != nil { + return m.Task + } + return nil +} + +type TaskQueueUpdateStorageLimitRequest struct { + AppId []byte `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + Limit *int64 `protobuf:"varint,2,req,name=limit" json:"limit,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueUpdateStorageLimitRequest) Reset() { *m = TaskQueueUpdateStorageLimitRequest{} } +func (m *TaskQueueUpdateStorageLimitRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueUpdateStorageLimitRequest) ProtoMessage() {} + +func (m *TaskQueueUpdateStorageLimitRequest) GetAppId() []byte { + if m != nil { + return m.AppId + } + return nil +} + +func (m *TaskQueueUpdateStorageLimitRequest) GetLimit() int64 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return 0 +} + +type TaskQueueUpdateStorageLimitResponse struct { + NewLimit *int64 `protobuf:"varint,1,req,name=new_limit" json:"new_limit,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueUpdateStorageLimitResponse) Reset() { *m = TaskQueueUpdateStorageLimitResponse{} } +func (m *TaskQueueUpdateStorageLimitResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueUpdateStorageLimitResponse) ProtoMessage() {} + +func (m *TaskQueueUpdateStorageLimitResponse) GetNewLimit() int64 { + if m != nil && m.NewLimit != nil { + return *m.NewLimit + } + return 0 +} + +type TaskQueueQueryAndOwnTasksRequest struct { + QueueName []byte `protobuf:"bytes,1,req,name=queue_name" json:"queue_name,omitempty"` + LeaseSeconds *float64 `protobuf:"fixed64,2,req,name=lease_seconds" json:"lease_seconds,omitempty"` + MaxTasks *int64 `protobuf:"varint,3,req,name=max_tasks" json:"max_tasks,omitempty"` + GroupByTag *bool `protobuf:"varint,4,opt,name=group_by_tag,def=0" json:"group_by_tag,omitempty"` + Tag []byte `protobuf:"bytes,5,opt,name=tag" json:"tag,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryAndOwnTasksRequest) Reset() { *m = TaskQueueQueryAndOwnTasksRequest{} } +func (m *TaskQueueQueryAndOwnTasksRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryAndOwnTasksRequest) ProtoMessage() {} + +const Default_TaskQueueQueryAndOwnTasksRequest_GroupByTag bool = false + +func (m *TaskQueueQueryAndOwnTasksRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueQueryAndOwnTasksRequest) GetLeaseSeconds() float64 { + if m != nil && m.LeaseSeconds != nil { + return *m.LeaseSeconds + } + return 0 +} + +func (m *TaskQueueQueryAndOwnTasksRequest) GetMaxTasks() int64 { + if m != nil && m.MaxTasks != nil { + return *m.MaxTasks + } + return 0 +} + +func (m *TaskQueueQueryAndOwnTasksRequest) GetGroupByTag() bool { + if m != nil && m.GroupByTag != nil { + return *m.GroupByTag + } + return Default_TaskQueueQueryAndOwnTasksRequest_GroupByTag +} + +func (m *TaskQueueQueryAndOwnTasksRequest) GetTag() []byte { + if m != nil { + return m.Tag + } + return nil +} + +type TaskQueueQueryAndOwnTasksResponse struct { + Task []*TaskQueueQueryAndOwnTasksResponse_Task `protobuf:"group,1,rep,name=Task" json:"task,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryAndOwnTasksResponse) Reset() { *m = TaskQueueQueryAndOwnTasksResponse{} } +func (m *TaskQueueQueryAndOwnTasksResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryAndOwnTasksResponse) ProtoMessage() {} + +func (m *TaskQueueQueryAndOwnTasksResponse) GetTask() []*TaskQueueQueryAndOwnTasksResponse_Task { + if m != nil { + return m.Task + } + return nil +} + +type TaskQueueQueryAndOwnTasksResponse_Task struct { + TaskName []byte `protobuf:"bytes,2,req,name=task_name" json:"task_name,omitempty"` + EtaUsec *int64 `protobuf:"varint,3,req,name=eta_usec" json:"eta_usec,omitempty"` + RetryCount *int32 `protobuf:"varint,4,opt,name=retry_count,def=0" json:"retry_count,omitempty"` + Body []byte `protobuf:"bytes,5,opt,name=body" json:"body,omitempty"` + Tag []byte `protobuf:"bytes,6,opt,name=tag" json:"tag,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) Reset() { + *m = TaskQueueQueryAndOwnTasksResponse_Task{} +} +func (m *TaskQueueQueryAndOwnTasksResponse_Task) String() string { return proto.CompactTextString(m) } +func (*TaskQueueQueryAndOwnTasksResponse_Task) ProtoMessage() {} + +const Default_TaskQueueQueryAndOwnTasksResponse_Task_RetryCount int32 = 0 + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) GetEtaUsec() int64 { + if m != nil && m.EtaUsec != nil { + return *m.EtaUsec + } + return 0 +} + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) GetRetryCount() int32 { + if m != nil && m.RetryCount != nil { + return *m.RetryCount + } + return Default_TaskQueueQueryAndOwnTasksResponse_Task_RetryCount +} + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +func (m *TaskQueueQueryAndOwnTasksResponse_Task) GetTag() []byte { + if m != nil { + return m.Tag + } + return nil +} + +type TaskQueueModifyTaskLeaseRequest struct { + QueueName []byte `protobuf:"bytes,1,req,name=queue_name" json:"queue_name,omitempty"` + TaskName []byte `protobuf:"bytes,2,req,name=task_name" json:"task_name,omitempty"` + EtaUsec *int64 `protobuf:"varint,3,req,name=eta_usec" json:"eta_usec,omitempty"` + LeaseSeconds *float64 `protobuf:"fixed64,4,req,name=lease_seconds" json:"lease_seconds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueModifyTaskLeaseRequest) Reset() { *m = TaskQueueModifyTaskLeaseRequest{} } +func (m *TaskQueueModifyTaskLeaseRequest) String() string { return proto.CompactTextString(m) } +func (*TaskQueueModifyTaskLeaseRequest) ProtoMessage() {} + +func (m *TaskQueueModifyTaskLeaseRequest) GetQueueName() []byte { + if m != nil { + return m.QueueName + } + return nil +} + +func (m *TaskQueueModifyTaskLeaseRequest) GetTaskName() []byte { + if m != nil { + return m.TaskName + } + return nil +} + +func (m *TaskQueueModifyTaskLeaseRequest) GetEtaUsec() int64 { + if m != nil && m.EtaUsec != nil { + return *m.EtaUsec + } + return 0 +} + +func (m *TaskQueueModifyTaskLeaseRequest) GetLeaseSeconds() float64 { + if m != nil && m.LeaseSeconds != nil { + return *m.LeaseSeconds + } + return 0 +} + +type TaskQueueModifyTaskLeaseResponse struct { + UpdatedEtaUsec *int64 `protobuf:"varint,1,req,name=updated_eta_usec" json:"updated_eta_usec,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TaskQueueModifyTaskLeaseResponse) Reset() { *m = TaskQueueModifyTaskLeaseResponse{} } +func (m *TaskQueueModifyTaskLeaseResponse) String() string { return proto.CompactTextString(m) } +func (*TaskQueueModifyTaskLeaseResponse) ProtoMessage() {} + +func (m *TaskQueueModifyTaskLeaseResponse) GetUpdatedEtaUsec() int64 { + if m != nil && m.UpdatedEtaUsec != nil { + return *m.UpdatedEtaUsec + } + return 0 +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto b/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto new file mode 100644 index 000000000..419aaf570 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/taskqueue/taskqueue_service.proto @@ -0,0 +1,342 @@ +syntax = "proto2"; +option go_package = "taskqueue"; + +import "google.golang.org/appengine/internal/datastore/datastore_v3.proto"; + +package appengine; + +message TaskQueueServiceError { + enum ErrorCode { + OK = 0; + UNKNOWN_QUEUE = 1; + TRANSIENT_ERROR = 2; + INTERNAL_ERROR = 3; + TASK_TOO_LARGE = 4; + INVALID_TASK_NAME = 5; + INVALID_QUEUE_NAME = 6; + INVALID_URL = 7; + INVALID_QUEUE_RATE = 8; + PERMISSION_DENIED = 9; + TASK_ALREADY_EXISTS = 10; + TOMBSTONED_TASK = 11; + INVALID_ETA = 12; + INVALID_REQUEST = 13; + UNKNOWN_TASK = 14; + TOMBSTONED_QUEUE = 15; + DUPLICATE_TASK_NAME = 16; + SKIPPED = 17; + TOO_MANY_TASKS = 18; + INVALID_PAYLOAD = 19; + INVALID_RETRY_PARAMETERS = 20; + INVALID_QUEUE_MODE = 21; + ACL_LOOKUP_ERROR = 22; + TRANSACTIONAL_REQUEST_TOO_LARGE = 23; + INCORRECT_CREATOR_NAME = 24; + TASK_LEASE_EXPIRED = 25; + QUEUE_PAUSED = 26; + INVALID_TAG = 27; + + // Reserved range for the Datastore error codes. + // Original Datastore error code is shifted by DATASTORE_ERROR offset. + DATASTORE_ERROR = 10000; + } +} + +message TaskPayload { + extensions 10 to max; + option message_set_wire_format = true; +} + +message TaskQueueRetryParameters { + optional int32 retry_limit = 1; + optional int64 age_limit_sec = 2; + + optional double min_backoff_sec = 3 [default = 0.1]; + optional double max_backoff_sec = 4 [default = 3600]; + optional int32 max_doublings = 5 [default = 16]; +} + +message TaskQueueAcl { + repeated bytes user_email = 1; + repeated bytes writer_email = 2; +} + +message TaskQueueHttpHeader { + required bytes key = 1; + required bytes value = 2; +} + +message TaskQueueMode { + enum Mode { + PUSH = 0; + PULL = 1; + } +} + +message TaskQueueAddRequest { + required bytes queue_name = 1; + required bytes task_name = 2; + required int64 eta_usec = 3; + + enum RequestMethod { + GET = 1; + POST = 2; + HEAD = 3; + PUT = 4; + DELETE = 5; + } + optional RequestMethod method = 5 [default=POST]; + + optional bytes url = 4; + + repeated group Header = 6 { + required bytes key = 7; + required bytes value = 8; + } + + optional bytes body = 9 [ctype=CORD]; + optional Transaction transaction = 10; + optional bytes app_id = 11; + + optional group CronTimetable = 12 { + required bytes schedule = 13; + required bytes timezone = 14; + } + + optional bytes description = 15; + optional TaskPayload payload = 16; + optional TaskQueueRetryParameters retry_parameters = 17; + optional TaskQueueMode.Mode mode = 18 [default=PUSH]; + optional bytes tag = 19; +} + +message TaskQueueAddResponse { + optional bytes chosen_task_name = 1; +} + +message TaskQueueBulkAddRequest { + repeated TaskQueueAddRequest add_request = 1; +} + +message TaskQueueBulkAddResponse { + repeated group TaskResult = 1 { + required TaskQueueServiceError.ErrorCode result = 2; + optional bytes chosen_task_name = 3; + } +} + +message TaskQueueDeleteRequest { + required bytes queue_name = 1; + repeated bytes task_name = 2; + optional bytes app_id = 3; +} + +message TaskQueueDeleteResponse { + repeated TaskQueueServiceError.ErrorCode result = 3; +} + +message TaskQueueForceRunRequest { + optional bytes app_id = 1; + required bytes queue_name = 2; + required bytes task_name = 3; +} + +message TaskQueueForceRunResponse { + required TaskQueueServiceError.ErrorCode result = 3; +} + +message TaskQueueUpdateQueueRequest { + optional bytes app_id = 1; + required bytes queue_name = 2; + required double bucket_refill_per_second = 3; + required int32 bucket_capacity = 4; + optional string user_specified_rate = 5; + optional TaskQueueRetryParameters retry_parameters = 6; + optional int32 max_concurrent_requests = 7; + optional TaskQueueMode.Mode mode = 8 [default = PUSH]; + optional TaskQueueAcl acl = 9; + repeated TaskQueueHttpHeader header_override = 10; +} + +message TaskQueueUpdateQueueResponse { +} + +message TaskQueueFetchQueuesRequest { + optional bytes app_id = 1; + required int32 max_rows = 2; +} + +message TaskQueueFetchQueuesResponse { + repeated group Queue = 1 { + required bytes queue_name = 2; + required double bucket_refill_per_second = 3; + required double bucket_capacity = 4; + optional string user_specified_rate = 5; + required bool paused = 6 [default=false]; + optional TaskQueueRetryParameters retry_parameters = 7; + optional int32 max_concurrent_requests = 8; + optional TaskQueueMode.Mode mode = 9 [default = PUSH]; + optional TaskQueueAcl acl = 10; + repeated TaskQueueHttpHeader header_override = 11; + optional string creator_name = 12 [ctype=CORD, default="apphosting"]; + } +} + +message TaskQueueFetchQueueStatsRequest { + optional bytes app_id = 1; + repeated bytes queue_name = 2; + optional int32 max_num_tasks = 3 [default = 0]; +} + +message TaskQueueScannerQueueInfo { + required int64 executed_last_minute = 1; + required int64 executed_last_hour = 2; + required double sampling_duration_seconds = 3; + optional int32 requests_in_flight = 4; + optional double enforced_rate = 5; +} + +message TaskQueueFetchQueueStatsResponse { + repeated group QueueStats = 1 { + required int32 num_tasks = 2; + required int64 oldest_eta_usec = 3; + optional TaskQueueScannerQueueInfo scanner_info = 4; + } +} +message TaskQueuePauseQueueRequest { + required bytes app_id = 1; + required bytes queue_name = 2; + required bool pause = 3; +} + +message TaskQueuePauseQueueResponse { +} + +message TaskQueuePurgeQueueRequest { + optional bytes app_id = 1; + required bytes queue_name = 2; +} + +message TaskQueuePurgeQueueResponse { +} + +message TaskQueueDeleteQueueRequest { + required bytes app_id = 1; + required bytes queue_name = 2; +} + +message TaskQueueDeleteQueueResponse { +} + +message TaskQueueDeleteGroupRequest { + required bytes app_id = 1; +} + +message TaskQueueDeleteGroupResponse { +} + +message TaskQueueQueryTasksRequest { + optional bytes app_id = 1; + required bytes queue_name = 2; + + optional bytes start_task_name = 3; + optional int64 start_eta_usec = 4; + optional bytes start_tag = 6; + optional int32 max_rows = 5 [default = 1]; +} + +message TaskQueueQueryTasksResponse { + repeated group Task = 1 { + required bytes task_name = 2; + required int64 eta_usec = 3; + optional bytes url = 4; + + enum RequestMethod { + GET = 1; + POST = 2; + HEAD = 3; + PUT = 4; + DELETE = 5; + } + optional RequestMethod method = 5; + + optional int32 retry_count = 6 [default=0]; + + repeated group Header = 7 { + required bytes key = 8; + required bytes value = 9; + } + + optional int32 body_size = 10; + optional bytes body = 11 [ctype=CORD]; + required int64 creation_time_usec = 12; + + optional group CronTimetable = 13 { + required bytes schedule = 14; + required bytes timezone = 15; + } + + optional group RunLog = 16 { + required int64 dispatched_usec = 17; + required int64 lag_usec = 18; + required int64 elapsed_usec = 19; + optional int64 response_code = 20; + optional string retry_reason = 27; + } + + optional bytes description = 21; + optional TaskPayload payload = 22; + optional TaskQueueRetryParameters retry_parameters = 23; + optional int64 first_try_usec = 24; + optional bytes tag = 25; + optional int32 execution_count = 26 [default=0]; + } +} + +message TaskQueueFetchTaskRequest { + optional bytes app_id = 1; + required bytes queue_name = 2; + required bytes task_name = 3; +} + +message TaskQueueFetchTaskResponse { + required TaskQueueQueryTasksResponse task = 1; +} + +message TaskQueueUpdateStorageLimitRequest { + required bytes app_id = 1; + required int64 limit = 2; +} + +message TaskQueueUpdateStorageLimitResponse { + required int64 new_limit = 1; +} + +message TaskQueueQueryAndOwnTasksRequest { + required bytes queue_name = 1; + required double lease_seconds = 2; + required int64 max_tasks = 3; + optional bool group_by_tag = 4 [default=false]; + optional bytes tag = 5; +} + +message TaskQueueQueryAndOwnTasksResponse { + repeated group Task = 1 { + required bytes task_name = 2; + required int64 eta_usec = 3; + optional int32 retry_count = 4 [default=0]; + optional bytes body = 5 [ctype=CORD]; + optional bytes tag = 6; + } +} + +message TaskQueueModifyTaskLeaseRequest { + required bytes queue_name = 1; + required bytes task_name = 2; + required int64 eta_usec = 3; + required double lease_seconds = 4; +} + +message TaskQueueModifyTaskLeaseResponse { + required int64 updated_eta_usec = 1; +} diff --git a/vendor/google.golang.org/appengine/internal/transaction.go b/vendor/google.golang.org/appengine/internal/transaction.go new file mode 100644 index 000000000..28a6d1812 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/transaction.go @@ -0,0 +1,107 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package internal + +// This file implements hooks for applying datastore transactions. + +import ( + "errors" + "reflect" + + "github.com/golang/protobuf/proto" + netcontext "golang.org/x/net/context" + + basepb "google.golang.org/appengine/internal/base" + pb "google.golang.org/appengine/internal/datastore" +) + +var transactionSetters = make(map[reflect.Type]reflect.Value) + +// RegisterTransactionSetter registers a function that sets transaction information +// in a protocol buffer message. f should be a function with two arguments, +// the first being a protocol buffer type, and the second being *datastore.Transaction. +func RegisterTransactionSetter(f interface{}) { + v := reflect.ValueOf(f) + transactionSetters[v.Type().In(0)] = v +} + +// applyTransaction applies the transaction t to message pb +// by using the relevant setter passed to RegisterTransactionSetter. +func applyTransaction(pb proto.Message, t *pb.Transaction) { + v := reflect.ValueOf(pb) + if f, ok := transactionSetters[v.Type()]; ok { + f.Call([]reflect.Value{v, reflect.ValueOf(t)}) + } +} + +var transactionKey = "used for *Transaction" + +func transactionFromContext(ctx netcontext.Context) *transaction { + t, _ := ctx.Value(&transactionKey).(*transaction) + return t +} + +func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context { + return netcontext.WithValue(ctx, &transactionKey, t) +} + +type transaction struct { + transaction pb.Transaction + finished bool +} + +var ErrConcurrentTransaction = errors.New("internal: concurrent transaction") + +func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool) error { + if transactionFromContext(c) != nil { + return errors.New("nested transactions are not supported") + } + + // Begin the transaction. + t := &transaction{} + req := &pb.BeginTransactionRequest{ + App: proto.String(FullyQualifiedAppID(c)), + } + if xg { + req.AllowMultipleEg = proto.Bool(true) + } + if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil { + return err + } + + // Call f, rolling back the transaction if f returns a non-nil error, or panics. + // The panic is not recovered. + defer func() { + if t.finished { + return + } + t.finished = true + // Ignore the error return value, since we are already returning a non-nil + // error (or we're panicking). + Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{}) + }() + if err := f(withTransaction(c, t)); err != nil { + return err + } + t.finished = true + + // Commit the transaction. + res := &pb.CommitResponse{} + err := Call(c, "datastore_v3", "Commit", &t.transaction, res) + if ae, ok := err.(*APIError); ok { + /* TODO: restore this conditional + if appengine.IsDevAppServer() { + */ + // The Python Dev AppServer raises an ApplicationError with error code 2 (which is + // Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.". + if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." { + return ErrConcurrentTransaction + } + if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) { + return ErrConcurrentTransaction + } + } + return err +} diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go new file mode 100644 index 000000000..af463fbb2 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go @@ -0,0 +1,355 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +// DO NOT EDIT! + +/* +Package urlfetch is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto + +It has these top-level messages: + URLFetchServiceError + URLFetchRequest + URLFetchResponse +*/ +package urlfetch + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type URLFetchServiceError_ErrorCode int32 + +const ( + URLFetchServiceError_OK URLFetchServiceError_ErrorCode = 0 + URLFetchServiceError_INVALID_URL URLFetchServiceError_ErrorCode = 1 + URLFetchServiceError_FETCH_ERROR URLFetchServiceError_ErrorCode = 2 + URLFetchServiceError_UNSPECIFIED_ERROR URLFetchServiceError_ErrorCode = 3 + URLFetchServiceError_RESPONSE_TOO_LARGE URLFetchServiceError_ErrorCode = 4 + URLFetchServiceError_DEADLINE_EXCEEDED URLFetchServiceError_ErrorCode = 5 + URLFetchServiceError_SSL_CERTIFICATE_ERROR URLFetchServiceError_ErrorCode = 6 + URLFetchServiceError_DNS_ERROR URLFetchServiceError_ErrorCode = 7 + URLFetchServiceError_CLOSED URLFetchServiceError_ErrorCode = 8 + URLFetchServiceError_INTERNAL_TRANSIENT_ERROR URLFetchServiceError_ErrorCode = 9 + URLFetchServiceError_TOO_MANY_REDIRECTS URLFetchServiceError_ErrorCode = 10 + URLFetchServiceError_MALFORMED_REPLY URLFetchServiceError_ErrorCode = 11 + URLFetchServiceError_CONNECTION_ERROR URLFetchServiceError_ErrorCode = 12 +) + +var URLFetchServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "INVALID_URL", + 2: "FETCH_ERROR", + 3: "UNSPECIFIED_ERROR", + 4: "RESPONSE_TOO_LARGE", + 5: "DEADLINE_EXCEEDED", + 6: "SSL_CERTIFICATE_ERROR", + 7: "DNS_ERROR", + 8: "CLOSED", + 9: "INTERNAL_TRANSIENT_ERROR", + 10: "TOO_MANY_REDIRECTS", + 11: "MALFORMED_REPLY", + 12: "CONNECTION_ERROR", +} +var URLFetchServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "INVALID_URL": 1, + "FETCH_ERROR": 2, + "UNSPECIFIED_ERROR": 3, + "RESPONSE_TOO_LARGE": 4, + "DEADLINE_EXCEEDED": 5, + "SSL_CERTIFICATE_ERROR": 6, + "DNS_ERROR": 7, + "CLOSED": 8, + "INTERNAL_TRANSIENT_ERROR": 9, + "TOO_MANY_REDIRECTS": 10, + "MALFORMED_REPLY": 11, + "CONNECTION_ERROR": 12, +} + +func (x URLFetchServiceError_ErrorCode) Enum() *URLFetchServiceError_ErrorCode { + p := new(URLFetchServiceError_ErrorCode) + *p = x + return p +} +func (x URLFetchServiceError_ErrorCode) String() string { + return proto.EnumName(URLFetchServiceError_ErrorCode_name, int32(x)) +} +func (x *URLFetchServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(URLFetchServiceError_ErrorCode_value, data, "URLFetchServiceError_ErrorCode") + if err != nil { + return err + } + *x = URLFetchServiceError_ErrorCode(value) + return nil +} + +type URLFetchRequest_RequestMethod int32 + +const ( + URLFetchRequest_GET URLFetchRequest_RequestMethod = 1 + URLFetchRequest_POST URLFetchRequest_RequestMethod = 2 + URLFetchRequest_HEAD URLFetchRequest_RequestMethod = 3 + URLFetchRequest_PUT URLFetchRequest_RequestMethod = 4 + URLFetchRequest_DELETE URLFetchRequest_RequestMethod = 5 + URLFetchRequest_PATCH URLFetchRequest_RequestMethod = 6 +) + +var URLFetchRequest_RequestMethod_name = map[int32]string{ + 1: "GET", + 2: "POST", + 3: "HEAD", + 4: "PUT", + 5: "DELETE", + 6: "PATCH", +} +var URLFetchRequest_RequestMethod_value = map[string]int32{ + "GET": 1, + "POST": 2, + "HEAD": 3, + "PUT": 4, + "DELETE": 5, + "PATCH": 6, +} + +func (x URLFetchRequest_RequestMethod) Enum() *URLFetchRequest_RequestMethod { + p := new(URLFetchRequest_RequestMethod) + *p = x + return p +} +func (x URLFetchRequest_RequestMethod) String() string { + return proto.EnumName(URLFetchRequest_RequestMethod_name, int32(x)) +} +func (x *URLFetchRequest_RequestMethod) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(URLFetchRequest_RequestMethod_value, data, "URLFetchRequest_RequestMethod") + if err != nil { + return err + } + *x = URLFetchRequest_RequestMethod(value) + return nil +} + +type URLFetchServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} } +func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) } +func (*URLFetchServiceError) ProtoMessage() {} + +type URLFetchRequest struct { + Method *URLFetchRequest_RequestMethod `protobuf:"varint,1,req,name=Method,enum=appengine.URLFetchRequest_RequestMethod" json:"Method,omitempty"` + Url *string `protobuf:"bytes,2,req,name=Url" json:"Url,omitempty"` + Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header" json:"header,omitempty"` + Payload []byte `protobuf:"bytes,6,opt,name=Payload" json:"Payload,omitempty"` + FollowRedirects *bool `protobuf:"varint,7,opt,name=FollowRedirects,def=1" json:"FollowRedirects,omitempty"` + Deadline *float64 `protobuf:"fixed64,8,opt,name=Deadline" json:"Deadline,omitempty"` + MustValidateServerCertificate *bool `protobuf:"varint,9,opt,name=MustValidateServerCertificate,def=1" json:"MustValidateServerCertificate,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} } +func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) } +func (*URLFetchRequest) ProtoMessage() {} + +const Default_URLFetchRequest_FollowRedirects bool = true +const Default_URLFetchRequest_MustValidateServerCertificate bool = true + +func (m *URLFetchRequest) GetMethod() URLFetchRequest_RequestMethod { + if m != nil && m.Method != nil { + return *m.Method + } + return URLFetchRequest_GET +} + +func (m *URLFetchRequest) GetUrl() string { + if m != nil && m.Url != nil { + return *m.Url + } + return "" +} + +func (m *URLFetchRequest) GetHeader() []*URLFetchRequest_Header { + if m != nil { + return m.Header + } + return nil +} + +func (m *URLFetchRequest) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +func (m *URLFetchRequest) GetFollowRedirects() bool { + if m != nil && m.FollowRedirects != nil { + return *m.FollowRedirects + } + return Default_URLFetchRequest_FollowRedirects +} + +func (m *URLFetchRequest) GetDeadline() float64 { + if m != nil && m.Deadline != nil { + return *m.Deadline + } + return 0 +} + +func (m *URLFetchRequest) GetMustValidateServerCertificate() bool { + if m != nil && m.MustValidateServerCertificate != nil { + return *m.MustValidateServerCertificate + } + return Default_URLFetchRequest_MustValidateServerCertificate +} + +type URLFetchRequest_Header struct { + Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"` + Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} } +func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) } +func (*URLFetchRequest_Header) ProtoMessage() {} + +func (m *URLFetchRequest_Header) GetKey() string { + if m != nil && m.Key != nil { + return *m.Key + } + return "" +} + +func (m *URLFetchRequest_Header) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +type URLFetchResponse struct { + Content []byte `protobuf:"bytes,1,opt,name=Content" json:"Content,omitempty"` + StatusCode *int32 `protobuf:"varint,2,req,name=StatusCode" json:"StatusCode,omitempty"` + Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header" json:"header,omitempty"` + ContentWasTruncated *bool `protobuf:"varint,6,opt,name=ContentWasTruncated,def=0" json:"ContentWasTruncated,omitempty"` + ExternalBytesSent *int64 `protobuf:"varint,7,opt,name=ExternalBytesSent" json:"ExternalBytesSent,omitempty"` + ExternalBytesReceived *int64 `protobuf:"varint,8,opt,name=ExternalBytesReceived" json:"ExternalBytesReceived,omitempty"` + FinalUrl *string `protobuf:"bytes,9,opt,name=FinalUrl" json:"FinalUrl,omitempty"` + ApiCpuMilliseconds *int64 `protobuf:"varint,10,opt,name=ApiCpuMilliseconds,def=0" json:"ApiCpuMilliseconds,omitempty"` + ApiBytesSent *int64 `protobuf:"varint,11,opt,name=ApiBytesSent,def=0" json:"ApiBytesSent,omitempty"` + ApiBytesReceived *int64 `protobuf:"varint,12,opt,name=ApiBytesReceived,def=0" json:"ApiBytesReceived,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} } +func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) } +func (*URLFetchResponse) ProtoMessage() {} + +const Default_URLFetchResponse_ContentWasTruncated bool = false +const Default_URLFetchResponse_ApiCpuMilliseconds int64 = 0 +const Default_URLFetchResponse_ApiBytesSent int64 = 0 +const Default_URLFetchResponse_ApiBytesReceived int64 = 0 + +func (m *URLFetchResponse) GetContent() []byte { + if m != nil { + return m.Content + } + return nil +} + +func (m *URLFetchResponse) GetStatusCode() int32 { + if m != nil && m.StatusCode != nil { + return *m.StatusCode + } + return 0 +} + +func (m *URLFetchResponse) GetHeader() []*URLFetchResponse_Header { + if m != nil { + return m.Header + } + return nil +} + +func (m *URLFetchResponse) GetContentWasTruncated() bool { + if m != nil && m.ContentWasTruncated != nil { + return *m.ContentWasTruncated + } + return Default_URLFetchResponse_ContentWasTruncated +} + +func (m *URLFetchResponse) GetExternalBytesSent() int64 { + if m != nil && m.ExternalBytesSent != nil { + return *m.ExternalBytesSent + } + return 0 +} + +func (m *URLFetchResponse) GetExternalBytesReceived() int64 { + if m != nil && m.ExternalBytesReceived != nil { + return *m.ExternalBytesReceived + } + return 0 +} + +func (m *URLFetchResponse) GetFinalUrl() string { + if m != nil && m.FinalUrl != nil { + return *m.FinalUrl + } + return "" +} + +func (m *URLFetchResponse) GetApiCpuMilliseconds() int64 { + if m != nil && m.ApiCpuMilliseconds != nil { + return *m.ApiCpuMilliseconds + } + return Default_URLFetchResponse_ApiCpuMilliseconds +} + +func (m *URLFetchResponse) GetApiBytesSent() int64 { + if m != nil && m.ApiBytesSent != nil { + return *m.ApiBytesSent + } + return Default_URLFetchResponse_ApiBytesSent +} + +func (m *URLFetchResponse) GetApiBytesReceived() int64 { + if m != nil && m.ApiBytesReceived != nil { + return *m.ApiBytesReceived + } + return Default_URLFetchResponse_ApiBytesReceived +} + +type URLFetchResponse_Header struct { + Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"` + Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} } +func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) } +func (*URLFetchResponse_Header) ProtoMessage() {} + +func (m *URLFetchResponse_Header) GetKey() string { + if m != nil && m.Key != nil { + return *m.Key + } + return "" +} + +func (m *URLFetchResponse_Header) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto new file mode 100644 index 000000000..f695edf6a --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto @@ -0,0 +1,64 @@ +syntax = "proto2"; +option go_package = "urlfetch"; + +package appengine; + +message URLFetchServiceError { + enum ErrorCode { + OK = 0; + INVALID_URL = 1; + FETCH_ERROR = 2; + UNSPECIFIED_ERROR = 3; + RESPONSE_TOO_LARGE = 4; + DEADLINE_EXCEEDED = 5; + SSL_CERTIFICATE_ERROR = 6; + DNS_ERROR = 7; + CLOSED = 8; + INTERNAL_TRANSIENT_ERROR = 9; + TOO_MANY_REDIRECTS = 10; + MALFORMED_REPLY = 11; + CONNECTION_ERROR = 12; + } +} + +message URLFetchRequest { + enum RequestMethod { + GET = 1; + POST = 2; + HEAD = 3; + PUT = 4; + DELETE = 5; + PATCH = 6; + } + required RequestMethod Method = 1; + required string Url = 2; + repeated group Header = 3 { + required string Key = 4; + required string Value = 5; + } + optional bytes Payload = 6 [ctype=CORD]; + + optional bool FollowRedirects = 7 [default=true]; + + optional double Deadline = 8; + + optional bool MustValidateServerCertificate = 9 [default=true]; +} + +message URLFetchResponse { + optional bytes Content = 1; + required int32 StatusCode = 2; + repeated group Header = 3 { + required string Key = 4; + required string Value = 5; + } + optional bool ContentWasTruncated = 6 [default=false]; + optional int64 ExternalBytesSent = 7; + optional int64 ExternalBytesReceived = 8; + + optional string FinalUrl = 9; + + optional int64 ApiCpuMilliseconds = 10 [default=0]; + optional int64 ApiBytesSent = 11 [default=0]; + optional int64 ApiBytesReceived = 12 [default=0]; +} diff --git a/vendor/google.golang.org/appengine/internal/user/user_service.pb.go b/vendor/google.golang.org/appengine/internal/user/user_service.pb.go new file mode 100644 index 000000000..6b52ffcce --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/user/user_service.pb.go @@ -0,0 +1,289 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/user/user_service.proto +// DO NOT EDIT! + +/* +Package user is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/user/user_service.proto + +It has these top-level messages: + UserServiceError + CreateLoginURLRequest + CreateLoginURLResponse + CreateLogoutURLRequest + CreateLogoutURLResponse + GetOAuthUserRequest + GetOAuthUserResponse + CheckOAuthSignatureRequest + CheckOAuthSignatureResponse +*/ +package user + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type UserServiceError_ErrorCode int32 + +const ( + UserServiceError_OK UserServiceError_ErrorCode = 0 + UserServiceError_REDIRECT_URL_TOO_LONG UserServiceError_ErrorCode = 1 + UserServiceError_NOT_ALLOWED UserServiceError_ErrorCode = 2 + UserServiceError_OAUTH_INVALID_TOKEN UserServiceError_ErrorCode = 3 + UserServiceError_OAUTH_INVALID_REQUEST UserServiceError_ErrorCode = 4 + UserServiceError_OAUTH_ERROR UserServiceError_ErrorCode = 5 +) + +var UserServiceError_ErrorCode_name = map[int32]string{ + 0: "OK", + 1: "REDIRECT_URL_TOO_LONG", + 2: "NOT_ALLOWED", + 3: "OAUTH_INVALID_TOKEN", + 4: "OAUTH_INVALID_REQUEST", + 5: "OAUTH_ERROR", +} +var UserServiceError_ErrorCode_value = map[string]int32{ + "OK": 0, + "REDIRECT_URL_TOO_LONG": 1, + "NOT_ALLOWED": 2, + "OAUTH_INVALID_TOKEN": 3, + "OAUTH_INVALID_REQUEST": 4, + "OAUTH_ERROR": 5, +} + +func (x UserServiceError_ErrorCode) Enum() *UserServiceError_ErrorCode { + p := new(UserServiceError_ErrorCode) + *p = x + return p +} +func (x UserServiceError_ErrorCode) String() string { + return proto.EnumName(UserServiceError_ErrorCode_name, int32(x)) +} +func (x *UserServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(UserServiceError_ErrorCode_value, data, "UserServiceError_ErrorCode") + if err != nil { + return err + } + *x = UserServiceError_ErrorCode(value) + return nil +} + +type UserServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *UserServiceError) Reset() { *m = UserServiceError{} } +func (m *UserServiceError) String() string { return proto.CompactTextString(m) } +func (*UserServiceError) ProtoMessage() {} + +type CreateLoginURLRequest struct { + DestinationUrl *string `protobuf:"bytes,1,req,name=destination_url" json:"destination_url,omitempty"` + AuthDomain *string `protobuf:"bytes,2,opt,name=auth_domain" json:"auth_domain,omitempty"` + FederatedIdentity *string `protobuf:"bytes,3,opt,name=federated_identity,def=" json:"federated_identity,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateLoginURLRequest) Reset() { *m = CreateLoginURLRequest{} } +func (m *CreateLoginURLRequest) String() string { return proto.CompactTextString(m) } +func (*CreateLoginURLRequest) ProtoMessage() {} + +func (m *CreateLoginURLRequest) GetDestinationUrl() string { + if m != nil && m.DestinationUrl != nil { + return *m.DestinationUrl + } + return "" +} + +func (m *CreateLoginURLRequest) GetAuthDomain() string { + if m != nil && m.AuthDomain != nil { + return *m.AuthDomain + } + return "" +} + +func (m *CreateLoginURLRequest) GetFederatedIdentity() string { + if m != nil && m.FederatedIdentity != nil { + return *m.FederatedIdentity + } + return "" +} + +type CreateLoginURLResponse struct { + LoginUrl *string `protobuf:"bytes,1,req,name=login_url" json:"login_url,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateLoginURLResponse) Reset() { *m = CreateLoginURLResponse{} } +func (m *CreateLoginURLResponse) String() string { return proto.CompactTextString(m) } +func (*CreateLoginURLResponse) ProtoMessage() {} + +func (m *CreateLoginURLResponse) GetLoginUrl() string { + if m != nil && m.LoginUrl != nil { + return *m.LoginUrl + } + return "" +} + +type CreateLogoutURLRequest struct { + DestinationUrl *string `protobuf:"bytes,1,req,name=destination_url" json:"destination_url,omitempty"` + AuthDomain *string `protobuf:"bytes,2,opt,name=auth_domain" json:"auth_domain,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateLogoutURLRequest) Reset() { *m = CreateLogoutURLRequest{} } +func (m *CreateLogoutURLRequest) String() string { return proto.CompactTextString(m) } +func (*CreateLogoutURLRequest) ProtoMessage() {} + +func (m *CreateLogoutURLRequest) GetDestinationUrl() string { + if m != nil && m.DestinationUrl != nil { + return *m.DestinationUrl + } + return "" +} + +func (m *CreateLogoutURLRequest) GetAuthDomain() string { + if m != nil && m.AuthDomain != nil { + return *m.AuthDomain + } + return "" +} + +type CreateLogoutURLResponse struct { + LogoutUrl *string `protobuf:"bytes,1,req,name=logout_url" json:"logout_url,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CreateLogoutURLResponse) Reset() { *m = CreateLogoutURLResponse{} } +func (m *CreateLogoutURLResponse) String() string { return proto.CompactTextString(m) } +func (*CreateLogoutURLResponse) ProtoMessage() {} + +func (m *CreateLogoutURLResponse) GetLogoutUrl() string { + if m != nil && m.LogoutUrl != nil { + return *m.LogoutUrl + } + return "" +} + +type GetOAuthUserRequest struct { + Scope *string `protobuf:"bytes,1,opt,name=scope" json:"scope,omitempty"` + Scopes []string `protobuf:"bytes,2,rep,name=scopes" json:"scopes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetOAuthUserRequest) Reset() { *m = GetOAuthUserRequest{} } +func (m *GetOAuthUserRequest) String() string { return proto.CompactTextString(m) } +func (*GetOAuthUserRequest) ProtoMessage() {} + +func (m *GetOAuthUserRequest) GetScope() string { + if m != nil && m.Scope != nil { + return *m.Scope + } + return "" +} + +func (m *GetOAuthUserRequest) GetScopes() []string { + if m != nil { + return m.Scopes + } + return nil +} + +type GetOAuthUserResponse struct { + Email *string `protobuf:"bytes,1,req,name=email" json:"email,omitempty"` + UserId *string `protobuf:"bytes,2,req,name=user_id" json:"user_id,omitempty"` + AuthDomain *string `protobuf:"bytes,3,req,name=auth_domain" json:"auth_domain,omitempty"` + UserOrganization *string `protobuf:"bytes,4,opt,name=user_organization,def=" json:"user_organization,omitempty"` + IsAdmin *bool `protobuf:"varint,5,opt,name=is_admin,def=0" json:"is_admin,omitempty"` + ClientId *string `protobuf:"bytes,6,opt,name=client_id,def=" json:"client_id,omitempty"` + Scopes []string `protobuf:"bytes,7,rep,name=scopes" json:"scopes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetOAuthUserResponse) Reset() { *m = GetOAuthUserResponse{} } +func (m *GetOAuthUserResponse) String() string { return proto.CompactTextString(m) } +func (*GetOAuthUserResponse) ProtoMessage() {} + +const Default_GetOAuthUserResponse_IsAdmin bool = false + +func (m *GetOAuthUserResponse) GetEmail() string { + if m != nil && m.Email != nil { + return *m.Email + } + return "" +} + +func (m *GetOAuthUserResponse) GetUserId() string { + if m != nil && m.UserId != nil { + return *m.UserId + } + return "" +} + +func (m *GetOAuthUserResponse) GetAuthDomain() string { + if m != nil && m.AuthDomain != nil { + return *m.AuthDomain + } + return "" +} + +func (m *GetOAuthUserResponse) GetUserOrganization() string { + if m != nil && m.UserOrganization != nil { + return *m.UserOrganization + } + return "" +} + +func (m *GetOAuthUserResponse) GetIsAdmin() bool { + if m != nil && m.IsAdmin != nil { + return *m.IsAdmin + } + return Default_GetOAuthUserResponse_IsAdmin +} + +func (m *GetOAuthUserResponse) GetClientId() string { + if m != nil && m.ClientId != nil { + return *m.ClientId + } + return "" +} + +func (m *GetOAuthUserResponse) GetScopes() []string { + if m != nil { + return m.Scopes + } + return nil +} + +type CheckOAuthSignatureRequest struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *CheckOAuthSignatureRequest) Reset() { *m = CheckOAuthSignatureRequest{} } +func (m *CheckOAuthSignatureRequest) String() string { return proto.CompactTextString(m) } +func (*CheckOAuthSignatureRequest) ProtoMessage() {} + +type CheckOAuthSignatureResponse struct { + OauthConsumerKey *string `protobuf:"bytes,1,req,name=oauth_consumer_key" json:"oauth_consumer_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CheckOAuthSignatureResponse) Reset() { *m = CheckOAuthSignatureResponse{} } +func (m *CheckOAuthSignatureResponse) String() string { return proto.CompactTextString(m) } +func (*CheckOAuthSignatureResponse) ProtoMessage() {} + +func (m *CheckOAuthSignatureResponse) GetOauthConsumerKey() string { + if m != nil && m.OauthConsumerKey != nil { + return *m.OauthConsumerKey + } + return "" +} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/user/user_service.proto b/vendor/google.golang.org/appengine/internal/user/user_service.proto new file mode 100644 index 000000000..f3e969346 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/user/user_service.proto @@ -0,0 +1,58 @@ +syntax = "proto2"; +option go_package = "user"; + +package appengine; + +message UserServiceError { + enum ErrorCode { + OK = 0; + REDIRECT_URL_TOO_LONG = 1; + NOT_ALLOWED = 2; + OAUTH_INVALID_TOKEN = 3; + OAUTH_INVALID_REQUEST = 4; + OAUTH_ERROR = 5; + } +} + +message CreateLoginURLRequest { + required string destination_url = 1; + optional string auth_domain = 2; + optional string federated_identity = 3 [default = ""]; +} + +message CreateLoginURLResponse { + required string login_url = 1; +} + +message CreateLogoutURLRequest { + required string destination_url = 1; + optional string auth_domain = 2; +} + +message CreateLogoutURLResponse { + required string logout_url = 1; +} + +message GetOAuthUserRequest { + optional string scope = 1; + + repeated string scopes = 2; +} + +message GetOAuthUserResponse { + required string email = 1; + required string user_id = 2; + required string auth_domain = 3; + optional string user_organization = 4 [default = ""]; + optional bool is_admin = 5 [default = false]; + optional string client_id = 6 [default = ""]; + + repeated string scopes = 7; +} + +message CheckOAuthSignatureRequest { +} + +message CheckOAuthSignatureResponse { + required string oauth_consumer_key = 1; +} diff --git a/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.pb.go b/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.pb.go new file mode 100644 index 000000000..6d5b0ae65 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.pb.go @@ -0,0 +1,427 @@ +// Code generated by protoc-gen-go. +// source: google.golang.org/appengine/internal/xmpp/xmpp_service.proto +// DO NOT EDIT! + +/* +Package xmpp is a generated protocol buffer package. + +It is generated from these files: + google.golang.org/appengine/internal/xmpp/xmpp_service.proto + +It has these top-level messages: + XmppServiceError + PresenceRequest + PresenceResponse + BulkPresenceRequest + BulkPresenceResponse + XmppMessageRequest + XmppMessageResponse + XmppSendPresenceRequest + XmppSendPresenceResponse + XmppInviteRequest + XmppInviteResponse +*/ +package xmpp + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type XmppServiceError_ErrorCode int32 + +const ( + XmppServiceError_UNSPECIFIED_ERROR XmppServiceError_ErrorCode = 1 + XmppServiceError_INVALID_JID XmppServiceError_ErrorCode = 2 + XmppServiceError_NO_BODY XmppServiceError_ErrorCode = 3 + XmppServiceError_INVALID_XML XmppServiceError_ErrorCode = 4 + XmppServiceError_INVALID_TYPE XmppServiceError_ErrorCode = 5 + XmppServiceError_INVALID_SHOW XmppServiceError_ErrorCode = 6 + XmppServiceError_EXCEEDED_MAX_SIZE XmppServiceError_ErrorCode = 7 + XmppServiceError_APPID_ALIAS_REQUIRED XmppServiceError_ErrorCode = 8 + XmppServiceError_NONDEFAULT_MODULE XmppServiceError_ErrorCode = 9 +) + +var XmppServiceError_ErrorCode_name = map[int32]string{ + 1: "UNSPECIFIED_ERROR", + 2: "INVALID_JID", + 3: "NO_BODY", + 4: "INVALID_XML", + 5: "INVALID_TYPE", + 6: "INVALID_SHOW", + 7: "EXCEEDED_MAX_SIZE", + 8: "APPID_ALIAS_REQUIRED", + 9: "NONDEFAULT_MODULE", +} +var XmppServiceError_ErrorCode_value = map[string]int32{ + "UNSPECIFIED_ERROR": 1, + "INVALID_JID": 2, + "NO_BODY": 3, + "INVALID_XML": 4, + "INVALID_TYPE": 5, + "INVALID_SHOW": 6, + "EXCEEDED_MAX_SIZE": 7, + "APPID_ALIAS_REQUIRED": 8, + "NONDEFAULT_MODULE": 9, +} + +func (x XmppServiceError_ErrorCode) Enum() *XmppServiceError_ErrorCode { + p := new(XmppServiceError_ErrorCode) + *p = x + return p +} +func (x XmppServiceError_ErrorCode) String() string { + return proto.EnumName(XmppServiceError_ErrorCode_name, int32(x)) +} +func (x *XmppServiceError_ErrorCode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(XmppServiceError_ErrorCode_value, data, "XmppServiceError_ErrorCode") + if err != nil { + return err + } + *x = XmppServiceError_ErrorCode(value) + return nil +} + +type PresenceResponse_SHOW int32 + +const ( + PresenceResponse_NORMAL PresenceResponse_SHOW = 0 + PresenceResponse_AWAY PresenceResponse_SHOW = 1 + PresenceResponse_DO_NOT_DISTURB PresenceResponse_SHOW = 2 + PresenceResponse_CHAT PresenceResponse_SHOW = 3 + PresenceResponse_EXTENDED_AWAY PresenceResponse_SHOW = 4 +) + +var PresenceResponse_SHOW_name = map[int32]string{ + 0: "NORMAL", + 1: "AWAY", + 2: "DO_NOT_DISTURB", + 3: "CHAT", + 4: "EXTENDED_AWAY", +} +var PresenceResponse_SHOW_value = map[string]int32{ + "NORMAL": 0, + "AWAY": 1, + "DO_NOT_DISTURB": 2, + "CHAT": 3, + "EXTENDED_AWAY": 4, +} + +func (x PresenceResponse_SHOW) Enum() *PresenceResponse_SHOW { + p := new(PresenceResponse_SHOW) + *p = x + return p +} +func (x PresenceResponse_SHOW) String() string { + return proto.EnumName(PresenceResponse_SHOW_name, int32(x)) +} +func (x *PresenceResponse_SHOW) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PresenceResponse_SHOW_value, data, "PresenceResponse_SHOW") + if err != nil { + return err + } + *x = PresenceResponse_SHOW(value) + return nil +} + +type XmppMessageResponse_XmppMessageStatus int32 + +const ( + XmppMessageResponse_NO_ERROR XmppMessageResponse_XmppMessageStatus = 0 + XmppMessageResponse_INVALID_JID XmppMessageResponse_XmppMessageStatus = 1 + XmppMessageResponse_OTHER_ERROR XmppMessageResponse_XmppMessageStatus = 2 +) + +var XmppMessageResponse_XmppMessageStatus_name = map[int32]string{ + 0: "NO_ERROR", + 1: "INVALID_JID", + 2: "OTHER_ERROR", +} +var XmppMessageResponse_XmppMessageStatus_value = map[string]int32{ + "NO_ERROR": 0, + "INVALID_JID": 1, + "OTHER_ERROR": 2, +} + +func (x XmppMessageResponse_XmppMessageStatus) Enum() *XmppMessageResponse_XmppMessageStatus { + p := new(XmppMessageResponse_XmppMessageStatus) + *p = x + return p +} +func (x XmppMessageResponse_XmppMessageStatus) String() string { + return proto.EnumName(XmppMessageResponse_XmppMessageStatus_name, int32(x)) +} +func (x *XmppMessageResponse_XmppMessageStatus) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(XmppMessageResponse_XmppMessageStatus_value, data, "XmppMessageResponse_XmppMessageStatus") + if err != nil { + return err + } + *x = XmppMessageResponse_XmppMessageStatus(value) + return nil +} + +type XmppServiceError struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppServiceError) Reset() { *m = XmppServiceError{} } +func (m *XmppServiceError) String() string { return proto.CompactTextString(m) } +func (*XmppServiceError) ProtoMessage() {} + +type PresenceRequest struct { + Jid *string `protobuf:"bytes,1,req,name=jid" json:"jid,omitempty"` + FromJid *string `protobuf:"bytes,2,opt,name=from_jid" json:"from_jid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PresenceRequest) Reset() { *m = PresenceRequest{} } +func (m *PresenceRequest) String() string { return proto.CompactTextString(m) } +func (*PresenceRequest) ProtoMessage() {} + +func (m *PresenceRequest) GetJid() string { + if m != nil && m.Jid != nil { + return *m.Jid + } + return "" +} + +func (m *PresenceRequest) GetFromJid() string { + if m != nil && m.FromJid != nil { + return *m.FromJid + } + return "" +} + +type PresenceResponse struct { + IsAvailable *bool `protobuf:"varint,1,req,name=is_available" json:"is_available,omitempty"` + Presence *PresenceResponse_SHOW `protobuf:"varint,2,opt,name=presence,enum=appengine.PresenceResponse_SHOW" json:"presence,omitempty"` + Valid *bool `protobuf:"varint,3,opt,name=valid" json:"valid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PresenceResponse) Reset() { *m = PresenceResponse{} } +func (m *PresenceResponse) String() string { return proto.CompactTextString(m) } +func (*PresenceResponse) ProtoMessage() {} + +func (m *PresenceResponse) GetIsAvailable() bool { + if m != nil && m.IsAvailable != nil { + return *m.IsAvailable + } + return false +} + +func (m *PresenceResponse) GetPresence() PresenceResponse_SHOW { + if m != nil && m.Presence != nil { + return *m.Presence + } + return PresenceResponse_NORMAL +} + +func (m *PresenceResponse) GetValid() bool { + if m != nil && m.Valid != nil { + return *m.Valid + } + return false +} + +type BulkPresenceRequest struct { + Jid []string `protobuf:"bytes,1,rep,name=jid" json:"jid,omitempty"` + FromJid *string `protobuf:"bytes,2,opt,name=from_jid" json:"from_jid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BulkPresenceRequest) Reset() { *m = BulkPresenceRequest{} } +func (m *BulkPresenceRequest) String() string { return proto.CompactTextString(m) } +func (*BulkPresenceRequest) ProtoMessage() {} + +func (m *BulkPresenceRequest) GetJid() []string { + if m != nil { + return m.Jid + } + return nil +} + +func (m *BulkPresenceRequest) GetFromJid() string { + if m != nil && m.FromJid != nil { + return *m.FromJid + } + return "" +} + +type BulkPresenceResponse struct { + PresenceResponse []*PresenceResponse `protobuf:"bytes,1,rep,name=presence_response" json:"presence_response,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BulkPresenceResponse) Reset() { *m = BulkPresenceResponse{} } +func (m *BulkPresenceResponse) String() string { return proto.CompactTextString(m) } +func (*BulkPresenceResponse) ProtoMessage() {} + +func (m *BulkPresenceResponse) GetPresenceResponse() []*PresenceResponse { + if m != nil { + return m.PresenceResponse + } + return nil +} + +type XmppMessageRequest struct { + Jid []string `protobuf:"bytes,1,rep,name=jid" json:"jid,omitempty"` + Body *string `protobuf:"bytes,2,req,name=body" json:"body,omitempty"` + RawXml *bool `protobuf:"varint,3,opt,name=raw_xml,def=0" json:"raw_xml,omitempty"` + Type *string `protobuf:"bytes,4,opt,name=type,def=chat" json:"type,omitempty"` + FromJid *string `protobuf:"bytes,5,opt,name=from_jid" json:"from_jid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppMessageRequest) Reset() { *m = XmppMessageRequest{} } +func (m *XmppMessageRequest) String() string { return proto.CompactTextString(m) } +func (*XmppMessageRequest) ProtoMessage() {} + +const Default_XmppMessageRequest_RawXml bool = false +const Default_XmppMessageRequest_Type string = "chat" + +func (m *XmppMessageRequest) GetJid() []string { + if m != nil { + return m.Jid + } + return nil +} + +func (m *XmppMessageRequest) GetBody() string { + if m != nil && m.Body != nil { + return *m.Body + } + return "" +} + +func (m *XmppMessageRequest) GetRawXml() bool { + if m != nil && m.RawXml != nil { + return *m.RawXml + } + return Default_XmppMessageRequest_RawXml +} + +func (m *XmppMessageRequest) GetType() string { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_XmppMessageRequest_Type +} + +func (m *XmppMessageRequest) GetFromJid() string { + if m != nil && m.FromJid != nil { + return *m.FromJid + } + return "" +} + +type XmppMessageResponse struct { + Status []XmppMessageResponse_XmppMessageStatus `protobuf:"varint,1,rep,name=status,enum=appengine.XmppMessageResponse_XmppMessageStatus" json:"status,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppMessageResponse) Reset() { *m = XmppMessageResponse{} } +func (m *XmppMessageResponse) String() string { return proto.CompactTextString(m) } +func (*XmppMessageResponse) ProtoMessage() {} + +func (m *XmppMessageResponse) GetStatus() []XmppMessageResponse_XmppMessageStatus { + if m != nil { + return m.Status + } + return nil +} + +type XmppSendPresenceRequest struct { + Jid *string `protobuf:"bytes,1,req,name=jid" json:"jid,omitempty"` + Type *string `protobuf:"bytes,2,opt,name=type" json:"type,omitempty"` + Show *string `protobuf:"bytes,3,opt,name=show" json:"show,omitempty"` + Status *string `protobuf:"bytes,4,opt,name=status" json:"status,omitempty"` + FromJid *string `protobuf:"bytes,5,opt,name=from_jid" json:"from_jid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppSendPresenceRequest) Reset() { *m = XmppSendPresenceRequest{} } +func (m *XmppSendPresenceRequest) String() string { return proto.CompactTextString(m) } +func (*XmppSendPresenceRequest) ProtoMessage() {} + +func (m *XmppSendPresenceRequest) GetJid() string { + if m != nil && m.Jid != nil { + return *m.Jid + } + return "" +} + +func (m *XmppSendPresenceRequest) GetType() string { + if m != nil && m.Type != nil { + return *m.Type + } + return "" +} + +func (m *XmppSendPresenceRequest) GetShow() string { + if m != nil && m.Show != nil { + return *m.Show + } + return "" +} + +func (m *XmppSendPresenceRequest) GetStatus() string { + if m != nil && m.Status != nil { + return *m.Status + } + return "" +} + +func (m *XmppSendPresenceRequest) GetFromJid() string { + if m != nil && m.FromJid != nil { + return *m.FromJid + } + return "" +} + +type XmppSendPresenceResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppSendPresenceResponse) Reset() { *m = XmppSendPresenceResponse{} } +func (m *XmppSendPresenceResponse) String() string { return proto.CompactTextString(m) } +func (*XmppSendPresenceResponse) ProtoMessage() {} + +type XmppInviteRequest struct { + Jid *string `protobuf:"bytes,1,req,name=jid" json:"jid,omitempty"` + FromJid *string `protobuf:"bytes,2,opt,name=from_jid" json:"from_jid,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppInviteRequest) Reset() { *m = XmppInviteRequest{} } +func (m *XmppInviteRequest) String() string { return proto.CompactTextString(m) } +func (*XmppInviteRequest) ProtoMessage() {} + +func (m *XmppInviteRequest) GetJid() string { + if m != nil && m.Jid != nil { + return *m.Jid + } + return "" +} + +func (m *XmppInviteRequest) GetFromJid() string { + if m != nil && m.FromJid != nil { + return *m.FromJid + } + return "" +} + +type XmppInviteResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *XmppInviteResponse) Reset() { *m = XmppInviteResponse{} } +func (m *XmppInviteResponse) String() string { return proto.CompactTextString(m) } +func (*XmppInviteResponse) ProtoMessage() {} + +func init() { +} diff --git a/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.proto b/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.proto new file mode 100644 index 000000000..472d52ebf --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/xmpp/xmpp_service.proto @@ -0,0 +1,83 @@ +syntax = "proto2"; +option go_package = "xmpp"; + +package appengine; + +message XmppServiceError { + enum ErrorCode { + UNSPECIFIED_ERROR = 1; + INVALID_JID = 2; + NO_BODY = 3; + INVALID_XML = 4; + INVALID_TYPE = 5; + INVALID_SHOW = 6; + EXCEEDED_MAX_SIZE = 7; + APPID_ALIAS_REQUIRED = 8; + NONDEFAULT_MODULE = 9; + } +} + +message PresenceRequest { + required string jid = 1; + optional string from_jid = 2; +} + +message PresenceResponse { + enum SHOW { + NORMAL = 0; + AWAY = 1; + DO_NOT_DISTURB = 2; + CHAT = 3; + EXTENDED_AWAY = 4; + } + + required bool is_available = 1; + optional SHOW presence = 2; + optional bool valid = 3; +} + +message BulkPresenceRequest { + repeated string jid = 1; + optional string from_jid = 2; +} + +message BulkPresenceResponse { + repeated PresenceResponse presence_response = 1; +} + +message XmppMessageRequest { + repeated string jid = 1; + required string body = 2; + optional bool raw_xml = 3 [ default = false ]; + optional string type = 4 [ default = "chat" ]; + optional string from_jid = 5; +} + +message XmppMessageResponse { + enum XmppMessageStatus { + NO_ERROR = 0; + INVALID_JID = 1; + OTHER_ERROR = 2; + } + + repeated XmppMessageStatus status = 1; +} + +message XmppSendPresenceRequest { + required string jid = 1; + optional string type = 2; + optional string show = 3; + optional string status = 4; + optional string from_jid = 5; +} + +message XmppSendPresenceResponse { +} + +message XmppInviteRequest { + required string jid = 1; + optional string from_jid = 2; +} + +message XmppInviteResponse { +} diff --git a/vendor/google.golang.org/appengine/log/api.go b/vendor/google.golang.org/appengine/log/api.go new file mode 100644 index 000000000..24d58601b --- /dev/null +++ b/vendor/google.golang.org/appengine/log/api.go @@ -0,0 +1,40 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package log + +// This file implements the logging API. + +import ( + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" +) + +// Debugf formats its arguments according to the format, analogous to fmt.Printf, +// and records the text as a log message at Debug level. The message will be associated +// with the request linked with the provided context. +func Debugf(ctx context.Context, format string, args ...interface{}) { + internal.Logf(ctx, 0, format, args...) +} + +// Infof is like Debugf, but at Info level. +func Infof(ctx context.Context, format string, args ...interface{}) { + internal.Logf(ctx, 1, format, args...) +} + +// Warningf is like Debugf, but at Warning level. +func Warningf(ctx context.Context, format string, args ...interface{}) { + internal.Logf(ctx, 2, format, args...) +} + +// Errorf is like Debugf, but at Error level. +func Errorf(ctx context.Context, format string, args ...interface{}) { + internal.Logf(ctx, 3, format, args...) +} + +// Criticalf is like Debugf, but at Critical level. +func Criticalf(ctx context.Context, format string, args ...interface{}) { + internal.Logf(ctx, 4, format, args...) +} diff --git a/vendor/google.golang.org/appengine/log/log.go b/vendor/google.golang.org/appengine/log/log.go new file mode 100644 index 000000000..cd89e5ced --- /dev/null +++ b/vendor/google.golang.org/appengine/log/log.go @@ -0,0 +1,323 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package log provides the means of querying an application's logs from +within an App Engine application. + +Example: + c := appengine.NewContext(r) + query := &log.Query{ + AppLogs: true, + Versions: []string{"1"}, + } + + for results := query.Run(c); ; { + record, err := results.Next() + if err == log.Done { + log.Infof(c, "Done processing results") + break + } + if err != nil { + log.Errorf(c, "Failed to retrieve next log: %v", err) + break + } + log.Infof(c, "Saw record %v", record) + } +*/ +package log + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/log" +) + +// Query defines a logs query. +type Query struct { + // Start time specifies the earliest log to return (inclusive). + StartTime time.Time + + // End time specifies the latest log to return (exclusive). + EndTime time.Time + + // Offset specifies a position within the log stream to resume reading from, + // and should come from a previously returned Record's field of the same name. + Offset []byte + + // Incomplete controls whether active (incomplete) requests should be included. + Incomplete bool + + // AppLogs indicates if application-level logs should be included. + AppLogs bool + + // ApplyMinLevel indicates if MinLevel should be used to filter results. + ApplyMinLevel bool + + // If ApplyMinLevel is true, only logs for requests with at least one + // application log of MinLevel or higher will be returned. + MinLevel int + + // Versions is the major version IDs whose logs should be retrieved. + // Logs for specific modules can be retrieved by the specifying versions + // in the form "module:version"; the default module is used if no module + // is specified. + Versions []string + + // A list of requests to search for instead of a time-based scan. Cannot be + // combined with filtering options such as StartTime, EndTime, Offset, + // Incomplete, ApplyMinLevel, or Versions. + RequestIDs []string +} + +// AppLog represents a single application-level log. +type AppLog struct { + Time time.Time + Level int + Message string +} + +// Record contains all the information for a single web request. +type Record struct { + AppID string + ModuleID string + VersionID string + RequestID []byte + IP string + Nickname string + AppEngineRelease string + + // The time when this request started. + StartTime time.Time + + // The time when this request finished. + EndTime time.Time + + // Opaque cursor into the result stream. + Offset []byte + + // The time required to process the request. + Latency time.Duration + MCycles int64 + Method string + Resource string + HTTPVersion string + Status int32 + + // The size of the request sent back to the client, in bytes. + ResponseSize int64 + Referrer string + UserAgent string + URLMapEntry string + Combined string + Host string + + // The estimated cost of this request, in dollars. + Cost float64 + TaskQueueName string + TaskName string + WasLoadingRequest bool + PendingTime time.Duration + Finished bool + AppLogs []AppLog + + // Mostly-unique identifier for the instance that handled the request if available. + InstanceID string +} + +// Result represents the result of a query. +type Result struct { + logs []*Record + context context.Context + request *pb.LogReadRequest + resultsSeen bool + err error +} + +// Next returns the next log record, +func (qr *Result) Next() (*Record, error) { + if qr.err != nil { + return nil, qr.err + } + if len(qr.logs) > 0 { + lr := qr.logs[0] + qr.logs = qr.logs[1:] + return lr, nil + } + + if qr.request.Offset == nil && qr.resultsSeen { + return nil, Done + } + + if err := qr.run(); err != nil { + // Errors here may be retried, so don't store the error. + return nil, err + } + + return qr.Next() +} + +// Done is returned when a query iteration has completed. +var Done = errors.New("log: query has no more results") + +// protoToAppLogs takes as input an array of pointers to LogLines, the internal +// Protocol Buffer representation of a single application-level log, +// and converts it to an array of AppLogs, the external representation +// of an application-level log. +func protoToAppLogs(logLines []*pb.LogLine) []AppLog { + appLogs := make([]AppLog, len(logLines)) + + for i, line := range logLines { + appLogs[i] = AppLog{ + Time: time.Unix(0, *line.Time*1e3), + Level: int(*line.Level), + Message: *line.LogMessage, + } + } + + return appLogs +} + +// protoToRecord converts a RequestLog, the internal Protocol Buffer +// representation of a single request-level log, to a Record, its +// corresponding external representation. +func protoToRecord(rl *pb.RequestLog) *Record { + offset, err := proto.Marshal(rl.Offset) + if err != nil { + offset = nil + } + return &Record{ + AppID: *rl.AppId, + ModuleID: rl.GetModuleId(), + VersionID: *rl.VersionId, + RequestID: rl.RequestId, + Offset: offset, + IP: *rl.Ip, + Nickname: rl.GetNickname(), + AppEngineRelease: string(rl.GetAppEngineRelease()), + StartTime: time.Unix(0, *rl.StartTime*1e3), + EndTime: time.Unix(0, *rl.EndTime*1e3), + Latency: time.Duration(*rl.Latency) * time.Microsecond, + MCycles: *rl.Mcycles, + Method: *rl.Method, + Resource: *rl.Resource, + HTTPVersion: *rl.HttpVersion, + Status: *rl.Status, + ResponseSize: *rl.ResponseSize, + Referrer: rl.GetReferrer(), + UserAgent: rl.GetUserAgent(), + URLMapEntry: *rl.UrlMapEntry, + Combined: *rl.Combined, + Host: rl.GetHost(), + Cost: rl.GetCost(), + TaskQueueName: rl.GetTaskQueueName(), + TaskName: rl.GetTaskName(), + WasLoadingRequest: rl.GetWasLoadingRequest(), + PendingTime: time.Duration(rl.GetPendingTime()) * time.Microsecond, + Finished: rl.GetFinished(), + AppLogs: protoToAppLogs(rl.Line), + InstanceID: string(rl.GetCloneKey()), + } +} + +// Run starts a query for log records, which contain request and application +// level log information. +func (params *Query) Run(c context.Context) *Result { + req, err := makeRequest(params, internal.FullyQualifiedAppID(c), appengine.VersionID(c)) + return &Result{ + context: c, + request: req, + err: err, + } +} + +func makeRequest(params *Query, appID, versionID string) (*pb.LogReadRequest, error) { + req := &pb.LogReadRequest{} + req.AppId = &appID + if !params.StartTime.IsZero() { + req.StartTime = proto.Int64(params.StartTime.UnixNano() / 1e3) + } + if !params.EndTime.IsZero() { + req.EndTime = proto.Int64(params.EndTime.UnixNano() / 1e3) + } + if len(params.Offset) > 0 { + var offset pb.LogOffset + if err := proto.Unmarshal(params.Offset, &offset); err != nil { + return nil, fmt.Errorf("bad Offset: %v", err) + } + req.Offset = &offset + } + if params.Incomplete { + req.IncludeIncomplete = ¶ms.Incomplete + } + if params.AppLogs { + req.IncludeAppLogs = ¶ms.AppLogs + } + if params.ApplyMinLevel { + req.MinimumLogLevel = proto.Int32(int32(params.MinLevel)) + } + if params.Versions == nil { + // If no versions were specified, default to the default module at + // the major version being used by this module. + if i := strings.Index(versionID, "."); i >= 0 { + versionID = versionID[:i] + } + req.VersionId = []string{versionID} + } else { + req.ModuleVersion = make([]*pb.LogModuleVersion, 0, len(params.Versions)) + for _, v := range params.Versions { + var m *string + if i := strings.Index(v, ":"); i >= 0 { + m, v = proto.String(v[:i]), v[i+1:] + } + req.ModuleVersion = append(req.ModuleVersion, &pb.LogModuleVersion{ + ModuleId: m, + VersionId: proto.String(v), + }) + } + } + if params.RequestIDs != nil { + ids := make([][]byte, len(params.RequestIDs)) + for i, v := range params.RequestIDs { + ids[i] = []byte(v) + } + req.RequestId = ids + } + + return req, nil +} + +// run takes the query Result produced by a call to Run and updates it with +// more Records. The updated Result contains a new set of logs as well as an +// offset to where more logs can be found. We also convert the items in the +// response from their internal representations to external versions of the +// same structs. +func (r *Result) run() error { + res := &pb.LogReadResponse{} + if err := internal.Call(r.context, "logservice", "Read", r.request, res); err != nil { + return err + } + + r.logs = make([]*Record, len(res.Log)) + r.request.Offset = res.Offset + r.resultsSeen = true + + for i, log := range res.Log { + r.logs[i] = protoToRecord(log) + } + + return nil +} + +func init() { + internal.RegisterErrorCodeMap("logservice", pb.LogServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/mail/mail.go b/vendor/google.golang.org/appengine/mail/mail.go new file mode 100644 index 000000000..be0eb518c --- /dev/null +++ b/vendor/google.golang.org/appengine/mail/mail.go @@ -0,0 +1,123 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package mail provides the means of sending email from an +App Engine application. + +Example: + msg := &mail.Message{ + Sender: "romeo@montague.com", + To: []string{"Juliet "}, + Subject: "See you tonight", + Body: "Don't forget our plans. Hark, 'til later.", + } + if err := mail.Send(c, msg); err != nil { + log.Errorf(c, "Alas, my user, the email failed to sendeth: %v", err) + } +*/ +package mail + +import ( + "net/mail" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + bpb "google.golang.org/appengine/internal/base" + pb "google.golang.org/appengine/internal/mail" +) + +// A Message represents an email message. +// Addresses may be of any form permitted by RFC 822. +type Message struct { + // Sender must be set, and must be either an application admin + // or the currently signed-in user. + Sender string + ReplyTo string // may be empty + + // At least one of these slices must have a non-zero length, + // except when calling SendToAdmins. + To, Cc, Bcc []string + + Subject string + + // At least one of Body or HTMLBody must be non-empty. + Body string + HTMLBody string + + Attachments []Attachment + + // Extra mail headers. + // See https://cloud.google.com/appengine/docs/go/mail/ + // for permissible headers. + Headers mail.Header +} + +// An Attachment represents an email attachment. +type Attachment struct { + // Name must be set to a valid file name. + Name string + Data []byte + ContentID string +} + +// Send sends an email message. +func Send(c context.Context, msg *Message) error { + return send(c, "Send", msg) +} + +// SendToAdmins sends an email message to the application's administrators. +func SendToAdmins(c context.Context, msg *Message) error { + return send(c, "SendToAdmins", msg) +} + +func send(c context.Context, method string, msg *Message) error { + req := &pb.MailMessage{ + Sender: &msg.Sender, + To: msg.To, + Cc: msg.Cc, + Bcc: msg.Bcc, + Subject: &msg.Subject, + } + if msg.ReplyTo != "" { + req.ReplyTo = &msg.ReplyTo + } + if msg.Body != "" { + req.TextBody = &msg.Body + } + if msg.HTMLBody != "" { + req.HtmlBody = &msg.HTMLBody + } + if len(msg.Attachments) > 0 { + req.Attachment = make([]*pb.MailAttachment, len(msg.Attachments)) + for i, att := range msg.Attachments { + req.Attachment[i] = &pb.MailAttachment{ + FileName: proto.String(att.Name), + Data: att.Data, + } + if att.ContentID != "" { + req.Attachment[i].ContentID = proto.String(att.ContentID) + } + } + } + for key, vs := range msg.Headers { + for _, v := range vs { + req.Header = append(req.Header, &pb.MailHeader{ + Name: proto.String(key), + Value: proto.String(v), + }) + } + } + res := &bpb.VoidProto{} + if err := internal.Call(c, "mail", method, req, res); err != nil { + return err + } + return nil +} + +func init() { + internal.RegisterErrorCodeMap("mail", pb.MailServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/memcache/memcache.go b/vendor/google.golang.org/appengine/memcache/memcache.go new file mode 100644 index 000000000..515505504 --- /dev/null +++ b/vendor/google.golang.org/appengine/memcache/memcache.go @@ -0,0 +1,526 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package memcache provides a client for App Engine's distributed in-memory +// key-value store for small chunks of arbitrary data. +// +// The fundamental operations get and set items, keyed by a string. +// +// item0, err := memcache.Get(c, "key") +// if err != nil && err != memcache.ErrCacheMiss { +// return err +// } +// if err == nil { +// fmt.Fprintf(w, "memcache hit: Key=%q Val=[% x]\n", item0.Key, item0.Value) +// } else { +// fmt.Fprintf(w, "memcache miss\n") +// } +// +// and +// +// item1 := &memcache.Item{ +// Key: "foo", +// Value: []byte("bar"), +// } +// if err := memcache.Set(c, item1); err != nil { +// return err +// } +package memcache + +import ( + "bytes" + "encoding/gob" + "encoding/json" + "errors" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/memcache" +) + +var ( + // ErrCacheMiss means that an operation failed + // because the item wasn't present. + ErrCacheMiss = errors.New("memcache: cache miss") + // ErrCASConflict means that a CompareAndSwap call failed due to the + // cached value being modified between the Get and the CompareAndSwap. + // If the cached value was simply evicted rather than replaced, + // ErrNotStored will be returned instead. + ErrCASConflict = errors.New("memcache: compare-and-swap conflict") + // ErrNoStats means that no statistics were available. + ErrNoStats = errors.New("memcache: no statistics available") + // ErrNotStored means that a conditional write operation (i.e. Add or + // CompareAndSwap) failed because the condition was not satisfied. + ErrNotStored = errors.New("memcache: item not stored") + // ErrServerError means that a server error occurred. + ErrServerError = errors.New("memcache: server error") +) + +// Item is the unit of memcache gets and sets. +type Item struct { + // Key is the Item's key (250 bytes maximum). + Key string + // Value is the Item's value. + Value []byte + // Object is the Item's value for use with a Codec. + Object interface{} + // Flags are server-opaque flags whose semantics are entirely up to the + // App Engine app. + Flags uint32 + // Expiration is the maximum duration that the item will stay + // in the cache. + // The zero value means the Item has no expiration time. + // Subsecond precision is ignored. + // This is not set when getting items. + Expiration time.Duration + // casID is a client-opaque value used for compare-and-swap operations. + // Zero means that compare-and-swap is not used. + casID uint64 +} + +const ( + secondsIn30Years = 60 * 60 * 24 * 365 * 30 // from memcache server code + thirtyYears = time.Duration(secondsIn30Years) * time.Second +) + +// protoToItem converts a protocol buffer item to a Go struct. +func protoToItem(p *pb.MemcacheGetResponse_Item) *Item { + return &Item{ + Key: string(p.Key), + Value: p.Value, + Flags: p.GetFlags(), + casID: p.GetCasId(), + } +} + +// If err is an appengine.MultiError, return its first element. Otherwise, return err. +func singleError(err error) error { + if me, ok := err.(appengine.MultiError); ok { + return me[0] + } + return err +} + +// Get gets the item for the given key. ErrCacheMiss is returned for a memcache +// cache miss. The key must be at most 250 bytes in length. +func Get(c context.Context, key string) (*Item, error) { + m, err := GetMulti(c, []string{key}) + if err != nil { + return nil, err + } + if _, ok := m[key]; !ok { + return nil, ErrCacheMiss + } + return m[key], nil +} + +// GetMulti is a batch version of Get. The returned map from keys to items may +// have fewer elements than the input slice, due to memcache cache misses. +// Each key must be at most 250 bytes in length. +func GetMulti(c context.Context, key []string) (map[string]*Item, error) { + if len(key) == 0 { + return nil, nil + } + keyAsBytes := make([][]byte, len(key)) + for i, k := range key { + keyAsBytes[i] = []byte(k) + } + req := &pb.MemcacheGetRequest{ + Key: keyAsBytes, + ForCas: proto.Bool(true), + } + res := &pb.MemcacheGetResponse{} + if err := internal.Call(c, "memcache", "Get", req, res); err != nil { + return nil, err + } + m := make(map[string]*Item, len(res.Item)) + for _, p := range res.Item { + t := protoToItem(p) + m[t.Key] = t + } + return m, nil +} + +// Delete deletes the item for the given key. +// ErrCacheMiss is returned if the specified item can not be found. +// The key must be at most 250 bytes in length. +func Delete(c context.Context, key string) error { + return singleError(DeleteMulti(c, []string{key})) +} + +// DeleteMulti is a batch version of Delete. +// If any keys cannot be found, an appengine.MultiError is returned. +// Each key must be at most 250 bytes in length. +func DeleteMulti(c context.Context, key []string) error { + if len(key) == 0 { + return nil + } + req := &pb.MemcacheDeleteRequest{ + Item: make([]*pb.MemcacheDeleteRequest_Item, len(key)), + } + for i, k := range key { + req.Item[i] = &pb.MemcacheDeleteRequest_Item{Key: []byte(k)} + } + res := &pb.MemcacheDeleteResponse{} + if err := internal.Call(c, "memcache", "Delete", req, res); err != nil { + return err + } + if len(res.DeleteStatus) != len(key) { + return ErrServerError + } + me, any := make(appengine.MultiError, len(key)), false + for i, s := range res.DeleteStatus { + switch s { + case pb.MemcacheDeleteResponse_DELETED: + // OK + case pb.MemcacheDeleteResponse_NOT_FOUND: + me[i] = ErrCacheMiss + any = true + default: + me[i] = ErrServerError + any = true + } + } + if any { + return me + } + return nil +} + +// Increment atomically increments the decimal value in the given key +// by delta and returns the new value. The value must fit in a uint64. +// Overflow wraps around, and underflow is capped to zero. The +// provided delta may be negative. If the key doesn't exist in +// memcache, the provided initial value is used to atomically +// populate it before the delta is applied. +// The key must be at most 250 bytes in length. +func Increment(c context.Context, key string, delta int64, initialValue uint64) (newValue uint64, err error) { + return incr(c, key, delta, &initialValue) +} + +// IncrementExisting works like Increment but assumes that the key +// already exists in memcache and doesn't take an initial value. +// IncrementExisting can save work if calculating the initial value is +// expensive. +// An error is returned if the specified item can not be found. +func IncrementExisting(c context.Context, key string, delta int64) (newValue uint64, err error) { + return incr(c, key, delta, nil) +} + +func incr(c context.Context, key string, delta int64, initialValue *uint64) (newValue uint64, err error) { + req := &pb.MemcacheIncrementRequest{ + Key: []byte(key), + InitialValue: initialValue, + } + if delta >= 0 { + req.Delta = proto.Uint64(uint64(delta)) + } else { + req.Delta = proto.Uint64(uint64(-delta)) + req.Direction = pb.MemcacheIncrementRequest_DECREMENT.Enum() + } + res := &pb.MemcacheIncrementResponse{} + err = internal.Call(c, "memcache", "Increment", req, res) + if err != nil { + return + } + if res.NewValue == nil { + return 0, ErrCacheMiss + } + return *res.NewValue, nil +} + +// set sets the given items using the given conflict resolution policy. +// appengine.MultiError may be returned. +func set(c context.Context, item []*Item, value [][]byte, policy pb.MemcacheSetRequest_SetPolicy) error { + if len(item) == 0 { + return nil + } + req := &pb.MemcacheSetRequest{ + Item: make([]*pb.MemcacheSetRequest_Item, len(item)), + } + for i, t := range item { + p := &pb.MemcacheSetRequest_Item{ + Key: []byte(t.Key), + } + if value == nil { + p.Value = t.Value + } else { + p.Value = value[i] + } + if t.Flags != 0 { + p.Flags = proto.Uint32(t.Flags) + } + if t.Expiration != 0 { + // In the .proto file, MemcacheSetRequest_Item uses a fixed32 (i.e. unsigned) + // for expiration time, while MemcacheGetRequest_Item uses int32 (i.e. signed). + // Throughout this .go file, we use int32. + // Also, in the proto, the expiration value is either a duration (in seconds) + // or an absolute Unix timestamp (in seconds), depending on whether the + // value is less than or greater than or equal to 30 years, respectively. + if t.Expiration < time.Second { + // Because an Expiration of 0 means no expiration, we take + // care here to translate an item with an expiration + // Duration between 0-1 seconds as immediately expiring + // (saying it expired a few seconds ago), rather than + // rounding it down to 0 and making it live forever. + p.ExpirationTime = proto.Uint32(uint32(time.Now().Unix()) - 5) + } else if t.Expiration >= thirtyYears { + p.ExpirationTime = proto.Uint32(uint32(time.Now().Unix()) + uint32(t.Expiration/time.Second)) + } else { + p.ExpirationTime = proto.Uint32(uint32(t.Expiration / time.Second)) + } + } + if t.casID != 0 { + p.CasId = proto.Uint64(t.casID) + p.ForCas = proto.Bool(true) + } + p.SetPolicy = policy.Enum() + req.Item[i] = p + } + res := &pb.MemcacheSetResponse{} + if err := internal.Call(c, "memcache", "Set", req, res); err != nil { + return err + } + if len(res.SetStatus) != len(item) { + return ErrServerError + } + me, any := make(appengine.MultiError, len(item)), false + for i, st := range res.SetStatus { + var err error + switch st { + case pb.MemcacheSetResponse_STORED: + // OK + case pb.MemcacheSetResponse_NOT_STORED: + err = ErrNotStored + case pb.MemcacheSetResponse_EXISTS: + err = ErrCASConflict + default: + err = ErrServerError + } + if err != nil { + me[i] = err + any = true + } + } + if any { + return me + } + return nil +} + +// Set writes the given item, unconditionally. +func Set(c context.Context, item *Item) error { + return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_SET)) +} + +// SetMulti is a batch version of Set. +// appengine.MultiError may be returned. +func SetMulti(c context.Context, item []*Item) error { + return set(c, item, nil, pb.MemcacheSetRequest_SET) +} + +// Add writes the given item, if no value already exists for its key. +// ErrNotStored is returned if that condition is not met. +func Add(c context.Context, item *Item) error { + return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_ADD)) +} + +// AddMulti is a batch version of Add. +// appengine.MultiError may be returned. +func AddMulti(c context.Context, item []*Item) error { + return set(c, item, nil, pb.MemcacheSetRequest_ADD) +} + +// CompareAndSwap writes the given item that was previously returned by Get, +// if the value was neither modified or evicted between the Get and the +// CompareAndSwap calls. The item's Key should not change between calls but +// all other item fields may differ. +// ErrCASConflict is returned if the value was modified in between the calls. +// ErrNotStored is returned if the value was evicted in between the calls. +func CompareAndSwap(c context.Context, item *Item) error { + return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_CAS)) +} + +// CompareAndSwapMulti is a batch version of CompareAndSwap. +// appengine.MultiError may be returned. +func CompareAndSwapMulti(c context.Context, item []*Item) error { + return set(c, item, nil, pb.MemcacheSetRequest_CAS) +} + +// Codec represents a symmetric pair of functions that implement a codec. +// Items stored into or retrieved from memcache using a Codec have their +// values marshaled or unmarshaled. +// +// All the methods provided for Codec behave analogously to the package level +// function with same name. +type Codec struct { + Marshal func(interface{}) ([]byte, error) + Unmarshal func([]byte, interface{}) error +} + +// Get gets the item for the given key and decodes the obtained value into v. +// ErrCacheMiss is returned for a memcache cache miss. +// The key must be at most 250 bytes in length. +func (cd Codec) Get(c context.Context, key string, v interface{}) (*Item, error) { + i, err := Get(c, key) + if err != nil { + return nil, err + } + if err := cd.Unmarshal(i.Value, v); err != nil { + return nil, err + } + return i, nil +} + +func (cd Codec) set(c context.Context, items []*Item, policy pb.MemcacheSetRequest_SetPolicy) error { + var vs [][]byte + var me appengine.MultiError + for i, item := range items { + v, err := cd.Marshal(item.Object) + if err != nil { + if me == nil { + me = make(appengine.MultiError, len(items)) + } + me[i] = err + continue + } + if me == nil { + vs = append(vs, v) + } + } + if me != nil { + return me + } + + return set(c, items, vs, policy) +} + +// Set writes the given item, unconditionally. +func (cd Codec) Set(c context.Context, item *Item) error { + return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_SET)) +} + +// SetMulti is a batch version of Set. +// appengine.MultiError may be returned. +func (cd Codec) SetMulti(c context.Context, items []*Item) error { + return cd.set(c, items, pb.MemcacheSetRequest_SET) +} + +// Add writes the given item, if no value already exists for its key. +// ErrNotStored is returned if that condition is not met. +func (cd Codec) Add(c context.Context, item *Item) error { + return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_ADD)) +} + +// AddMulti is a batch version of Add. +// appengine.MultiError may be returned. +func (cd Codec) AddMulti(c context.Context, items []*Item) error { + return cd.set(c, items, pb.MemcacheSetRequest_ADD) +} + +// CompareAndSwap writes the given item that was previously returned by Get, +// if the value was neither modified or evicted between the Get and the +// CompareAndSwap calls. The item's Key should not change between calls but +// all other item fields may differ. +// ErrCASConflict is returned if the value was modified in between the calls. +// ErrNotStored is returned if the value was evicted in between the calls. +func (cd Codec) CompareAndSwap(c context.Context, item *Item) error { + return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_CAS)) +} + +// CompareAndSwapMulti is a batch version of CompareAndSwap. +// appengine.MultiError may be returned. +func (cd Codec) CompareAndSwapMulti(c context.Context, items []*Item) error { + return cd.set(c, items, pb.MemcacheSetRequest_CAS) +} + +var ( + // Gob is a Codec that uses the gob package. + Gob = Codec{gobMarshal, gobUnmarshal} + // JSON is a Codec that uses the json package. + JSON = Codec{json.Marshal, json.Unmarshal} +) + +func gobMarshal(v interface{}) ([]byte, error) { + var buf bytes.Buffer + if err := gob.NewEncoder(&buf).Encode(v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func gobUnmarshal(data []byte, v interface{}) error { + return gob.NewDecoder(bytes.NewBuffer(data)).Decode(v) +} + +// Statistics represents a set of statistics about the memcache cache. +// This may include items that have expired but have not yet been removed from the cache. +type Statistics struct { + Hits uint64 // Counter of cache hits + Misses uint64 // Counter of cache misses + ByteHits uint64 // Counter of bytes transferred for gets + + Items uint64 // Items currently in the cache + Bytes uint64 // Size of all items currently in the cache + + Oldest int64 // Age of access of the oldest item, in seconds +} + +// Stats retrieves the current memcache statistics. +func Stats(c context.Context) (*Statistics, error) { + req := &pb.MemcacheStatsRequest{} + res := &pb.MemcacheStatsResponse{} + if err := internal.Call(c, "memcache", "Stats", req, res); err != nil { + return nil, err + } + if res.Stats == nil { + return nil, ErrNoStats + } + return &Statistics{ + Hits: *res.Stats.Hits, + Misses: *res.Stats.Misses, + ByteHits: *res.Stats.ByteHits, + Items: *res.Stats.Items, + Bytes: *res.Stats.Bytes, + Oldest: int64(*res.Stats.OldestItemAge), + }, nil +} + +// Flush flushes all items from memcache. +func Flush(c context.Context) error { + req := &pb.MemcacheFlushRequest{} + res := &pb.MemcacheFlushResponse{} + return internal.Call(c, "memcache", "FlushAll", req, res) +} + +func namespaceMod(m proto.Message, namespace string) { + switch m := m.(type) { + case *pb.MemcacheDeleteRequest: + if m.NameSpace == nil { + m.NameSpace = &namespace + } + case *pb.MemcacheGetRequest: + if m.NameSpace == nil { + m.NameSpace = &namespace + } + case *pb.MemcacheIncrementRequest: + if m.NameSpace == nil { + m.NameSpace = &namespace + } + case *pb.MemcacheSetRequest: + if m.NameSpace == nil { + m.NameSpace = &namespace + } + // MemcacheFlushRequest, MemcacheStatsRequest do not apply namespace. + } +} + +func init() { + internal.RegisterErrorCodeMap("memcache", pb.MemcacheServiceError_ErrorCode_name) + internal.NamespaceMods["memcache"] = namespaceMod +} diff --git a/vendor/google.golang.org/appengine/module/module.go b/vendor/google.golang.org/appengine/module/module.go new file mode 100644 index 000000000..aaf020cc4 --- /dev/null +++ b/vendor/google.golang.org/appengine/module/module.go @@ -0,0 +1,113 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package module provides functions for interacting with modules. + +The appengine package contains functions that report the identity of the app, +including the module name. +*/ +package module + +import ( + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/modules" +) + +// List returns the names of modules belonging to this application. +func List(c context.Context) ([]string, error) { + req := &pb.GetModulesRequest{} + res := &pb.GetModulesResponse{} + err := internal.Call(c, "modules", "GetModules", req, res) + return res.Module, err +} + +// NumInstances returns the number of instances of the given module/version. +// If either argument is the empty string it means the default. +func NumInstances(c context.Context, module, version string) (int, error) { + req := &pb.GetNumInstancesRequest{} + if module != "" { + req.Module = &module + } + if version != "" { + req.Version = &version + } + res := &pb.GetNumInstancesResponse{} + + if err := internal.Call(c, "modules", "GetNumInstances", req, res); err != nil { + return 0, err + } + return int(*res.Instances), nil +} + +// SetNumInstances sets the number of instances of the given module.version to the +// specified value. If either module or version are the empty string it means the +// default. +func SetNumInstances(c context.Context, module, version string, instances int) error { + req := &pb.SetNumInstancesRequest{} + if module != "" { + req.Module = &module + } + if version != "" { + req.Version = &version + } + req.Instances = proto.Int64(int64(instances)) + res := &pb.SetNumInstancesResponse{} + return internal.Call(c, "modules", "SetNumInstances", req, res) +} + +// Versions returns the names of the versions that belong to the specified module. +// If module is the empty string, it means the default module. +func Versions(c context.Context, module string) ([]string, error) { + req := &pb.GetVersionsRequest{} + if module != "" { + req.Module = &module + } + res := &pb.GetVersionsResponse{} + err := internal.Call(c, "modules", "GetVersions", req, res) + return res.GetVersion(), err +} + +// DefaultVersion returns the default version of the specified module. +// If module is the empty string, it means the default module. +func DefaultVersion(c context.Context, module string) (string, error) { + req := &pb.GetDefaultVersionRequest{} + if module != "" { + req.Module = &module + } + res := &pb.GetDefaultVersionResponse{} + err := internal.Call(c, "modules", "GetDefaultVersion", req, res) + return res.GetVersion(), err +} + +// Start starts the specified version of the specified module. +// If either module or version are the empty string, it means the default. +func Start(c context.Context, module, version string) error { + req := &pb.StartModuleRequest{} + if module != "" { + req.Module = &module + } + if version != "" { + req.Version = &version + } + res := &pb.StartModuleResponse{} + return internal.Call(c, "modules", "StartModule", req, res) +} + +// Stop stops the specified version of the specified module. +// If either module or version are the empty string, it means the default. +func Stop(c context.Context, module, version string) error { + req := &pb.StopModuleRequest{} + if module != "" { + req.Module = &module + } + if version != "" { + req.Version = &version + } + res := &pb.StopModuleResponse{} + return internal.Call(c, "modules", "StopModule", req, res) +} diff --git a/vendor/google.golang.org/appengine/namespace.go b/vendor/google.golang.org/appengine/namespace.go new file mode 100644 index 000000000..21860ca08 --- /dev/null +++ b/vendor/google.golang.org/appengine/namespace.go @@ -0,0 +1,25 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package appengine + +import ( + "fmt" + "regexp" + + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" +) + +// Namespace returns a replacement context that operates within the given namespace. +func Namespace(c context.Context, namespace string) (context.Context, error) { + if !validNamespace.MatchString(namespace) { + return nil, fmt.Errorf("appengine: namespace %q does not match /%s/", namespace, validNamespace) + } + return internal.NamespacedContext(c, namespace), nil +} + +// validNamespace matches valid namespace names. +var validNamespace = regexp.MustCompile(`^[0-9A-Za-z._-]{0,100}$`) diff --git a/vendor/google.golang.org/appengine/remote_api/client.go b/vendor/google.golang.org/appengine/remote_api/client.go new file mode 100644 index 000000000..dbe219dbb --- /dev/null +++ b/vendor/google.golang.org/appengine/remote_api/client.go @@ -0,0 +1,174 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package remote_api + +// This file provides the client for connecting remotely to a user's production +// application. + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "math/rand" + "net/http" + "net/url" + "regexp" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/remote_api" +) + +// NewRemoteContext returns a context that gives access to the production +// APIs for the application at the given host. All communication will be +// performed over SSL unless the host is localhost. +func NewRemoteContext(host string, client *http.Client) (context.Context, error) { + // Add an appcfg header to outgoing requests. + t := client.Transport + if t == nil { + t = http.DefaultTransport + } + client.Transport = &headerAddingRoundTripper{t} + + url := url.URL{ + Scheme: "https", + Host: host, + Path: "/_ah/remote_api", + } + if host == "localhost" || strings.HasPrefix(host, "localhost:") { + url.Scheme = "http" + } + u := url.String() + appID, err := getAppID(client, u) + if err != nil { + return nil, fmt.Errorf("unable to contact server: %v", err) + } + rc := &remoteContext{ + client: client, + url: u, + } + ctx := internal.WithCallOverride(context.Background(), rc.call) + ctx = internal.WithLogOverride(ctx, rc.logf) + ctx = internal.WithAppIDOverride(ctx, appID) + return ctx, nil +} + +type remoteContext struct { + client *http.Client + url string +} + +var logLevels = map[int64]string{ + 0: "DEBUG", + 1: "INFO", + 2: "WARNING", + 3: "ERROR", + 4: "CRITICAL", +} + +func (c *remoteContext) logf(level int64, format string, args ...interface{}) { + log.Printf(logLevels[level]+": "+format, args...) +} + +func (c *remoteContext) call(ctx context.Context, service, method string, in, out proto.Message) error { + req, err := proto.Marshal(in) + if err != nil { + return fmt.Errorf("error marshalling request: %v", err) + } + + remReq := &pb.Request{ + ServiceName: proto.String(service), + Method: proto.String(method), + Request: req, + // NOTE(djd): RequestId is unused in the server. + } + + req, err = proto.Marshal(remReq) + if err != nil { + return fmt.Errorf("proto.Marshal: %v", err) + } + + // TODO(djd): Respect ctx.Deadline()? + resp, err := c.client.Post(c.url, "application/octet-stream", bytes.NewReader(req)) + if err != nil { + return fmt.Errorf("error sending request: %v", err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("bad response %d; body: %q", resp.StatusCode, body) + } + if err != nil { + return fmt.Errorf("failed reading response: %v", err) + } + remResp := &pb.Response{} + if err := proto.Unmarshal(body, remResp); err != nil { + return fmt.Errorf("error unmarshalling response: %v", err) + } + + if ae := remResp.GetApplicationError(); ae != nil { + return &internal.APIError{ + Code: ae.GetCode(), + Detail: ae.GetDetail(), + Service: service, + } + } + + if remResp.Response == nil { + return fmt.Errorf("unexpected response: %s", proto.MarshalTextString(remResp)) + } + + return proto.Unmarshal(remResp.Response, out) +} + +// This is a forgiving regexp designed to parse the app ID from YAML. +var appIDRE = regexp.MustCompile(`app_id["']?\s*:\s*['"]?([-a-z0-9.:~]+)`) + +func getAppID(client *http.Client, url string) (string, error) { + // Generate a pseudo-random token for handshaking. + token := strconv.Itoa(rand.New(rand.NewSource(time.Now().UnixNano())).Int()) + + resp, err := client.Get(fmt.Sprintf("%s?rtok=%s", url, token)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("bad response %d; body: %q", resp.StatusCode, body) + } + if err != nil { + return "", fmt.Errorf("failed reading response: %v", err) + } + + // Check the token is present in response. + if !bytes.Contains(body, []byte(token)) { + return "", fmt.Errorf("token not found: want %q; body %q", token, body) + } + + match := appIDRE.FindSubmatch(body) + if match == nil { + return "", fmt.Errorf("app ID not found: body %q", body) + } + + return string(match[1]), nil +} + +type headerAddingRoundTripper struct { + Wrapped http.RoundTripper +} + +func (t *headerAddingRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { + r.Header.Set("X-Appcfg-Api-Version", "1") + return t.Wrapped.RoundTrip(r) +} diff --git a/vendor/google.golang.org/appengine/remote_api/remote_api.go b/vendor/google.golang.org/appengine/remote_api/remote_api.go new file mode 100644 index 000000000..7b5579360 --- /dev/null +++ b/vendor/google.golang.org/appengine/remote_api/remote_api.go @@ -0,0 +1,152 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package remote_api implements the /_ah/remote_api endpoint. +This endpoint is used by offline tools such as the bulk loader. +*/ +package remote_api + +import ( + "fmt" + "io" + "io/ioutil" + "net/http" + "strconv" + + "github.com/golang/protobuf/proto" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/remote_api" + "google.golang.org/appengine/log" + "google.golang.org/appengine/user" +) + +func init() { + http.HandleFunc("/_ah/remote_api", handle) +} + +func handle(w http.ResponseWriter, req *http.Request) { + c := appengine.NewContext(req) + + u := user.Current(c) + if u == nil { + u, _ = user.CurrentOAuth(c, + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/appengine.apis", + ) + } + + if u == nil || !u.Admin { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusUnauthorized) + io.WriteString(w, "You must be logged in as an administrator to access this.\n") + return + } + if req.Header.Get("X-Appcfg-Api-Version") == "" { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusForbidden) + io.WriteString(w, "This request did not contain a necessary header.\n") + return + } + + if req.Method != "POST" { + // Response must be YAML. + rtok := req.FormValue("rtok") + if rtok == "" { + rtok = "0" + } + w.Header().Set("Content-Type", "text/yaml; charset=utf-8") + fmt.Fprintf(w, `{app_id: %q, rtok: %q}`, internal.FullyQualifiedAppID(c), rtok) + return + } + + defer req.Body.Close() + body, err := ioutil.ReadAll(req.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + log.Errorf(c, "Failed reading body: %v", err) + return + } + remReq := &pb.Request{} + if err := proto.Unmarshal(body, remReq); err != nil { + w.WriteHeader(http.StatusBadRequest) + log.Errorf(c, "Bad body: %v", err) + return + } + + service, method := *remReq.ServiceName, *remReq.Method + if !requestSupported(service, method) { + w.WriteHeader(http.StatusBadRequest) + log.Errorf(c, "Unsupported RPC /%s.%s", service, method) + return + } + + rawReq := &rawMessage{remReq.Request} + rawRes := &rawMessage{} + err = internal.Call(c, service, method, rawReq, rawRes) + + remRes := &pb.Response{} + if err == nil { + remRes.Response = rawRes.buf + } else if ae, ok := err.(*internal.APIError); ok { + remRes.ApplicationError = &pb.ApplicationError{ + Code: &ae.Code, + Detail: &ae.Detail, + } + } else { + // This shouldn't normally happen. + log.Errorf(c, "appengine/remote_api: Unexpected error of type %T: %v", err, err) + remRes.ApplicationError = &pb.ApplicationError{ + Code: proto.Int32(0), + Detail: proto.String(err.Error()), + } + } + out, err := proto.Marshal(remRes) + if err != nil { + // This should not be possible. + w.WriteHeader(500) + log.Errorf(c, "proto.Marshal: %v", err) + return + } + + log.Infof(c, "Spooling %d bytes of response to /%s.%s", len(out), service, method) + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Length", strconv.Itoa(len(out))) + w.Write(out) +} + +// rawMessage is a protocol buffer type that is already serialised. +// This allows the remote_api code here to handle messages +// without having to know the real type. +type rawMessage struct { + buf []byte +} + +func (rm *rawMessage) Marshal() ([]byte, error) { + return rm.buf, nil +} + +func (rm *rawMessage) Unmarshal(buf []byte) error { + rm.buf = make([]byte, len(buf)) + copy(rm.buf, buf) + return nil +} + +func requestSupported(service, method string) bool { + // This list of supported services is taken from SERVICE_PB_MAP in remote_api_services.py + switch service { + case "app_identity_service", "blobstore", "capability_service", "channel", "datastore_v3", + "datastore_v4", "file", "images", "logservice", "mail", "matcher", "memcache", "remote_datastore", + "remote_socket", "search", "modules", "system", "taskqueue", "urlfetch", "user", "xmpp": + return true + } + return false +} + +// Methods to satisfy proto.Message. +func (rm *rawMessage) Reset() { rm.buf = nil } +func (rm *rawMessage) String() string { return strconv.Quote(string(rm.buf)) } +func (*rawMessage) ProtoMessage() {} diff --git a/vendor/google.golang.org/appengine/runtime/runtime.go b/vendor/google.golang.org/appengine/runtime/runtime.go new file mode 100644 index 000000000..7aca8f639 --- /dev/null +++ b/vendor/google.golang.org/appengine/runtime/runtime.go @@ -0,0 +1,148 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package runtime exposes information about the resource usage of the application. +It also provides a way to run code in a new background context of a module. + +This package does not work on Managed VMs. +*/ +package runtime + +import ( + "net/http" + + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/system" +) + +// Statistics represents the system's statistics. +type Statistics struct { + // CPU records the CPU consumed by this instance, in megacycles. + CPU struct { + Total float64 + Rate1M float64 // consumption rate over one minute + Rate10M float64 // consumption rate over ten minutes + } + // RAM records the memory used by the instance, in megabytes. + RAM struct { + Current float64 + Average1M float64 // average usage over one minute + Average10M float64 // average usage over ten minutes + } +} + +func Stats(c context.Context) (*Statistics, error) { + req := &pb.GetSystemStatsRequest{} + res := &pb.GetSystemStatsResponse{} + if err := internal.Call(c, "system", "GetSystemStats", req, res); err != nil { + return nil, err + } + s := &Statistics{} + if res.Cpu != nil { + s.CPU.Total = res.Cpu.GetTotal() + s.CPU.Rate1M = res.Cpu.GetRate1M() + s.CPU.Rate10M = res.Cpu.GetRate10M() + } + if res.Memory != nil { + s.RAM.Current = res.Memory.GetCurrent() + s.RAM.Average1M = res.Memory.GetAverage1M() + s.RAM.Average10M = res.Memory.GetAverage10M() + } + return s, nil +} + +/* +RunInBackground makes an API call that triggers an /_ah/background request. + +There are two independent code paths that need to make contact: +the RunInBackground code, and the /_ah/background handler. The matchmaker +loop arranges for the two paths to meet. The RunInBackground code passes +a send to the matchmaker, the /_ah/background passes a recv to the matchmaker, +and the matchmaker hooks them up. +*/ + +func init() { + http.HandleFunc("/_ah/background", handleBackground) + + sc := make(chan send) + rc := make(chan recv) + sendc, recvc = sc, rc + go matchmaker(sc, rc) +} + +var ( + sendc chan<- send // RunInBackground sends to this + recvc chan<- recv // handleBackground sends to this +) + +type send struct { + id string + f func(context.Context) +} + +type recv struct { + id string + ch chan<- func(context.Context) +} + +func matchmaker(sendc <-chan send, recvc <-chan recv) { + // When one side of the match arrives before the other + // it is inserted in the corresponding map. + waitSend := make(map[string]send) + waitRecv := make(map[string]recv) + + for { + select { + case s := <-sendc: + if r, ok := waitRecv[s.id]; ok { + // meet! + delete(waitRecv, s.id) + r.ch <- s.f + } else { + // waiting for r + waitSend[s.id] = s + } + case r := <-recvc: + if s, ok := waitSend[r.id]; ok { + // meet! + delete(waitSend, r.id) + r.ch <- s.f + } else { + // waiting for s + waitRecv[r.id] = r + } + } + } +} + +var newContext = appengine.NewContext // for testing + +func handleBackground(w http.ResponseWriter, req *http.Request) { + id := req.Header.Get("X-AppEngine-BackgroundRequest") + + ch := make(chan func(context.Context)) + recvc <- recv{id, ch} + (<-ch)(newContext(req)) +} + +// RunInBackground runs f in a background goroutine in this process. +// f is provided a context that may outlast the context provided to RunInBackground. +// This is only valid to invoke from a manually scaled module. +func RunInBackground(c context.Context, f func(c context.Context)) error { + req := &pb.StartBackgroundRequestRequest{} + res := &pb.StartBackgroundRequestResponse{} + if err := internal.Call(c, "system", "StartBackgroundRequest", req, res); err != nil { + return err + } + sendc <- send{res.GetRequestId(), f} + return nil +} + +func init() { + internal.RegisterErrorCodeMap("system", pb.SystemServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/search/doc.go b/vendor/google.golang.org/appengine/search/doc.go new file mode 100644 index 000000000..2392e7e3a --- /dev/null +++ b/vendor/google.golang.org/appengine/search/doc.go @@ -0,0 +1,205 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package search provides a client for App Engine's search service. + + +Basic Operations + +Indexes contain documents. Each index is identified by its name: a +human-readable ASCII string. + +Within an index, documents are associated with an ID, which is also +a human-readable ASCII string. A document's contents are a mapping from +case-sensitive field names to values. Valid types for field values are: + - string, + - search.Atom, + - search.HTML, + - time.Time (stored with millisecond precision), + - float64 (value between -2,147,483,647 and 2,147,483,647 inclusive), + - appengine.GeoPoint. + +The Get and Put methods on an Index load and save a document. +A document's contents are typically represented by a struct pointer. + +Example code: + + type Doc struct { + Author string + Comment string + Creation time.Time + } + + index, err := search.Open("comments") + if err != nil { + return err + } + newID, err := index.Put(ctx, "", &Doc{ + Author: "gopher", + Comment: "the truth of the matter", + Creation: time.Now(), + }) + if err != nil { + return err + } + +A single document can be retrieved by its ID. Pass a destination struct +to Get to hold the resulting document. + + var doc Doc + err := index.Get(ctx, id, &doc) + if err != nil { + return err + } + + +Search and Listing Documents + +Indexes have two methods for retrieving multiple documents at once: Search and +List. + +Searching an index for a query will result in an iterator. As with an iterator +from package datastore, pass a destination struct to Next to decode the next +result. Next will return Done when the iterator is exhausted. + + for t := index.Search(ctx, "Comment:truth", nil); ; { + var doc Doc + id, err := t.Next(&doc) + if err == search.Done { + break + } + if err != nil { + return err + } + fmt.Fprintf(w, "%s -> %#v\n", id, doc) + } + +Search takes a string query to determine which documents to return. The query +can be simple, such as a single word to match, or complex. The query +language is described at +https://cloud.google.com/appengine/docs/go/search/query_strings + +Search also takes an optional SearchOptions struct which gives much more +control over how results are calculated and returned. + +Call List to iterate over all documents in an index. + + for t := index.List(ctx, nil); ; { + var doc Doc + id, err := t.Next(&doc) + if err == search.Done { + break + } + if err != nil { + return err + } + fmt.Fprintf(w, "%s -> %#v\n", id, doc) + } + + +Fields and Facets + +A document's contents can be represented by a variety of types. These are +typically struct pointers, but they can also be represented by any type +implementing the FieldLoadSaver interface. The FieldLoadSaver allows metadata +to be set for the document with the DocumentMetadata type. Struct pointers are +more strongly typed and are easier to use; FieldLoadSavers are more flexible. + +A document's contents can be expressed in two ways: fields and facets. + +Fields are the most common way of providing content for documents. Fields can +store data in multiple types and can be matched in searches using query +strings. + +Facets provide a way to attach categorical information to a document. The only +valid types for facets are search.Atom and float64. Facets allow search +results to contain summaries of the categories matched in a search, and to +restrict searches to only match against specific categories. + +By default, for struct pointers, all of the struct fields are used as document +fields, and the field name used is the same as on the struct (and hence must +start with an upper case letter). Struct fields may have a +`search:"name,options"` tag. The name must start with a letter and be +composed only of word characters. If options is "facet" then the struct +field will be used as a document facet. If options is "" then the comma +may be omitted. There are no other recognized options. + +Example code: + + // A and B are renamed to a and b. + // A, C and I are facets. + // D's tag is equivalent to having no tag at all (E). + // I has tag information for both the search and json packages. + type TaggedStruct struct { + A float64 `search:"a,facet"` + B float64 `search:"b"` + C float64 `search:",facet"` + D float64 `search:""` + E float64 + I float64 `search:",facet" json:"i"` + } + + +The FieldLoadSaver Interface + +A document's contents can also be represented by any type that implements the +FieldLoadSaver interface. This type may be a struct pointer, but it +does not have to be. The search package will call Load when loading the +document's contents, and Save when saving them. In addition to a slice of +Fields, the Load and Save methods also use the DocumentMetadata type to +provide additional information about a document (such as its Rank, or set of +Facets). Possible uses for this interface include deriving non-stored fields, +verifying fields or setting specific languages for string and HTML fields. + +Example code: + + type CustomFieldsExample struct { + // Item's title and which language it is in. + Title string + Lang string + // Mass, in grams. + Mass int + } + + func (x *CustomFieldsExample) Load(fields []search.Field, meta *search.DocumentMetadata) error { + // Load the title field, failing if any other field is found. + for _, f := range fields { + if f.Name != "title" { + return fmt.Errorf("unknown field %q", f.Name) + } + s, ok := f.Value.(string) + if !ok { + return fmt.Errorf("unsupported type %T for field %q", f.Value, f.Name) + } + x.Title = s + x.Lang = f.Language + } + // Load the mass facet, failing if any other facet is found. + for _, f := range meta.Facets { + if f.Name != "mass" { + return fmt.Errorf("unknown facet %q", f.Name) + } + m, ok := f.Value.(float64) + if !ok { + return fmt.Errorf("unsupported type %T for facet %q", f.Value, f.Name) + } + x.Mass = int(m) + } + return nil + } + + func (x *CustomFieldsExample) Save() ([]search.Field, *search.DocumentMetadata, error) { + fields := []search.Field{ + {Name: "title", Value: x.Title, Language: x.Lang}, + } + meta := &search.DocumentMetadata{ + Facets: { + {Name: "mass", Value: float64(x.Mass)}, + }, + } + return fields, meta, nil + } +*/ +package search diff --git a/vendor/google.golang.org/appengine/search/field.go b/vendor/google.golang.org/appengine/search/field.go new file mode 100644 index 000000000..707c2d8c0 --- /dev/null +++ b/vendor/google.golang.org/appengine/search/field.go @@ -0,0 +1,82 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package search + +// Field is a name/value pair. A search index's document can be loaded and +// saved as a sequence of Fields. +type Field struct { + // Name is the field name. A valid field name matches /[A-Za-z][A-Za-z0-9_]*/. + Name string + // Value is the field value. The valid types are: + // - string, + // - search.Atom, + // - search.HTML, + // - time.Time (stored with millisecond precision), + // - float64, + // - GeoPoint. + Value interface{} + // Language is a two-letter ISO 639-1 code for the field's language, + // defaulting to "en" if nothing is specified. It may only be specified for + // fields of type string and search.HTML. + Language string + // Derived marks fields that were calculated as a result of a + // FieldExpression provided to Search. This field is ignored when saving a + // document. + Derived bool +} + +// Facet is a name/value pair which is used to add categorical information to a +// document. +type Facet struct { + // Name is the facet name. A valid facet name matches /[A-Za-z][A-Za-z0-9_]*/. + // A facet name cannot be longer than 500 characters. + Name string + // Value is the facet value. + // + // When being used in documents (for example, in + // DocumentMetadata.Facets), the valid types are: + // - search.Atom, + // - float64. + // + // When being used in SearchOptions.Refinements or being returned + // in FacetResult, the valid types are: + // - search.Atom, + // - search.Range. + Value interface{} +} + +// DocumentMetadata is a struct containing information describing a given document. +type DocumentMetadata struct { + // Rank is an integer specifying the order the document will be returned in + // search results. If zero, the rank will be set to the number of seconds since + // 2011-01-01 00:00:00 UTC when being Put into an index. + Rank int + // Facets is the set of facets for this document. + Facets []Facet +} + +// FieldLoadSaver can be converted from and to a slice of Fields +// with additional document metadata. +type FieldLoadSaver interface { + Load([]Field, *DocumentMetadata) error + Save() ([]Field, *DocumentMetadata, error) +} + +// FieldList converts a []Field to implement FieldLoadSaver. +type FieldList []Field + +// Load loads all of the provided fields into l. +// It does not first reset *l to an empty slice. +func (l *FieldList) Load(f []Field, _ *DocumentMetadata) error { + *l = append(*l, f...) + return nil +} + +// Save returns all of l's fields as a slice of Fields. +func (l *FieldList) Save() ([]Field, *DocumentMetadata, error) { + return *l, nil, nil +} + +var _ FieldLoadSaver = (*FieldList)(nil) diff --git a/vendor/google.golang.org/appengine/search/search.go b/vendor/google.golang.org/appengine/search/search.go new file mode 100644 index 000000000..7a2652031 --- /dev/null +++ b/vendor/google.golang.org/appengine/search/search.go @@ -0,0 +1,1109 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package search + +// TODO: let Put specify the document language: "en", "fr", etc. Also: order_id?? storage?? +// TODO: Index.GetAll (or Iterator.GetAll)? +// TODO: struct <-> protobuf tests. +// TODO: enforce Python's MIN_NUMBER_VALUE and MIN_DATE (which would disallow a zero +// time.Time)? _MAXIMUM_STRING_LENGTH? + +import ( + "errors" + "fmt" + "math" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/search" +) + +var ( + // ErrInvalidDocumentType is returned when methods like Put, Get or Next + // are passed a dst or src argument of invalid type. + ErrInvalidDocumentType = errors.New("search: invalid document type") + + // ErrNoSuchDocument is returned when no document was found for a given ID. + ErrNoSuchDocument = errors.New("search: no such document") +) + +// Atom is a document field whose contents are indexed as a single indivisible +// string. +type Atom string + +// HTML is a document field whose contents are indexed as HTML. Only text nodes +// are indexed: "foobar" will be treated as "foobar". +type HTML string + +// validIndexNameOrDocID is the Go equivalent of Python's +// _ValidateVisiblePrintableAsciiNotReserved. +func validIndexNameOrDocID(s string) bool { + if strings.HasPrefix(s, "!") { + return false + } + for _, c := range s { + if c < 0x21 || 0x7f <= c { + return false + } + } + return true +} + +var ( + fieldNameRE = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`) + languageRE = regexp.MustCompile(`^[a-z]{2}$`) +) + +// validFieldName is the Go equivalent of Python's _CheckFieldName. It checks +// the validity of both field and facet names. +func validFieldName(s string) bool { + return len(s) <= 500 && fieldNameRE.MatchString(s) +} + +// validDocRank checks that the ranks is in the range [0, 2^31). +func validDocRank(r int) bool { + return 0 <= r && r <= (1<<31-1) +} + +// validLanguage checks that a language looks like ISO 639-1. +func validLanguage(s string) bool { + return languageRE.MatchString(s) +} + +// validFloat checks that f is in the range [-2147483647, 2147483647]. +func validFloat(f float64) bool { + return -(1<<31-1) <= f && f <= (1<<31-1) +} + +// Index is an index of documents. +type Index struct { + spec pb.IndexSpec +} + +// orderIDEpoch forms the basis for populating OrderId on documents. +var orderIDEpoch = time.Date(2011, 1, 1, 0, 0, 0, 0, time.UTC) + +// Open opens the index with the given name. The index is created if it does +// not already exist. +// +// The name is a human-readable ASCII string. It must contain no whitespace +// characters and not start with "!". +func Open(name string) (*Index, error) { + if !validIndexNameOrDocID(name) { + return nil, fmt.Errorf("search: invalid index name %q", name) + } + return &Index{ + spec: pb.IndexSpec{ + Name: &name, + }, + }, nil +} + +// Put saves src to the index. If id is empty, a new ID is allocated by the +// service and returned. If id is not empty, any existing index entry for that +// ID is replaced. +// +// The ID is a human-readable ASCII string. It must contain no whitespace +// characters and not start with "!". +// +// src must be a non-nil struct pointer or implement the FieldLoadSaver +// interface. +func (x *Index) Put(c context.Context, id string, src interface{}) (string, error) { + d, err := saveDoc(src) + if err != nil { + return "", err + } + if id != "" { + if !validIndexNameOrDocID(id) { + return "", fmt.Errorf("search: invalid ID %q", id) + } + d.Id = proto.String(id) + } + req := &pb.IndexDocumentRequest{ + Params: &pb.IndexDocumentParams{ + Document: []*pb.Document{d}, + IndexSpec: &x.spec, + }, + } + res := &pb.IndexDocumentResponse{} + if err := internal.Call(c, "search", "IndexDocument", req, res); err != nil { + return "", err + } + if len(res.Status) > 0 { + if s := res.Status[0]; s.GetCode() != pb.SearchServiceError_OK { + return "", fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail()) + } + } + if len(res.Status) != 1 || len(res.DocId) != 1 { + return "", fmt.Errorf("search: internal error: wrong number of results (%d Statuses, %d DocIDs)", + len(res.Status), len(res.DocId)) + } + return res.DocId[0], nil +} + +// Get loads the document with the given ID into dst. +// +// The ID is a human-readable ASCII string. It must be non-empty, contain no +// whitespace characters and not start with "!". +// +// dst must be a non-nil struct pointer or implement the FieldLoadSaver +// interface. +// +// ErrFieldMismatch is returned when a field is to be loaded into a different +// type than the one it was stored from, or when a field is missing or +// unexported in the destination struct. ErrFieldMismatch is only returned if +// dst is a struct pointer. It is up to the callee to decide whether this error +// is fatal, recoverable, or ignorable. +func (x *Index) Get(c context.Context, id string, dst interface{}) error { + if id == "" || !validIndexNameOrDocID(id) { + return fmt.Errorf("search: invalid ID %q", id) + } + req := &pb.ListDocumentsRequest{ + Params: &pb.ListDocumentsParams{ + IndexSpec: &x.spec, + StartDocId: proto.String(id), + Limit: proto.Int32(1), + }, + } + res := &pb.ListDocumentsResponse{} + if err := internal.Call(c, "search", "ListDocuments", req, res); err != nil { + return err + } + if res.Status == nil || res.Status.GetCode() != pb.SearchServiceError_OK { + return fmt.Errorf("search: %s: %s", res.Status.GetCode(), res.Status.GetErrorDetail()) + } + if len(res.Document) != 1 || res.Document[0].GetId() != id { + return ErrNoSuchDocument + } + return loadDoc(dst, res.Document[0], nil) +} + +// Delete deletes a document from the index. +func (x *Index) Delete(c context.Context, id string) error { + req := &pb.DeleteDocumentRequest{ + Params: &pb.DeleteDocumentParams{ + DocId: []string{id}, + IndexSpec: &x.spec, + }, + } + res := &pb.DeleteDocumentResponse{} + if err := internal.Call(c, "search", "DeleteDocument", req, res); err != nil { + return err + } + if len(res.Status) != 1 { + return fmt.Errorf("search: internal error: wrong number of results (%d)", len(res.Status)) + } + if s := res.Status[0]; s.GetCode() != pb.SearchServiceError_OK { + return fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail()) + } + return nil +} + +// List lists all of the documents in an index. The documents are returned in +// increasing ID order. +func (x *Index) List(c context.Context, opts *ListOptions) *Iterator { + t := &Iterator{ + c: c, + index: x, + count: -1, + listInclusive: true, + more: moreList, + } + if opts != nil { + t.listStartID = opts.StartID + t.limit = opts.Limit + t.idsOnly = opts.IDsOnly + } + return t +} + +func moreList(t *Iterator) error { + req := &pb.ListDocumentsRequest{ + Params: &pb.ListDocumentsParams{ + IndexSpec: &t.index.spec, + }, + } + if t.listStartID != "" { + req.Params.StartDocId = &t.listStartID + req.Params.IncludeStartDoc = &t.listInclusive + } + if t.limit > 0 { + req.Params.Limit = proto.Int32(int32(t.limit)) + } + if t.idsOnly { + req.Params.KeysOnly = &t.idsOnly + } + + res := &pb.ListDocumentsResponse{} + if err := internal.Call(t.c, "search", "ListDocuments", req, res); err != nil { + return err + } + if res.Status == nil || res.Status.GetCode() != pb.SearchServiceError_OK { + return fmt.Errorf("search: %s: %s", res.Status.GetCode(), res.Status.GetErrorDetail()) + } + t.listRes = res.Document + t.listStartID, t.listInclusive, t.more = "", false, nil + if len(res.Document) != 0 && t.limit <= 0 { + if id := res.Document[len(res.Document)-1].GetId(); id != "" { + t.listStartID, t.more = id, moreList + } + } + return nil +} + +// ListOptions are the options for listing documents in an index. Passing a nil +// *ListOptions is equivalent to using the default values. +type ListOptions struct { + // StartID is the inclusive lower bound for the ID of the returned + // documents. The zero value means all documents will be returned. + StartID string + + // Limit is the maximum number of documents to return. The zero value + // indicates no limit. + Limit int + + // IDsOnly indicates that only document IDs should be returned for the list + // operation; no document fields are populated. + IDsOnly bool +} + +// Search searches the index for the given query. +func (x *Index) Search(c context.Context, query string, opts *SearchOptions) *Iterator { + t := &Iterator{ + c: c, + index: x, + searchQuery: query, + more: moreSearch, + } + if opts != nil { + if opts.Cursor != "" { + if opts.Offset != 0 { + return errIter("at most one of Cursor and Offset may be specified") + } + t.searchCursor = proto.String(string(opts.Cursor)) + } + t.limit = opts.Limit + t.fields = opts.Fields + t.idsOnly = opts.IDsOnly + t.sort = opts.Sort + t.exprs = opts.Expressions + t.refinements = opts.Refinements + t.facetOpts = opts.Facets + t.searchOffset = opts.Offset + } + return t +} + +func moreSearch(t *Iterator) error { + // We use per-result (rather than single/per-page) cursors since this + // lets us return a Cursor for every iterator document. The two cursor + // types are largely interchangeable: a page cursor is the same as the + // last per-result cursor in a given search response. + req := &pb.SearchRequest{ + Params: &pb.SearchParams{ + IndexSpec: &t.index.spec, + Query: &t.searchQuery, + Cursor: t.searchCursor, + CursorType: pb.SearchParams_PER_RESULT.Enum(), + FieldSpec: &pb.FieldSpec{ + Name: t.fields, + }, + }, + } + if t.limit > 0 { + req.Params.Limit = proto.Int32(int32(t.limit)) + } + if t.searchOffset > 0 { + req.Params.Offset = proto.Int32(int32(t.searchOffset)) + t.searchOffset = 0 + } + if t.idsOnly { + req.Params.KeysOnly = &t.idsOnly + } + if t.sort != nil { + if err := sortToProto(t.sort, req.Params); err != nil { + return err + } + } + if t.refinements != nil { + if err := refinementsToProto(t.refinements, req.Params); err != nil { + return err + } + } + for _, e := range t.exprs { + req.Params.FieldSpec.Expression = append(req.Params.FieldSpec.Expression, &pb.FieldSpec_Expression{ + Name: proto.String(e.Name), + Expression: proto.String(e.Expr), + }) + } + for _, f := range t.facetOpts { + if err := f.setParams(req.Params); err != nil { + return fmt.Errorf("bad FacetSearchOption: %v", err) + } + } + // Don't repeat facet search. + t.facetOpts = nil + + res := &pb.SearchResponse{} + if err := internal.Call(t.c, "search", "Search", req, res); err != nil { + return err + } + if res.Status == nil || res.Status.GetCode() != pb.SearchServiceError_OK { + return fmt.Errorf("search: %s: %s", res.Status.GetCode(), res.Status.GetErrorDetail()) + } + t.searchRes = res.Result + if len(res.FacetResult) > 0 { + t.facetRes = res.FacetResult + } + t.count = int(*res.MatchedCount) + if t.limit > 0 { + t.more = nil + } else { + t.more = moreSearch + } + return nil +} + +// SearchOptions are the options for searching an index. Passing a nil +// *SearchOptions is equivalent to using the default values. +type SearchOptions struct { + // Limit is the maximum number of documents to return. The zero value + // indicates no limit. + Limit int + + // IDsOnly indicates that only document IDs should be returned for the search + // operation; no document fields are populated. + IDsOnly bool + + // Sort controls the ordering of search results. + Sort *SortOptions + + // Fields specifies which document fields to include in the results. If omitted, + // all document fields are returned. No more than 100 fields may be specified. + Fields []string + + // Expressions specifies additional computed fields to add to each returned + // document. + Expressions []FieldExpression + + // Facets controls what facet information is returned for these search results. + // If no options are specified, no facet results will be returned. + Facets []FacetSearchOption + + // Refinements filters the returned documents by requiring them to contain facets + // with specific values. Refinements are applied in conjunction for facets with + // different names, and in disjunction otherwise. + Refinements []Facet + + // Cursor causes the results to commence with the first document after + // the document associated with the cursor. + Cursor Cursor + + // Offset specifies the number of documents to skip over before returning results. + // When specified, Cursor must be nil. + Offset int +} + +// Cursor represents an iterator's position. +// +// The string value of a cursor is web-safe. It can be saved and restored +// for later use. +type Cursor string + +// FieldExpression defines a custom expression to evaluate for each result. +type FieldExpression struct { + // Name is the name to use for the computed field. + Name string + + // Expr is evaluated to provide a custom content snippet for each document. + // See https://cloud.google.com/appengine/docs/go/search/options for + // the supported expression syntax. + Expr string +} + +// FacetSearchOption controls what facet information is returned in search results. +type FacetSearchOption interface { + setParams(*pb.SearchParams) error +} + +// AutoFacetDiscovery returns a FacetSearchOption which enables automatic facet +// discovery for the search. Automatic facet discovery looks for the facets +// which appear the most often in the aggregate in the matched documents. +// +// The maximum number of facets returned is controlled by facetLimit, and the +// maximum number of values per facet by facetLimit. A limit of zero indicates +// a default limit should be used. +func AutoFacetDiscovery(facetLimit, valueLimit int) FacetSearchOption { + return &autoFacetOpt{facetLimit, valueLimit} +} + +type autoFacetOpt struct { + facetLimit, valueLimit int +} + +const defaultAutoFacetLimit = 10 // As per python runtime search.py. + +func (o *autoFacetOpt) setParams(params *pb.SearchParams) error { + lim := int32(o.facetLimit) + if lim == 0 { + lim = defaultAutoFacetLimit + } + params.AutoDiscoverFacetCount = &lim + if o.valueLimit > 0 { + params.FacetAutoDetectParam = &pb.FacetAutoDetectParam{ + ValueLimit: proto.Int32(int32(o.valueLimit)), + } + } + return nil +} + +// FacetDiscovery returns a FacetSearchOption which selects a facet to be +// returned with the search results. By default, the most frequently +// occurring values for that facet will be returned. However, you can also +// specify a list of particular Atoms or specific Ranges to return. +func FacetDiscovery(name string, value ...interface{}) FacetSearchOption { + return &facetOpt{name, value} +} + +type facetOpt struct { + name string + values []interface{} +} + +func (o *facetOpt) setParams(params *pb.SearchParams) error { + req := &pb.FacetRequest{Name: &o.name} + params.IncludeFacet = append(params.IncludeFacet, req) + if len(o.values) == 0 { + return nil + } + vtype := reflect.TypeOf(o.values[0]) + reqParam := &pb.FacetRequestParam{} + for _, v := range o.values { + if reflect.TypeOf(v) != vtype { + return errors.New("values must all be Atom, or must all be Range") + } + switch v := v.(type) { + case Atom: + reqParam.ValueConstraint = append(reqParam.ValueConstraint, string(v)) + case Range: + rng, err := rangeToProto(v) + if err != nil { + return fmt.Errorf("invalid range: %v", err) + } + reqParam.Range = append(reqParam.Range, rng) + default: + return fmt.Errorf("unsupported value type %T", v) + } + } + req.Params = reqParam + return nil +} + +// FacetDocumentDepth returns a FacetSearchOption which controls the number of +// documents to be evaluated with preparing facet results. +func FacetDocumentDepth(depth int) FacetSearchOption { + return facetDepthOpt(depth) +} + +type facetDepthOpt int + +func (o facetDepthOpt) setParams(params *pb.SearchParams) error { + params.FacetDepth = proto.Int32(int32(o)) + return nil +} + +// FacetResult represents the number of times a particular facet and value +// appeared in the documents matching a search request. +type FacetResult struct { + Facet + + // Count is the number of times this specific facet and value appeared in the + // matching documents. + Count int +} + +// Range represents a numeric range with inclusive start and exclusive end. +// Start may be specified as math.Inf(-1) to indicate there is no minimum +// value, and End may similarly be specified as math.Inf(1); at least one of +// Start or End must be a finite number. +type Range struct { + Start, End float64 +} + +var ( + negInf = math.Inf(-1) + posInf = math.Inf(1) +) + +// AtLeast returns a Range matching any value greater than, or equal to, min. +func AtLeast(min float64) Range { + return Range{Start: min, End: posInf} +} + +// LessThan returns a Range matching any value less than max. +func LessThan(max float64) Range { + return Range{Start: negInf, End: max} +} + +// SortOptions control the ordering and scoring of search results. +type SortOptions struct { + // Expressions is a slice of expressions representing a multi-dimensional + // sort. + Expressions []SortExpression + + // Scorer, when specified, will cause the documents to be scored according to + // search term frequency. + Scorer Scorer + + // Limit is the maximum number of objects to score and/or sort. Limit cannot + // be more than 10,000. The zero value indicates a default limit. + Limit int +} + +// SortExpression defines a single dimension for sorting a document. +type SortExpression struct { + // Expr is evaluated to provide a sorting value for each document. + // See https://cloud.google.com/appengine/docs/go/search/options for + // the supported expression syntax. + Expr string + + // Reverse causes the documents to be sorted in ascending order. + Reverse bool + + // The default value to use when no field is present or the expresion + // cannot be calculated for a document. For text sorts, Default must + // be of type string; for numeric sorts, float64. + Default interface{} +} + +// A Scorer defines how a document is scored. +type Scorer interface { + toProto(*pb.ScorerSpec) +} + +type enumScorer struct { + enum pb.ScorerSpec_Scorer +} + +func (e enumScorer) toProto(spec *pb.ScorerSpec) { + spec.Scorer = e.enum.Enum() +} + +var ( + // MatchScorer assigns a score based on term frequency in a document. + MatchScorer Scorer = enumScorer{pb.ScorerSpec_MATCH_SCORER} + + // RescoringMatchScorer assigns a score based on the quality of the query + // match. It is similar to a MatchScorer but uses a more complex scoring + // algorithm based on match term frequency and other factors like field type. + // Please be aware that this algorithm is continually refined and can change + // over time without notice. This means that the ordering of search results + // that use this scorer can also change without notice. + RescoringMatchScorer Scorer = enumScorer{pb.ScorerSpec_RESCORING_MATCH_SCORER} +) + +func sortToProto(sort *SortOptions, params *pb.SearchParams) error { + for _, e := range sort.Expressions { + spec := &pb.SortSpec{ + SortExpression: proto.String(e.Expr), + } + if e.Reverse { + spec.SortDescending = proto.Bool(false) + } + if e.Default != nil { + switch d := e.Default.(type) { + case float64: + spec.DefaultValueNumeric = &d + case string: + spec.DefaultValueText = &d + default: + return fmt.Errorf("search: invalid Default type %T for expression %q", d, e.Expr) + } + } + params.SortSpec = append(params.SortSpec, spec) + } + + spec := &pb.ScorerSpec{} + if sort.Limit > 0 { + spec.Limit = proto.Int32(int32(sort.Limit)) + params.ScorerSpec = spec + } + if sort.Scorer != nil { + sort.Scorer.toProto(spec) + params.ScorerSpec = spec + } + + return nil +} + +func refinementsToProto(refinements []Facet, params *pb.SearchParams) error { + for _, r := range refinements { + ref := &pb.FacetRefinement{ + Name: proto.String(r.Name), + } + switch v := r.Value.(type) { + case Atom: + ref.Value = proto.String(string(v)) + case Range: + rng, err := rangeToProto(v) + if err != nil { + return fmt.Errorf("search: refinement for facet %q: %v", r.Name, err) + } + // Unfortunately there are two identical messages for identify Facet ranges. + ref.Range = &pb.FacetRefinement_Range{Start: rng.Start, End: rng.End} + default: + return fmt.Errorf("search: unsupported refinement for facet %q of type %T", r.Name, v) + } + params.FacetRefinement = append(params.FacetRefinement, ref) + } + return nil +} + +func rangeToProto(r Range) (*pb.FacetRange, error) { + rng := &pb.FacetRange{} + if r.Start != negInf { + if !validFloat(r.Start) { + return nil, errors.New("invalid value for Start") + } + rng.Start = proto.String(strconv.FormatFloat(r.Start, 'e', -1, 64)) + } else if r.End == posInf { + return nil, errors.New("either Start or End must be finite") + } + if r.End != posInf { + if !validFloat(r.End) { + return nil, errors.New("invalid value for End") + } + rng.End = proto.String(strconv.FormatFloat(r.End, 'e', -1, 64)) + } + return rng, nil +} + +func protoToRange(rng *pb.FacetRefinement_Range) Range { + r := Range{Start: negInf, End: posInf} + if x, err := strconv.ParseFloat(rng.GetStart(), 64); err != nil { + r.Start = x + } + if x, err := strconv.ParseFloat(rng.GetEnd(), 64); err != nil { + r.End = x + } + return r +} + +// Iterator is the result of searching an index for a query or listing an +// index. +type Iterator struct { + c context.Context + index *Index + err error + + listRes []*pb.Document + listStartID string + listInclusive bool + + searchRes []*pb.SearchResult + facetRes []*pb.FacetResult + searchQuery string + searchCursor *string + searchOffset int + sort *SortOptions + + fields []string + exprs []FieldExpression + refinements []Facet + facetOpts []FacetSearchOption + + more func(*Iterator) error + + count int + limit int // items left to return; 0 for unlimited. + idsOnly bool +} + +// errIter returns an iterator that only returns the given error. +func errIter(err string) *Iterator { + return &Iterator{ + err: errors.New(err), + } +} + +// Done is returned when a query iteration has completed. +var Done = errors.New("search: query has no more results") + +// Count returns an approximation of the number of documents matched by the +// query. It is only valid to call for iterators returned by Search. +func (t *Iterator) Count() int { return t.count } + +// fetchMore retrieves more results, if there are no errors or pending results. +func (t *Iterator) fetchMore() { + if t.err == nil && len(t.listRes)+len(t.searchRes) == 0 && t.more != nil { + t.err = t.more(t) + } +} + +// Next returns the ID of the next result. When there are no more results, +// Done is returned as the error. +// +// dst must be a non-nil struct pointer, implement the FieldLoadSaver +// interface, or be a nil interface value. If a non-nil dst is provided, it +// will be filled with the indexed fields. dst is ignored if this iterator was +// created with an IDsOnly option. +func (t *Iterator) Next(dst interface{}) (string, error) { + t.fetchMore() + if t.err != nil { + return "", t.err + } + + var doc *pb.Document + var exprs []*pb.Field + switch { + case len(t.listRes) != 0: + doc = t.listRes[0] + t.listRes = t.listRes[1:] + case len(t.searchRes) != 0: + doc = t.searchRes[0].Document + exprs = t.searchRes[0].Expression + t.searchCursor = t.searchRes[0].Cursor + t.searchRes = t.searchRes[1:] + default: + return "", Done + } + if doc == nil { + return "", errors.New("search: internal error: no document returned") + } + if !t.idsOnly && dst != nil { + if err := loadDoc(dst, doc, exprs); err != nil { + return "", err + } + } + return doc.GetId(), nil +} + +// Cursor returns the cursor associated with the current document (that is, +// the document most recently returned by a call to Next). +// +// Passing this cursor in a future call to Search will cause those results +// to commence with the first document after the current document. +func (t *Iterator) Cursor() Cursor { + if t.searchCursor == nil { + return "" + } + return Cursor(*t.searchCursor) +} + +// Facets returns the facets found within the search results, if any facets +// were requested in the SearchOptions. +func (t *Iterator) Facets() ([][]FacetResult, error) { + t.fetchMore() + if t.err != nil && t.err != Done { + return nil, t.err + } + + var facets [][]FacetResult + for _, f := range t.facetRes { + fres := make([]FacetResult, 0, len(f.Value)) + for _, v := range f.Value { + ref := v.Refinement + facet := FacetResult{ + Facet: Facet{Name: ref.GetName()}, + Count: int(v.GetCount()), + } + if ref.Value != nil { + facet.Value = Atom(*ref.Value) + } else { + facet.Value = protoToRange(ref.Range) + } + fres = append(fres, facet) + } + facets = append(facets, fres) + } + return facets, nil +} + +// saveDoc converts from a struct pointer or +// FieldLoadSaver/FieldMetadataLoadSaver to the Document protobuf. +func saveDoc(src interface{}) (*pb.Document, error) { + var err error + var fields []Field + var meta *DocumentMetadata + switch x := src.(type) { + case FieldLoadSaver: + fields, meta, err = x.Save() + default: + fields, err = SaveStruct(src) + } + if err != nil { + return nil, err + } + + fieldsProto, err := fieldsToProto(fields) + if err != nil { + return nil, err + } + d := &pb.Document{ + Field: fieldsProto, + OrderId: proto.Int32(int32(time.Since(orderIDEpoch).Seconds())), + } + if meta != nil { + if meta.Rank != 0 { + if !validDocRank(meta.Rank) { + return nil, fmt.Errorf("search: invalid rank %d, must be [0, 2^31)", meta.Rank) + } + *d.OrderId = int32(meta.Rank) + } + if len(meta.Facets) > 0 { + facets, err := facetsToProto(meta.Facets) + if err != nil { + return nil, err + } + d.Facet = facets + } + } + return d, nil +} + +func fieldsToProto(src []Field) ([]*pb.Field, error) { + // Maps to catch duplicate time or numeric fields. + timeFields, numericFields := make(map[string]bool), make(map[string]bool) + dst := make([]*pb.Field, 0, len(src)) + for _, f := range src { + if !validFieldName(f.Name) { + return nil, fmt.Errorf("search: invalid field name %q", f.Name) + } + fieldValue := &pb.FieldValue{} + switch x := f.Value.(type) { + case string: + fieldValue.Type = pb.FieldValue_TEXT.Enum() + fieldValue.StringValue = proto.String(x) + case Atom: + fieldValue.Type = pb.FieldValue_ATOM.Enum() + fieldValue.StringValue = proto.String(string(x)) + case HTML: + fieldValue.Type = pb.FieldValue_HTML.Enum() + fieldValue.StringValue = proto.String(string(x)) + case time.Time: + if timeFields[f.Name] { + return nil, fmt.Errorf("search: duplicate time field %q", f.Name) + } + timeFields[f.Name] = true + fieldValue.Type = pb.FieldValue_DATE.Enum() + fieldValue.StringValue = proto.String(strconv.FormatInt(x.UnixNano()/1e6, 10)) + case float64: + if numericFields[f.Name] { + return nil, fmt.Errorf("search: duplicate numeric field %q", f.Name) + } + if !validFloat(x) { + return nil, fmt.Errorf("search: numeric field %q with invalid value %f", f.Name, x) + } + numericFields[f.Name] = true + fieldValue.Type = pb.FieldValue_NUMBER.Enum() + fieldValue.StringValue = proto.String(strconv.FormatFloat(x, 'e', -1, 64)) + case appengine.GeoPoint: + if !x.Valid() { + return nil, fmt.Errorf( + "search: GeoPoint field %q with invalid value %v", + f.Name, x) + } + fieldValue.Type = pb.FieldValue_GEO.Enum() + fieldValue.Geo = &pb.FieldValue_Geo{ + Lat: proto.Float64(x.Lat), + Lng: proto.Float64(x.Lng), + } + default: + return nil, fmt.Errorf("search: unsupported field type: %v", reflect.TypeOf(f.Value)) + } + if f.Language != "" { + switch f.Value.(type) { + case string, HTML: + if !validLanguage(f.Language) { + return nil, fmt.Errorf("search: invalid language for field %q: %q", f.Name, f.Language) + } + fieldValue.Language = proto.String(f.Language) + default: + return nil, fmt.Errorf("search: setting language not supported for field %q of type %T", f.Name, f.Value) + } + } + if p := fieldValue.StringValue; p != nil && !utf8.ValidString(*p) { + return nil, fmt.Errorf("search: %q field is invalid UTF-8: %q", f.Name, *p) + } + dst = append(dst, &pb.Field{ + Name: proto.String(f.Name), + Value: fieldValue, + }) + } + return dst, nil +} + +func facetsToProto(src []Facet) ([]*pb.Facet, error) { + dst := make([]*pb.Facet, 0, len(src)) + for _, f := range src { + if !validFieldName(f.Name) { + return nil, fmt.Errorf("search: invalid facet name %q", f.Name) + } + facetValue := &pb.FacetValue{} + switch x := f.Value.(type) { + case Atom: + if !utf8.ValidString(string(x)) { + return nil, fmt.Errorf("search: %q facet is invalid UTF-8: %q", f.Name, x) + } + facetValue.Type = pb.FacetValue_ATOM.Enum() + facetValue.StringValue = proto.String(string(x)) + case float64: + if !validFloat(x) { + return nil, fmt.Errorf("search: numeric facet %q with invalid value %f", f.Name, x) + } + facetValue.Type = pb.FacetValue_NUMBER.Enum() + facetValue.StringValue = proto.String(strconv.FormatFloat(x, 'e', -1, 64)) + default: + return nil, fmt.Errorf("search: unsupported facet type: %v", reflect.TypeOf(f.Value)) + } + dst = append(dst, &pb.Facet{ + Name: proto.String(f.Name), + Value: facetValue, + }) + } + return dst, nil +} + +// loadDoc converts from protobufs to a struct pointer or +// FieldLoadSaver/FieldMetadataLoadSaver. The src param provides the document's +// stored fields and facets, and any document metadata. An additional slice of +// fields, exprs, may optionally be provided to contain any derived expressions +// requested by the developer. +func loadDoc(dst interface{}, src *pb.Document, exprs []*pb.Field) (err error) { + fields, err := protoToFields(src.Field) + if err != nil { + return err + } + facets, err := protoToFacets(src.Facet) + if err != nil { + return err + } + if len(exprs) > 0 { + exprFields, err := protoToFields(exprs) + if err != nil { + return err + } + // Mark each field as derived. + for i := range exprFields { + exprFields[i].Derived = true + } + fields = append(fields, exprFields...) + } + meta := &DocumentMetadata{ + Rank: int(src.GetOrderId()), + Facets: facets, + } + switch x := dst.(type) { + case FieldLoadSaver: + return x.Load(fields, meta) + default: + return loadStructWithMeta(dst, fields, meta) + } +} + +func protoToFields(fields []*pb.Field) ([]Field, error) { + dst := make([]Field, 0, len(fields)) + for _, field := range fields { + fieldValue := field.GetValue() + f := Field{ + Name: field.GetName(), + } + switch fieldValue.GetType() { + case pb.FieldValue_TEXT: + f.Value = fieldValue.GetStringValue() + f.Language = fieldValue.GetLanguage() + case pb.FieldValue_ATOM: + f.Value = Atom(fieldValue.GetStringValue()) + case pb.FieldValue_HTML: + f.Value = HTML(fieldValue.GetStringValue()) + f.Language = fieldValue.GetLanguage() + case pb.FieldValue_DATE: + sv := fieldValue.GetStringValue() + millis, err := strconv.ParseInt(sv, 10, 64) + if err != nil { + return nil, fmt.Errorf("search: internal error: bad time.Time encoding %q: %v", sv, err) + } + f.Value = time.Unix(0, millis*1e6) + case pb.FieldValue_NUMBER: + sv := fieldValue.GetStringValue() + x, err := strconv.ParseFloat(sv, 64) + if err != nil { + return nil, err + } + f.Value = x + case pb.FieldValue_GEO: + geoValue := fieldValue.GetGeo() + geoPoint := appengine.GeoPoint{geoValue.GetLat(), geoValue.GetLng()} + if !geoPoint.Valid() { + return nil, fmt.Errorf("search: internal error: invalid GeoPoint encoding: %v", geoPoint) + } + f.Value = geoPoint + default: + return nil, fmt.Errorf("search: internal error: unknown data type %s", fieldValue.GetType()) + } + dst = append(dst, f) + } + return dst, nil +} + +func protoToFacets(facets []*pb.Facet) ([]Facet, error) { + if len(facets) == 0 { + return nil, nil + } + dst := make([]Facet, 0, len(facets)) + for _, facet := range facets { + facetValue := facet.GetValue() + f := Facet{ + Name: facet.GetName(), + } + switch facetValue.GetType() { + case pb.FacetValue_ATOM: + f.Value = Atom(facetValue.GetStringValue()) + case pb.FacetValue_NUMBER: + sv := facetValue.GetStringValue() + x, err := strconv.ParseFloat(sv, 64) + if err != nil { + return nil, err + } + f.Value = x + default: + return nil, fmt.Errorf("search: internal error: unknown data type %s", facetValue.GetType()) + } + dst = append(dst, f) + } + return dst, nil +} + +func namespaceMod(m proto.Message, namespace string) { + set := func(s **string) { + if *s == nil { + *s = &namespace + } + } + switch m := m.(type) { + case *pb.IndexDocumentRequest: + set(&m.Params.IndexSpec.Namespace) + case *pb.ListDocumentsRequest: + set(&m.Params.IndexSpec.Namespace) + case *pb.DeleteDocumentRequest: + set(&m.Params.IndexSpec.Namespace) + case *pb.SearchRequest: + set(&m.Params.IndexSpec.Namespace) + } +} + +func init() { + internal.RegisterErrorCodeMap("search", pb.SearchServiceError_ErrorCode_name) + internal.NamespaceMods["search"] = namespaceMod +} diff --git a/vendor/google.golang.org/appengine/search/struct.go b/vendor/google.golang.org/appengine/search/struct.go new file mode 100644 index 000000000..083c97f60 --- /dev/null +++ b/vendor/google.golang.org/appengine/search/struct.go @@ -0,0 +1,245 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package search + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +// ErrFieldMismatch is returned when a field is to be loaded into a different +// than the one it was stored from, or when a field is missing or unexported in +// the destination struct. +type ErrFieldMismatch struct { + FieldName string + Reason string +} + +func (e *ErrFieldMismatch) Error() string { + return fmt.Sprintf("search: cannot load field %q: %s", e.FieldName, e.Reason) +} + +// ErrFacetMismatch is returned when a facet is to be loaded into a different +// type than the one it was stored from, or when a field is missing or +// unexported in the destination struct. StructType is the type of the struct +// pointed to by the destination argument passed to Iterator.Next. +type ErrFacetMismatch struct { + StructType reflect.Type + FacetName string + Reason string +} + +func (e *ErrFacetMismatch) Error() string { + return fmt.Sprintf("search: cannot load facet %q into a %q: %s", e.FacetName, e.StructType, e.Reason) +} + +// structCodec defines how to convert a given struct to/from a search document. +type structCodec struct { + // byIndex returns the struct tag for the i'th struct field. + byIndex []structTag + + // fieldByName returns the index of the struct field for the given field name. + fieldByName map[string]int + + // facetByName returns the index of the struct field for the given facet name, + facetByName map[string]int +} + +// structTag holds a structured version of each struct field's parsed tag. +type structTag struct { + name string + facet bool +} + +var ( + codecsMu sync.RWMutex + codecs = map[reflect.Type]*structCodec{} +) + +func loadCodec(t reflect.Type) (*structCodec, error) { + codecsMu.RLock() + codec, ok := codecs[t] + codecsMu.RUnlock() + if ok { + return codec, nil + } + + codecsMu.Lock() + defer codecsMu.Unlock() + if codec, ok := codecs[t]; ok { + return codec, nil + } + + codec = &structCodec{ + fieldByName: make(map[string]int), + facetByName: make(map[string]int), + } + + for i, I := 0, t.NumField(); i < I; i++ { + f := t.Field(i) + name, opts := f.Tag.Get("search"), "" + if i := strings.Index(name, ","); i != -1 { + name, opts = name[:i], name[i+1:] + } + // TODO(davidday): Support name=="-" as per datastore. + if name == "" { + name = f.Name + } else if !validFieldName(name) { + return nil, fmt.Errorf("search: struct tag has invalid field name: %q", name) + } + facet := opts == "facet" + codec.byIndex = append(codec.byIndex, structTag{name: name, facet: facet}) + if facet { + codec.facetByName[name] = i + } else { + codec.fieldByName[name] = i + } + } + + codecs[t] = codec + return codec, nil +} + +// structFLS adapts a struct to be a FieldLoadSaver. +type structFLS struct { + v reflect.Value + codec *structCodec +} + +func (s structFLS) Load(fields []Field, meta *DocumentMetadata) error { + var err error + for _, field := range fields { + i, ok := s.codec.fieldByName[field.Name] + if !ok { + // Note the error, but keep going. + err = &ErrFieldMismatch{ + FieldName: field.Name, + Reason: "no such struct field", + } + continue + + } + f := s.v.Field(i) + if !f.CanSet() { + // Note the error, but keep going. + err = &ErrFieldMismatch{ + FieldName: field.Name, + Reason: "cannot set struct field", + } + continue + } + v := reflect.ValueOf(field.Value) + if ft, vt := f.Type(), v.Type(); ft != vt { + err = &ErrFieldMismatch{ + FieldName: field.Name, + Reason: fmt.Sprintf("type mismatch: %v for %v data", ft, vt), + } + continue + } + f.Set(v) + } + if meta == nil { + return nil + } + for _, facet := range meta.Facets { + i, ok := s.codec.facetByName[facet.Name] + if !ok { + // Note the error, but keep going. + if err == nil { + err = &ErrFacetMismatch{ + StructType: s.v.Type(), + FacetName: facet.Name, + Reason: "no matching field found", + } + } + continue + } + f := s.v.Field(i) + if !f.CanSet() { + // Note the error, but keep going. + if err == nil { + err = &ErrFacetMismatch{ + StructType: s.v.Type(), + FacetName: facet.Name, + Reason: "unable to set unexported field of struct", + } + } + continue + } + v := reflect.ValueOf(facet.Value) + if ft, vt := f.Type(), v.Type(); ft != vt { + if err == nil { + err = &ErrFacetMismatch{ + StructType: s.v.Type(), + FacetName: facet.Name, + Reason: fmt.Sprintf("type mismatch: %v for %d data", ft, vt), + } + continue + } + } + f.Set(v) + } + return err +} + +func (s structFLS) Save() ([]Field, *DocumentMetadata, error) { + fields := make([]Field, 0, len(s.codec.fieldByName)) + var facets []Facet + for i, tag := range s.codec.byIndex { + f := s.v.Field(i) + if !f.CanSet() { + continue + } + if tag.facet { + facets = append(facets, Facet{Name: tag.name, Value: f.Interface()}) + } else { + fields = append(fields, Field{Name: tag.name, Value: f.Interface()}) + } + } + return fields, &DocumentMetadata{Facets: facets}, nil +} + +// newStructFLS returns a FieldLoadSaver for the struct pointer p. +func newStructFLS(p interface{}) (FieldLoadSaver, error) { + v := reflect.ValueOf(p) + if v.Kind() != reflect.Ptr || v.IsNil() || v.Elem().Kind() != reflect.Struct { + return nil, ErrInvalidDocumentType + } + codec, err := loadCodec(v.Elem().Type()) + if err != nil { + return nil, err + } + return structFLS{v.Elem(), codec}, nil +} + +func loadStructWithMeta(dst interface{}, f []Field, meta *DocumentMetadata) error { + x, err := newStructFLS(dst) + if err != nil { + return err + } + return x.Load(f, meta) +} + +func saveStructWithMeta(src interface{}) ([]Field, *DocumentMetadata, error) { + x, err := newStructFLS(src) + if err != nil { + return nil, nil, err + } + return x.Save() +} + +// LoadStruct loads the fields from f to dst. dst must be a struct pointer. +func LoadStruct(dst interface{}, f []Field) error { + return loadStructWithMeta(dst, f, nil) +} + +// SaveStruct returns the fields from src as a slice of Field. +// src must be a struct pointer. +func SaveStruct(src interface{}) ([]Field, error) { + f, _, err := saveStructWithMeta(src) + return f, err +} diff --git a/vendor/google.golang.org/appengine/socket/doc.go b/vendor/google.golang.org/appengine/socket/doc.go new file mode 100644 index 000000000..1e2355392 --- /dev/null +++ b/vendor/google.golang.org/appengine/socket/doc.go @@ -0,0 +1,10 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package socket provides outbound network sockets. +// +// This package is only required in the classic App Engine environment. +// Applications running only in the Managed VM hosting environment should +// use the standard library's net package. +package socket diff --git a/vendor/google.golang.org/appengine/socket/socket_classic.go b/vendor/google.golang.org/appengine/socket/socket_classic.go new file mode 100644 index 000000000..0ad50e2d3 --- /dev/null +++ b/vendor/google.golang.org/appengine/socket/socket_classic.go @@ -0,0 +1,290 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build appengine + +package socket + +import ( + "fmt" + "io" + "net" + "strconv" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + "google.golang.org/appengine/internal" + + pb "google.golang.org/appengine/internal/socket" +) + +// Dial connects to the address addr on the network protocol. +// The address format is host:port, where host may be a hostname or an IP address. +// Known protocols are "tcp" and "udp". +// The returned connection satisfies net.Conn, and is valid while ctx is valid; +// if the connection is to be used after ctx becomes invalid, invoke SetContext +// with the new context. +func Dial(ctx context.Context, protocol, addr string) (*Conn, error) { + return DialTimeout(ctx, protocol, addr, 0) +} + +var ipFamilies = []pb.CreateSocketRequest_SocketFamily{ + pb.CreateSocketRequest_IPv4, + pb.CreateSocketRequest_IPv6, +} + +// DialTimeout is like Dial but takes a timeout. +// The timeout includes name resolution, if required. +func DialTimeout(ctx context.Context, protocol, addr string, timeout time.Duration) (*Conn, error) { + dialCtx := ctx // Used for dialing and name resolution, but not stored in the *Conn. + if timeout > 0 { + var cancel context.CancelFunc + dialCtx, cancel = context.WithTimeout(ctx, timeout) + defer cancel() + } + + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + port, err := strconv.Atoi(portStr) + if err != nil { + return nil, fmt.Errorf("socket: bad port %q: %v", portStr, err) + } + + var prot pb.CreateSocketRequest_SocketProtocol + switch protocol { + case "tcp": + prot = pb.CreateSocketRequest_TCP + case "udp": + prot = pb.CreateSocketRequest_UDP + default: + return nil, fmt.Errorf("socket: unknown protocol %q", protocol) + } + + packedAddrs, resolved, err := resolve(dialCtx, ipFamilies, host) + if err != nil { + return nil, fmt.Errorf("socket: failed resolving %q: %v", host, err) + } + if len(packedAddrs) == 0 { + return nil, fmt.Errorf("no addresses for %q", host) + } + + packedAddr := packedAddrs[0] // use first address + fam := pb.CreateSocketRequest_IPv4 + if len(packedAddr) == net.IPv6len { + fam = pb.CreateSocketRequest_IPv6 + } + + req := &pb.CreateSocketRequest{ + Family: fam.Enum(), + Protocol: prot.Enum(), + RemoteIp: &pb.AddressPort{ + Port: proto.Int32(int32(port)), + PackedAddress: packedAddr, + }, + } + if resolved { + req.RemoteIp.HostnameHint = &host + } + res := &pb.CreateSocketReply{} + if err := internal.Call(dialCtx, "remote_socket", "CreateSocket", req, res); err != nil { + return nil, err + } + + return &Conn{ + ctx: ctx, + desc: res.GetSocketDescriptor(), + prot: prot, + local: res.ProxyExternalIp, + remote: req.RemoteIp, + }, nil +} + +// LookupIP returns the given host's IP addresses. +func LookupIP(ctx context.Context, host string) (addrs []net.IP, err error) { + packedAddrs, _, err := resolve(ctx, ipFamilies, host) + if err != nil { + return nil, fmt.Errorf("socket: failed resolving %q: %v", host, err) + } + addrs = make([]net.IP, len(packedAddrs)) + for i, pa := range packedAddrs { + addrs[i] = net.IP(pa) + } + return addrs, nil +} + +func resolve(ctx context.Context, fams []pb.CreateSocketRequest_SocketFamily, host string) ([][]byte, bool, error) { + // Check if it's an IP address. + if ip := net.ParseIP(host); ip != nil { + if ip := ip.To4(); ip != nil { + return [][]byte{ip}, false, nil + } + return [][]byte{ip}, false, nil + } + + req := &pb.ResolveRequest{ + Name: &host, + AddressFamilies: fams, + } + res := &pb.ResolveReply{} + if err := internal.Call(ctx, "remote_socket", "Resolve", req, res); err != nil { + // XXX: need to map to pb.ResolveReply_ErrorCode? + return nil, false, err + } + return res.PackedAddress, true, nil +} + +// withDeadline is like context.WithDeadline, except it ignores the zero deadline. +func withDeadline(parent context.Context, deadline time.Time) (context.Context, context.CancelFunc) { + if deadline.IsZero() { + return parent, func() {} + } + return context.WithDeadline(parent, deadline) +} + +// Conn represents a socket connection. +// It implements net.Conn. +type Conn struct { + ctx context.Context + desc string + offset int64 + + prot pb.CreateSocketRequest_SocketProtocol + local, remote *pb.AddressPort + + readDeadline, writeDeadline time.Time // optional +} + +// SetContext sets the context that is used by this Conn. +// It is usually used only when using a Conn that was created in a different context, +// such as when a connection is created during a warmup request but used while +// servicing a user request. +func (cn *Conn) SetContext(ctx context.Context) { + cn.ctx = ctx +} + +func (cn *Conn) Read(b []byte) (n int, err error) { + const maxRead = 1 << 20 + if len(b) > maxRead { + b = b[:maxRead] + } + + req := &pb.ReceiveRequest{ + SocketDescriptor: &cn.desc, + DataSize: proto.Int32(int32(len(b))), + } + res := &pb.ReceiveReply{} + if !cn.readDeadline.IsZero() { + req.TimeoutSeconds = proto.Float64(cn.readDeadline.Sub(time.Now()).Seconds()) + } + ctx, cancel := withDeadline(cn.ctx, cn.readDeadline) + defer cancel() + if err := internal.Call(ctx, "remote_socket", "Receive", req, res); err != nil { + return 0, err + } + if len(res.Data) == 0 { + return 0, io.EOF + } + if len(res.Data) > len(b) { + return 0, fmt.Errorf("socket: internal error: read too much data: %d > %d", len(res.Data), len(b)) + } + return copy(b, res.Data), nil +} + +func (cn *Conn) Write(b []byte) (n int, err error) { + const lim = 1 << 20 // max per chunk + + for n < len(b) { + chunk := b[n:] + if len(chunk) > lim { + chunk = chunk[:lim] + } + + req := &pb.SendRequest{ + SocketDescriptor: &cn.desc, + Data: chunk, + StreamOffset: &cn.offset, + } + res := &pb.SendReply{} + if !cn.writeDeadline.IsZero() { + req.TimeoutSeconds = proto.Float64(cn.writeDeadline.Sub(time.Now()).Seconds()) + } + ctx, cancel := withDeadline(cn.ctx, cn.writeDeadline) + defer cancel() + if err = internal.Call(ctx, "remote_socket", "Send", req, res); err != nil { + // assume zero bytes were sent in this RPC + break + } + n += int(res.GetDataSent()) + cn.offset += int64(res.GetDataSent()) + } + + return +} + +func (cn *Conn) Close() error { + req := &pb.CloseRequest{ + SocketDescriptor: &cn.desc, + } + res := &pb.CloseReply{} + if err := internal.Call(cn.ctx, "remote_socket", "Close", req, res); err != nil { + return err + } + cn.desc = "CLOSED" + return nil +} + +func addr(prot pb.CreateSocketRequest_SocketProtocol, ap *pb.AddressPort) net.Addr { + if ap == nil { + return nil + } + switch prot { + case pb.CreateSocketRequest_TCP: + return &net.TCPAddr{ + IP: net.IP(ap.PackedAddress), + Port: int(*ap.Port), + } + case pb.CreateSocketRequest_UDP: + return &net.UDPAddr{ + IP: net.IP(ap.PackedAddress), + Port: int(*ap.Port), + } + } + panic("unknown protocol " + prot.String()) +} + +func (cn *Conn) LocalAddr() net.Addr { return addr(cn.prot, cn.local) } +func (cn *Conn) RemoteAddr() net.Addr { return addr(cn.prot, cn.remote) } + +func (cn *Conn) SetDeadline(t time.Time) error { + cn.readDeadline = t + cn.writeDeadline = t + return nil +} + +func (cn *Conn) SetReadDeadline(t time.Time) error { + cn.readDeadline = t + return nil +} + +func (cn *Conn) SetWriteDeadline(t time.Time) error { + cn.writeDeadline = t + return nil +} + +// KeepAlive signals that the connection is still in use. +// It may be called to prevent the socket being closed due to inactivity. +func (cn *Conn) KeepAlive() error { + req := &pb.GetSocketNameRequest{ + SocketDescriptor: &cn.desc, + } + res := &pb.GetSocketNameReply{} + return internal.Call(cn.ctx, "remote_socket", "GetSocketName", req, res) +} + +func init() { + internal.RegisterErrorCodeMap("remote_socket", pb.RemoteSocketServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/socket/socket_vm.go b/vendor/google.golang.org/appengine/socket/socket_vm.go new file mode 100644 index 000000000..ed98ac2f0 --- /dev/null +++ b/vendor/google.golang.org/appengine/socket/socket_vm.go @@ -0,0 +1,64 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine + +package socket + +import ( + "net" + "time" + + "golang.org/x/net/context" +) + +// Dial connects to the address addr on the network protocol. +// The address format is host:port, where host may be a hostname or an IP address. +// Known protocols are "tcp" and "udp". +// The returned connection satisfies net.Conn, and is valid while ctx is valid; +// if the connection is to be used after ctx becomes invalid, invoke SetContext +// with the new context. +func Dial(ctx context.Context, protocol, addr string) (*Conn, error) { + conn, err := net.Dial(protocol, addr) + if err != nil { + return nil, err + } + return &Conn{conn}, nil +} + +// DialTimeout is like Dial but takes a timeout. +// The timeout includes name resolution, if required. +func DialTimeout(ctx context.Context, protocol, addr string, timeout time.Duration) (*Conn, error) { + conn, err := net.DialTimeout(protocol, addr, timeout) + if err != nil { + return nil, err + } + return &Conn{conn}, nil +} + +// LookupIP returns the given host's IP addresses. +func LookupIP(ctx context.Context, host string) (addrs []net.IP, err error) { + return net.LookupIP(host) +} + +// Conn represents a socket connection. +// It implements net.Conn. +type Conn struct { + net.Conn +} + +// SetContext sets the context that is used by this Conn. +// It is usually used only when using a Conn that was created in a different context, +// such as when a connection is created during a warmup request but used while +// servicing a user request. +func (cn *Conn) SetContext(ctx context.Context) { + // This function is not required on managed VMs. +} + +// KeepAlive signals that the connection is still in use. +// It may be called to prevent the socket being closed due to inactivity. +func (cn *Conn) KeepAlive() error { + // This function is not required on managed VMs. + return nil +} diff --git a/vendor/google.golang.org/appengine/taskqueue/taskqueue.go b/vendor/google.golang.org/appengine/taskqueue/taskqueue.go new file mode 100644 index 000000000..7bdae927b --- /dev/null +++ b/vendor/google.golang.org/appengine/taskqueue/taskqueue.go @@ -0,0 +1,496 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package taskqueue provides a client for App Engine's taskqueue service. +Using this service, applications may perform work outside a user's request. + +A Task may be constructed manually; alternatively, since the most common +taskqueue operation is to add a single POST task, NewPOSTTask makes it easy. + + t := taskqueue.NewPOSTTask("/worker", url.Values{ + "key": {key}, + }) + taskqueue.Add(c, t, "") // add t to the default queue +*/ +package taskqueue + +import ( + "errors" + "fmt" + "net/http" + "net/url" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + dspb "google.golang.org/appengine/internal/datastore" + pb "google.golang.org/appengine/internal/taskqueue" +) + +var ( + // ErrTaskAlreadyAdded is the error returned by Add and AddMulti when a task has already been added with a particular name. + ErrTaskAlreadyAdded = errors.New("taskqueue: task has already been added") +) + +// RetryOptions let you control whether to retry a task and the backoff intervals between tries. +type RetryOptions struct { + // Number of tries/leases after which the task fails permanently and is deleted. + // If AgeLimit is also set, both limits must be exceeded for the task to fail permanently. + RetryLimit int32 + + // Maximum time allowed since the task's first try before the task fails permanently and is deleted (only for push tasks). + // If RetryLimit is also set, both limits must be exceeded for the task to fail permanently. + AgeLimit time.Duration + + // Minimum time between successive tries (only for push tasks). + MinBackoff time.Duration + + // Maximum time between successive tries (only for push tasks). + MaxBackoff time.Duration + + // Maximum number of times to double the interval between successive tries before the intervals increase linearly (only for push tasks). + MaxDoublings int32 + + // If MaxDoublings is zero, set ApplyZeroMaxDoublings to true to override the default non-zero value. + // Otherwise a zero MaxDoublings is ignored and the default is used. + ApplyZeroMaxDoublings bool +} + +// toRetryParameter converts RetryOptions to pb.TaskQueueRetryParameters. +func (opt *RetryOptions) toRetryParameters() *pb.TaskQueueRetryParameters { + params := &pb.TaskQueueRetryParameters{} + if opt.RetryLimit > 0 { + params.RetryLimit = proto.Int32(opt.RetryLimit) + } + if opt.AgeLimit > 0 { + params.AgeLimitSec = proto.Int64(int64(opt.AgeLimit.Seconds())) + } + if opt.MinBackoff > 0 { + params.MinBackoffSec = proto.Float64(opt.MinBackoff.Seconds()) + } + if opt.MaxBackoff > 0 { + params.MaxBackoffSec = proto.Float64(opt.MaxBackoff.Seconds()) + } + if opt.MaxDoublings > 0 || (opt.MaxDoublings == 0 && opt.ApplyZeroMaxDoublings) { + params.MaxDoublings = proto.Int32(opt.MaxDoublings) + } + return params +} + +// A Task represents a task to be executed. +type Task struct { + // Path is the worker URL for the task. + // If unset, it will default to /_ah/queue/. + Path string + + // Payload is the data for the task. + // This will be delivered as the HTTP request body. + // It is only used when Method is POST, PUT or PULL. + // url.Values' Encode method may be used to generate this for POST requests. + Payload []byte + + // Additional HTTP headers to pass at the task's execution time. + // To schedule the task to be run with an alternate app version + // or backend, set the "Host" header. + Header http.Header + + // Method is the HTTP method for the task ("GET", "POST", etc.), + // or "PULL" if this is task is destined for a pull-based queue. + // If empty, this defaults to "POST". + Method string + + // A name for the task. + // If empty, a name will be chosen. + Name string + + // Delay specifies the duration the task queue service must wait + // before executing the task. + // Either Delay or ETA may be set, but not both. + Delay time.Duration + + // ETA specifies the earliest time a task may be executed (push queues) + // or leased (pull queues). + // Either Delay or ETA may be set, but not both. + ETA time.Time + + // The number of times the task has been dispatched or leased. + RetryCount int32 + + // Tag for the task. Only used when Method is PULL. + Tag string + + // Retry options for this task. May be nil. + RetryOptions *RetryOptions +} + +func (t *Task) method() string { + if t.Method == "" { + return "POST" + } + return t.Method +} + +// NewPOSTTask creates a Task that will POST to a path with the given form data. +func NewPOSTTask(path string, params url.Values) *Task { + h := make(http.Header) + h.Set("Content-Type", "application/x-www-form-urlencoded") + return &Task{ + Path: path, + Payload: []byte(params.Encode()), + Header: h, + Method: "POST", + } +} + +var ( + currentNamespace = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") + defaultNamespace = http.CanonicalHeaderKey("X-AppEngine-Default-Namespace") +) + +func getDefaultNamespace(ctx context.Context) string { + return internal.IncomingHeaders(ctx).Get(defaultNamespace) +} + +func newAddReq(c context.Context, task *Task, queueName string) (*pb.TaskQueueAddRequest, error) { + if queueName == "" { + queueName = "default" + } + path := task.Path + if path == "" { + path = "/_ah/queue/" + queueName + } + eta := task.ETA + if eta.IsZero() { + eta = time.Now().Add(task.Delay) + } else if task.Delay != 0 { + panic("taskqueue: both Delay and ETA are set") + } + req := &pb.TaskQueueAddRequest{ + QueueName: []byte(queueName), + TaskName: []byte(task.Name), + EtaUsec: proto.Int64(eta.UnixNano() / 1e3), + } + method := task.method() + if method == "PULL" { + // Pull-based task + req.Body = task.Payload + req.Mode = pb.TaskQueueMode_PULL.Enum() + if task.Tag != "" { + req.Tag = []byte(task.Tag) + } + } else { + // HTTP-based task + if v, ok := pb.TaskQueueAddRequest_RequestMethod_value[method]; ok { + req.Method = pb.TaskQueueAddRequest_RequestMethod(v).Enum() + } else { + return nil, fmt.Errorf("taskqueue: bad method %q", method) + } + req.Url = []byte(path) + for k, vs := range task.Header { + for _, v := range vs { + req.Header = append(req.Header, &pb.TaskQueueAddRequest_Header{ + Key: []byte(k), + Value: []byte(v), + }) + } + } + if method == "POST" || method == "PUT" { + req.Body = task.Payload + } + + // Namespace headers. + if _, ok := task.Header[currentNamespace]; !ok { + // Fetch the current namespace of this request. + ns := internal.NamespaceFromContext(c) + req.Header = append(req.Header, &pb.TaskQueueAddRequest_Header{ + Key: []byte(currentNamespace), + Value: []byte(ns), + }) + } + if _, ok := task.Header[defaultNamespace]; !ok { + // Fetch the X-AppEngine-Default-Namespace header of this request. + if ns := getDefaultNamespace(c); ns != "" { + req.Header = append(req.Header, &pb.TaskQueueAddRequest_Header{ + Key: []byte(defaultNamespace), + Value: []byte(ns), + }) + } + } + } + + if task.RetryOptions != nil { + req.RetryParameters = task.RetryOptions.toRetryParameters() + } + + return req, nil +} + +var alreadyAddedErrors = map[pb.TaskQueueServiceError_ErrorCode]bool{ + pb.TaskQueueServiceError_TASK_ALREADY_EXISTS: true, + pb.TaskQueueServiceError_TOMBSTONED_TASK: true, +} + +// Add adds the task to a named queue. +// An empty queue name means that the default queue will be used. +// Add returns an equivalent Task with defaults filled in, including setting +// the task's Name field to the chosen name if the original was empty. +func Add(c context.Context, task *Task, queueName string) (*Task, error) { + req, err := newAddReq(c, task, queueName) + if err != nil { + return nil, err + } + res := &pb.TaskQueueAddResponse{} + if err := internal.Call(c, "taskqueue", "Add", req, res); err != nil { + apiErr, ok := err.(*internal.APIError) + if ok && alreadyAddedErrors[pb.TaskQueueServiceError_ErrorCode(apiErr.Code)] { + return nil, ErrTaskAlreadyAdded + } + return nil, err + } + resultTask := *task + resultTask.Method = task.method() + if task.Name == "" { + resultTask.Name = string(res.ChosenTaskName) + } + return &resultTask, nil +} + +// AddMulti adds multiple tasks to a named queue. +// An empty queue name means that the default queue will be used. +// AddMulti returns a slice of equivalent tasks with defaults filled in, including setting +// each task's Name field to the chosen name if the original was empty. +// If a given task is badly formed or could not be added, an appengine.MultiError is returned. +func AddMulti(c context.Context, tasks []*Task, queueName string) ([]*Task, error) { + req := &pb.TaskQueueBulkAddRequest{ + AddRequest: make([]*pb.TaskQueueAddRequest, len(tasks)), + } + me, any := make(appengine.MultiError, len(tasks)), false + for i, t := range tasks { + req.AddRequest[i], me[i] = newAddReq(c, t, queueName) + any = any || me[i] != nil + } + if any { + return nil, me + } + res := &pb.TaskQueueBulkAddResponse{} + if err := internal.Call(c, "taskqueue", "BulkAdd", req, res); err != nil { + return nil, err + } + if len(res.Taskresult) != len(tasks) { + return nil, errors.New("taskqueue: server error") + } + tasksOut := make([]*Task, len(tasks)) + for i, tr := range res.Taskresult { + tasksOut[i] = new(Task) + *tasksOut[i] = *tasks[i] + tasksOut[i].Method = tasksOut[i].method() + if tasksOut[i].Name == "" { + tasksOut[i].Name = string(tr.ChosenTaskName) + } + if *tr.Result != pb.TaskQueueServiceError_OK { + if alreadyAddedErrors[*tr.Result] { + me[i] = ErrTaskAlreadyAdded + } else { + me[i] = &internal.APIError{ + Service: "taskqueue", + Code: int32(*tr.Result), + } + } + any = true + } + } + if any { + return tasksOut, me + } + return tasksOut, nil +} + +// Delete deletes a task from a named queue. +func Delete(c context.Context, task *Task, queueName string) error { + err := DeleteMulti(c, []*Task{task}, queueName) + if me, ok := err.(appengine.MultiError); ok { + return me[0] + } + return err +} + +// DeleteMulti deletes multiple tasks from a named queue. +// If a given task could not be deleted, an appengine.MultiError is returned. +func DeleteMulti(c context.Context, tasks []*Task, queueName string) error { + taskNames := make([][]byte, len(tasks)) + for i, t := range tasks { + taskNames[i] = []byte(t.Name) + } + if queueName == "" { + queueName = "default" + } + req := &pb.TaskQueueDeleteRequest{ + QueueName: []byte(queueName), + TaskName: taskNames, + } + res := &pb.TaskQueueDeleteResponse{} + if err := internal.Call(c, "taskqueue", "Delete", req, res); err != nil { + return err + } + if a, b := len(req.TaskName), len(res.Result); a != b { + return fmt.Errorf("taskqueue: internal error: requested deletion of %d tasks, got %d results", a, b) + } + me, any := make(appengine.MultiError, len(res.Result)), false + for i, ec := range res.Result { + if ec != pb.TaskQueueServiceError_OK { + me[i] = &internal.APIError{ + Service: "taskqueue", + Code: int32(ec), + } + any = true + } + } + if any { + return me + } + return nil +} + +func lease(c context.Context, maxTasks int, queueName string, leaseTime int, groupByTag bool, tag []byte) ([]*Task, error) { + if queueName == "" { + queueName = "default" + } + req := &pb.TaskQueueQueryAndOwnTasksRequest{ + QueueName: []byte(queueName), + LeaseSeconds: proto.Float64(float64(leaseTime)), + MaxTasks: proto.Int64(int64(maxTasks)), + GroupByTag: proto.Bool(groupByTag), + Tag: tag, + } + res := &pb.TaskQueueQueryAndOwnTasksResponse{} + if err := internal.Call(c, "taskqueue", "QueryAndOwnTasks", req, res); err != nil { + return nil, err + } + tasks := make([]*Task, len(res.Task)) + for i, t := range res.Task { + tasks[i] = &Task{ + Payload: t.Body, + Name: string(t.TaskName), + Method: "PULL", + ETA: time.Unix(0, *t.EtaUsec*1e3), + RetryCount: *t.RetryCount, + Tag: string(t.Tag), + } + } + return tasks, nil +} + +// Lease leases tasks from a queue. +// leaseTime is in seconds. +// The number of tasks fetched will be at most maxTasks. +func Lease(c context.Context, maxTasks int, queueName string, leaseTime int) ([]*Task, error) { + return lease(c, maxTasks, queueName, leaseTime, false, nil) +} + +// LeaseByTag leases tasks from a queue, grouped by tag. +// If tag is empty, then the returned tasks are grouped by the tag of the task with earliest ETA. +// leaseTime is in seconds. +// The number of tasks fetched will be at most maxTasks. +func LeaseByTag(c context.Context, maxTasks int, queueName string, leaseTime int, tag string) ([]*Task, error) { + return lease(c, maxTasks, queueName, leaseTime, true, []byte(tag)) +} + +// Purge removes all tasks from a queue. +func Purge(c context.Context, queueName string) error { + if queueName == "" { + queueName = "default" + } + req := &pb.TaskQueuePurgeQueueRequest{ + QueueName: []byte(queueName), + } + res := &pb.TaskQueuePurgeQueueResponse{} + return internal.Call(c, "taskqueue", "PurgeQueue", req, res) +} + +// ModifyLease modifies the lease of a task. +// Used to request more processing time, or to abandon processing. +// leaseTime is in seconds and must not be negative. +func ModifyLease(c context.Context, task *Task, queueName string, leaseTime int) error { + if queueName == "" { + queueName = "default" + } + req := &pb.TaskQueueModifyTaskLeaseRequest{ + QueueName: []byte(queueName), + TaskName: []byte(task.Name), + EtaUsec: proto.Int64(task.ETA.UnixNano() / 1e3), // Used to verify ownership. + LeaseSeconds: proto.Float64(float64(leaseTime)), + } + res := &pb.TaskQueueModifyTaskLeaseResponse{} + if err := internal.Call(c, "taskqueue", "ModifyTaskLease", req, res); err != nil { + return err + } + task.ETA = time.Unix(0, *res.UpdatedEtaUsec*1e3) + return nil +} + +// QueueStatistics represents statistics about a single task queue. +type QueueStatistics struct { + Tasks int // may be an approximation + OldestETA time.Time // zero if there are no pending tasks + + Executed1Minute int // tasks executed in the last minute + InFlight int // tasks executing now + EnforcedRate float64 // requests per second +} + +// QueueStats retrieves statistics about queues. +func QueueStats(c context.Context, queueNames []string) ([]QueueStatistics, error) { + req := &pb.TaskQueueFetchQueueStatsRequest{ + QueueName: make([][]byte, len(queueNames)), + } + for i, q := range queueNames { + if q == "" { + q = "default" + } + req.QueueName[i] = []byte(q) + } + res := &pb.TaskQueueFetchQueueStatsResponse{} + if err := internal.Call(c, "taskqueue", "FetchQueueStats", req, res); err != nil { + return nil, err + } + qs := make([]QueueStatistics, len(res.Queuestats)) + for i, qsg := range res.Queuestats { + qs[i] = QueueStatistics{ + Tasks: int(*qsg.NumTasks), + } + if eta := *qsg.OldestEtaUsec; eta > -1 { + qs[i].OldestETA = time.Unix(0, eta*1e3) + } + if si := qsg.ScannerInfo; si != nil { + qs[i].Executed1Minute = int(*si.ExecutedLastMinute) + qs[i].InFlight = int(si.GetRequestsInFlight()) + qs[i].EnforcedRate = si.GetEnforcedRate() + } + } + return qs, nil +} + +func setTransaction(x *pb.TaskQueueAddRequest, t *dspb.Transaction) { + x.Transaction = t +} + +func init() { + internal.RegisterErrorCodeMap("taskqueue", pb.TaskQueueServiceError_ErrorCode_name) + + // Datastore error codes are shifted by DATASTORE_ERROR when presented through taskqueue. + dsCode := int32(pb.TaskQueueServiceError_DATASTORE_ERROR) + int32(dspb.Error_TIMEOUT) + internal.RegisterTimeoutErrorCode("taskqueue", dsCode) + + // Transaction registration. + internal.RegisterTransactionSetter(setTransaction) + internal.RegisterTransactionSetter(func(x *pb.TaskQueueBulkAddRequest, t *dspb.Transaction) { + for _, req := range x.AddRequest { + setTransaction(req, t) + } + }) +} diff --git a/vendor/google.golang.org/appengine/timeout.go b/vendor/google.golang.org/appengine/timeout.go new file mode 100644 index 000000000..05642a992 --- /dev/null +++ b/vendor/google.golang.org/appengine/timeout.go @@ -0,0 +1,20 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package appengine + +import "golang.org/x/net/context" + +// IsTimeoutError reports whether err is a timeout error. +func IsTimeoutError(err error) bool { + if err == context.DeadlineExceeded { + return true + } + if t, ok := err.(interface { + IsTimeout() bool + }); ok { + return t.IsTimeout() + } + return false +} diff --git a/vendor/google.golang.org/appengine/urlfetch/urlfetch.go b/vendor/google.golang.org/appengine/urlfetch/urlfetch.go new file mode 100644 index 000000000..ba3d17c71 --- /dev/null +++ b/vendor/google.golang.org/appengine/urlfetch/urlfetch.go @@ -0,0 +1,210 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package urlfetch provides an http.RoundTripper implementation +// for fetching URLs via App Engine's urlfetch service. +package urlfetch + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/urlfetch" +) + +// Transport is an implementation of http.RoundTripper for +// App Engine. Users should generally create an http.Client using +// this transport and use the Client rather than using this transport +// directly. +type Transport struct { + Context context.Context + + // Controls whether the application checks the validity of SSL certificates + // over HTTPS connections. A value of false (the default) instructs the + // application to send a request to the server only if the certificate is + // valid and signed by a trusted certificate authority (CA), and also + // includes a hostname that matches the certificate. A value of true + // instructs the application to perform no certificate validation. + AllowInvalidServerCertificate bool +} + +// Verify statically that *Transport implements http.RoundTripper. +var _ http.RoundTripper = (*Transport)(nil) + +// Client returns an *http.Client using a default urlfetch Transport. This +// client will have the default deadline of 5 seconds, and will check the +// validity of SSL certificates. +// +// Any deadline of the provided context will be used for requests through this client; +// if the client does not have a deadline then a 5 second default is used. +func Client(ctx context.Context) *http.Client { + return &http.Client{ + Transport: &Transport{ + Context: ctx, + }, + } +} + +type bodyReader struct { + content []byte + truncated bool + closed bool +} + +// ErrTruncatedBody is the error returned after the final Read() from a +// response's Body if the body has been truncated by App Engine's proxy. +var ErrTruncatedBody = errors.New("urlfetch: truncated body") + +func statusCodeToText(code int) string { + if t := http.StatusText(code); t != "" { + return t + } + return strconv.Itoa(code) +} + +func (br *bodyReader) Read(p []byte) (n int, err error) { + if br.closed { + if br.truncated { + return 0, ErrTruncatedBody + } + return 0, io.EOF + } + n = copy(p, br.content) + if n > 0 { + br.content = br.content[n:] + return + } + if br.truncated { + br.closed = true + return 0, ErrTruncatedBody + } + return 0, io.EOF +} + +func (br *bodyReader) Close() error { + br.closed = true + br.content = nil + return nil +} + +// A map of the URL Fetch-accepted methods that take a request body. +var methodAcceptsRequestBody = map[string]bool{ + "POST": true, + "PUT": true, + "PATCH": true, +} + +// urlString returns a valid string given a URL. This function is necessary because +// the String method of URL doesn't correctly handle URLs with non-empty Opaque values. +// See http://code.google.com/p/go/issues/detail?id=4860. +func urlString(u *url.URL) string { + if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") { + return u.String() + } + aux := *u + aux.Opaque = "//" + aux.Host + aux.Opaque + return aux.String() +} + +// RoundTrip issues a single HTTP request and returns its response. Per the +// http.RoundTripper interface, RoundTrip only returns an error if there +// was an unsupported request or the URL Fetch proxy fails. +// Note that HTTP response codes such as 5xx, 403, 404, etc are not +// errors as far as the transport is concerned and will be returned +// with err set to nil. +func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) { + methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method] + if !ok { + return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method) + } + + method := pb.URLFetchRequest_RequestMethod(methNum) + + freq := &pb.URLFetchRequest{ + Method: &method, + Url: proto.String(urlString(req.URL)), + FollowRedirects: proto.Bool(false), // http.Client's responsibility + MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate), + } + if deadline, ok := t.Context.Deadline(); ok { + freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds()) + } + + for k, vals := range req.Header { + for _, val := range vals { + freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{ + Key: proto.String(k), + Value: proto.String(val), + }) + } + } + if methodAcceptsRequestBody[req.Method] && req.Body != nil { + // Avoid a []byte copy if req.Body has a Bytes method. + switch b := req.Body.(type) { + case interface { + Bytes() []byte + }: + freq.Payload = b.Bytes() + default: + freq.Payload, err = ioutil.ReadAll(req.Body) + if err != nil { + return nil, err + } + } + } + + fres := &pb.URLFetchResponse{} + if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil { + return nil, err + } + + res = &http.Response{} + res.StatusCode = int(*fres.StatusCode) + res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode)) + res.Header = make(http.Header) + res.Request = req + + // Faked: + res.ProtoMajor = 1 + res.ProtoMinor = 1 + res.Proto = "HTTP/1.1" + res.Close = true + + for _, h := range fres.Header { + hkey := http.CanonicalHeaderKey(*h.Key) + hval := *h.Value + if hkey == "Content-Length" { + // Will get filled in below for all but HEAD requests. + if req.Method == "HEAD" { + res.ContentLength, _ = strconv.ParseInt(hval, 10, 64) + } + continue + } + res.Header.Add(hkey, hval) + } + + if req.Method != "HEAD" { + res.ContentLength = int64(len(fres.Content)) + } + + truncated := fres.GetContentWasTruncated() + res.Body = &bodyReader{content: fres.Content, truncated: truncated} + return +} + +func init() { + internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name) + internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED)) +} diff --git a/vendor/google.golang.org/appengine/user/oauth.go b/vendor/google.golang.org/appengine/user/oauth.go new file mode 100644 index 000000000..ffad57182 --- /dev/null +++ b/vendor/google.golang.org/appengine/user/oauth.go @@ -0,0 +1,52 @@ +// Copyright 2012 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package user + +import ( + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/user" +) + +// CurrentOAuth returns the user associated with the OAuth consumer making this +// request. If the OAuth consumer did not make a valid OAuth request, or the +// scopes is non-empty and the current user does not have at least one of the +// scopes, this method will return an error. +func CurrentOAuth(c context.Context, scopes ...string) (*User, error) { + req := &pb.GetOAuthUserRequest{} + if len(scopes) != 1 || scopes[0] != "" { + // The signature for this function used to be CurrentOAuth(Context, string). + // Ignore the singular "" scope to preserve existing behavior. + req.Scopes = scopes + } + + res := &pb.GetOAuthUserResponse{} + + err := internal.Call(c, "user", "GetOAuthUser", req, res) + if err != nil { + return nil, err + } + return &User{ + Email: *res.Email, + AuthDomain: *res.AuthDomain, + Admin: res.GetIsAdmin(), + ID: *res.UserId, + ClientID: res.GetClientId(), + }, nil +} + +// OAuthConsumerKey returns the OAuth consumer key provided with the current +// request. This method will return an error if the OAuth request was invalid. +func OAuthConsumerKey(c context.Context) (string, error) { + req := &pb.CheckOAuthSignatureRequest{} + res := &pb.CheckOAuthSignatureResponse{} + + err := internal.Call(c, "user", "CheckOAuthSignature", req, res) + if err != nil { + return "", err + } + return *res.OauthConsumerKey, err +} diff --git a/vendor/google.golang.org/appengine/user/user.go b/vendor/google.golang.org/appengine/user/user.go new file mode 100644 index 000000000..622b61020 --- /dev/null +++ b/vendor/google.golang.org/appengine/user/user.go @@ -0,0 +1,84 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// Package user provides a client for App Engine's user authentication service. +package user + +import ( + "strings" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/user" +) + +// User represents a user of the application. +type User struct { + Email string + AuthDomain string + Admin bool + + // ID is the unique permanent ID of the user. + // It is populated if the Email is associated + // with a Google account, or empty otherwise. + ID string + + // ClientID is the ID of the pre-registered client so its identity can be verified. + // See https://developers.google.com/console/help/#generatingoauth2 for more information. + ClientID string + + FederatedIdentity string + FederatedProvider string +} + +// String returns a displayable name for the user. +func (u *User) String() string { + if u.AuthDomain != "" && strings.HasSuffix(u.Email, "@"+u.AuthDomain) { + return u.Email[:len(u.Email)-len("@"+u.AuthDomain)] + } + if u.FederatedIdentity != "" { + return u.FederatedIdentity + } + return u.Email +} + +// LoginURL returns a URL that, when visited, prompts the user to sign in, +// then redirects the user to the URL specified by dest. +func LoginURL(c context.Context, dest string) (string, error) { + return LoginURLFederated(c, dest, "") +} + +// LoginURLFederated is like LoginURL but accepts a user's OpenID identifier. +func LoginURLFederated(c context.Context, dest, identity string) (string, error) { + req := &pb.CreateLoginURLRequest{ + DestinationUrl: proto.String(dest), + } + if identity != "" { + req.FederatedIdentity = proto.String(identity) + } + res := &pb.CreateLoginURLResponse{} + if err := internal.Call(c, "user", "CreateLoginURL", req, res); err != nil { + return "", err + } + return *res.LoginUrl, nil +} + +// LogoutURL returns a URL that, when visited, signs the user out, +// then redirects the user to the URL specified by dest. +func LogoutURL(c context.Context, dest string) (string, error) { + req := &pb.CreateLogoutURLRequest{ + DestinationUrl: proto.String(dest), + } + res := &pb.CreateLogoutURLResponse{} + if err := internal.Call(c, "user", "CreateLogoutURL", req, res); err != nil { + return "", err + } + return *res.LogoutUrl, nil +} + +func init() { + internal.RegisterErrorCodeMap("user", pb.UserServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/appengine/user/user_classic.go b/vendor/google.golang.org/appengine/user/user_classic.go new file mode 100644 index 000000000..a747ef365 --- /dev/null +++ b/vendor/google.golang.org/appengine/user/user_classic.go @@ -0,0 +1,35 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build appengine + +package user + +import ( + "appengine/user" + + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" +) + +func Current(ctx context.Context) *User { + u := user.Current(internal.ClassicContextFromContext(ctx)) + if u == nil { + return nil + } + // Map appengine/user.User to this package's User type. + return &User{ + Email: u.Email, + AuthDomain: u.AuthDomain, + Admin: u.Admin, + ID: u.ID, + FederatedIdentity: u.FederatedIdentity, + FederatedProvider: u.FederatedProvider, + } +} + +func IsAdmin(ctx context.Context) bool { + return user.IsAdmin(internal.ClassicContextFromContext(ctx)) +} diff --git a/vendor/google.golang.org/appengine/user/user_vm.go b/vendor/google.golang.org/appengine/user/user_vm.go new file mode 100644 index 000000000..8dc672e92 --- /dev/null +++ b/vendor/google.golang.org/appengine/user/user_vm.go @@ -0,0 +1,38 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine + +package user + +import ( + "golang.org/x/net/context" + + "google.golang.org/appengine/internal" +) + +// Current returns the currently logged-in user, +// or nil if the user is not signed in. +func Current(c context.Context) *User { + h := internal.IncomingHeaders(c) + u := &User{ + Email: h.Get("X-AppEngine-User-Email"), + AuthDomain: h.Get("X-AppEngine-Auth-Domain"), + ID: h.Get("X-AppEngine-User-Id"), + Admin: h.Get("X-AppEngine-User-Is-Admin") == "1", + FederatedIdentity: h.Get("X-AppEngine-Federated-Identity"), + FederatedProvider: h.Get("X-AppEngine-Federated-Provider"), + } + if u.Email == "" && u.FederatedIdentity == "" { + return nil + } + return u +} + +// IsAdmin returns true if the current user is signed in and +// is currently registered as an administrator of the application. +func IsAdmin(c context.Context) bool { + h := internal.IncomingHeaders(c) + return h.Get("X-AppEngine-User-Is-Admin") == "1" +} diff --git a/vendor/google.golang.org/appengine/xmpp/xmpp.go b/vendor/google.golang.org/appengine/xmpp/xmpp.go new file mode 100644 index 000000000..bbc27538a --- /dev/null +++ b/vendor/google.golang.org/appengine/xmpp/xmpp.go @@ -0,0 +1,253 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +/* +Package xmpp provides the means to send and receive instant messages +to and from users of XMPP-compatible services. + +To send a message, + m := &xmpp.Message{ + To: []string{"kaylee@example.com"}, + Body: `Hi! How's the carrot?`, + } + err := m.Send(c) + +To receive messages, + func init() { + xmpp.Handle(handleChat) + } + + func handleChat(c context.Context, m *xmpp.Message) { + // ... + } +*/ +package xmpp + +import ( + "errors" + "fmt" + "net/http" + + "golang.org/x/net/context" + + "google.golang.org/appengine" + "google.golang.org/appengine/internal" + pb "google.golang.org/appengine/internal/xmpp" +) + +// Message represents an incoming chat message. +type Message struct { + // Sender is the JID of the sender. + // Optional for outgoing messages. + Sender string + + // To is the intended recipients of the message. + // Incoming messages will have exactly one element. + To []string + + // Body is the body of the message. + Body string + + // Type is the message type, per RFC 3921. + // It defaults to "chat". + Type string + + // RawXML is whether the body contains raw XML. + RawXML bool +} + +// Presence represents an outgoing presence update. +type Presence struct { + // Sender is the JID (optional). + Sender string + + // The intended recipient of the presence update. + To string + + // Type, per RFC 3921 (optional). Defaults to "available". + Type string + + // State of presence (optional). + // Valid values: "away", "chat", "xa", "dnd" (RFC 3921). + State string + + // Free text status message (optional). + Status string +} + +var ( + ErrPresenceUnavailable = errors.New("xmpp: presence unavailable") + ErrInvalidJID = errors.New("xmpp: invalid JID") +) + +// Handle arranges for f to be called for incoming XMPP messages. +// Only messages of type "chat" or "normal" will be handled. +func Handle(f func(c context.Context, m *Message)) { + http.HandleFunc("/_ah/xmpp/message/chat/", func(_ http.ResponseWriter, r *http.Request) { + f(appengine.NewContext(r), &Message{ + Sender: r.FormValue("from"), + To: []string{r.FormValue("to")}, + Body: r.FormValue("body"), + }) + }) +} + +// Send sends a message. +// If any failures occur with specific recipients, the error will be an appengine.MultiError. +func (m *Message) Send(c context.Context) error { + req := &pb.XmppMessageRequest{ + Jid: m.To, + Body: &m.Body, + RawXml: &m.RawXML, + } + if m.Type != "" && m.Type != "chat" { + req.Type = &m.Type + } + if m.Sender != "" { + req.FromJid = &m.Sender + } + res := &pb.XmppMessageResponse{} + if err := internal.Call(c, "xmpp", "SendMessage", req, res); err != nil { + return err + } + + if len(res.Status) != len(req.Jid) { + return fmt.Errorf("xmpp: sent message to %d JIDs, but only got %d statuses back", len(req.Jid), len(res.Status)) + } + me, any := make(appengine.MultiError, len(req.Jid)), false + for i, st := range res.Status { + if st != pb.XmppMessageResponse_NO_ERROR { + me[i] = errors.New(st.String()) + any = true + } + } + if any { + return me + } + return nil +} + +// Invite sends an invitation. If the from address is an empty string +// the default (yourapp@appspot.com/bot) will be used. +func Invite(c context.Context, to, from string) error { + req := &pb.XmppInviteRequest{ + Jid: &to, + } + if from != "" { + req.FromJid = &from + } + res := &pb.XmppInviteResponse{} + return internal.Call(c, "xmpp", "SendInvite", req, res) +} + +// Send sends a presence update. +func (p *Presence) Send(c context.Context) error { + req := &pb.XmppSendPresenceRequest{ + Jid: &p.To, + } + if p.State != "" { + req.Show = &p.State + } + if p.Type != "" { + req.Type = &p.Type + } + if p.Sender != "" { + req.FromJid = &p.Sender + } + if p.Status != "" { + req.Status = &p.Status + } + res := &pb.XmppSendPresenceResponse{} + return internal.Call(c, "xmpp", "SendPresence", req, res) +} + +var presenceMap = map[pb.PresenceResponse_SHOW]string{ + pb.PresenceResponse_NORMAL: "", + pb.PresenceResponse_AWAY: "away", + pb.PresenceResponse_DO_NOT_DISTURB: "dnd", + pb.PresenceResponse_CHAT: "chat", + pb.PresenceResponse_EXTENDED_AWAY: "xa", +} + +// GetPresence retrieves a user's presence. +// If the from address is an empty string the default +// (yourapp@appspot.com/bot) will be used. +// Possible return values are "", "away", "dnd", "chat", "xa". +// ErrPresenceUnavailable is returned if the presence is unavailable. +func GetPresence(c context.Context, to string, from string) (string, error) { + req := &pb.PresenceRequest{ + Jid: &to, + } + if from != "" { + req.FromJid = &from + } + res := &pb.PresenceResponse{} + if err := internal.Call(c, "xmpp", "GetPresence", req, res); err != nil { + return "", err + } + if !*res.IsAvailable || res.Presence == nil { + return "", ErrPresenceUnavailable + } + presence, ok := presenceMap[*res.Presence] + if ok { + return presence, nil + } + return "", fmt.Errorf("xmpp: unknown presence %v", *res.Presence) +} + +// GetPresenceMulti retrieves multiple users' presence. +// If the from address is an empty string the default +// (yourapp@appspot.com/bot) will be used. +// Possible return values are "", "away", "dnd", "chat", "xa". +// If any presence is unavailable, an appengine.MultiError is returned +func GetPresenceMulti(c context.Context, to []string, from string) ([]string, error) { + req := &pb.BulkPresenceRequest{ + Jid: to, + } + if from != "" { + req.FromJid = &from + } + res := &pb.BulkPresenceResponse{} + + if err := internal.Call(c, "xmpp", "BulkGetPresence", req, res); err != nil { + return nil, err + } + + presences := make([]string, 0, len(res.PresenceResponse)) + errs := appengine.MultiError{} + + addResult := func(presence string, err error) { + presences = append(presences, presence) + errs = append(errs, err) + } + + anyErr := false + for _, subres := range res.PresenceResponse { + if !subres.GetValid() { + anyErr = true + addResult("", ErrInvalidJID) + continue + } + if !*subres.IsAvailable || subres.Presence == nil { + anyErr = true + addResult("", ErrPresenceUnavailable) + continue + } + presence, ok := presenceMap[*subres.Presence] + if ok { + addResult(presence, nil) + } else { + anyErr = true + addResult("", fmt.Errorf("xmpp: unknown presence %q", *subres.Presence)) + } + } + if anyErr { + return presences, errs + } + return presences, nil +} + +func init() { + internal.RegisterErrorCodeMap("xmpp", pb.XmppServiceError_ErrorCode_name) +} diff --git a/vendor/google.golang.org/cloud/LICENSE b/vendor/google.golang.org/cloud/LICENSE new file mode 100644 index 000000000..a4c5efd82 --- /dev/null +++ b/vendor/google.golang.org/cloud/LICENSE @@ -0,0 +1,202 @@ + + 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. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/google.golang.org/cloud/compute/metadata/metadata.go b/vendor/google.golang.org/cloud/compute/metadata/metadata.go new file mode 100644 index 000000000..a3daf943a --- /dev/null +++ b/vendor/google.golang.org/cloud/compute/metadata/metadata.go @@ -0,0 +1,332 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package metadata provides access to Google Compute Engine (GCE) +// metadata and API service accounts. +// +// This package is a wrapper around the GCE metadata service, +// as documented at https://developers.google.com/compute/docs/metadata. +package metadata + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "strings" + "sync" + "time" + + "google.golang.org/cloud/internal" +) + +type cachedValue struct { + k string + trim bool + mu sync.Mutex + v string +} + +var ( + projID = &cachedValue{k: "project/project-id", trim: true} + projNum = &cachedValue{k: "project/numeric-project-id", trim: true} + instID = &cachedValue{k: "instance/id", trim: true} +) + +var metaClient = &http.Client{ + Transport: &internal.Transport{ + Base: &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 750 * time.Millisecond, + KeepAlive: 30 * time.Second, + }).Dial, + ResponseHeaderTimeout: 750 * time.Millisecond, + }, + }, +} + +// NotDefinedError is returned when requested metadata is not defined. +// +// The underlying string is the suffix after "/computeMetadata/v1/". +// +// This error is not returned if the value is defined to be the empty +// string. +type NotDefinedError string + +func (suffix NotDefinedError) Error() string { + return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix)) +} + +// Get returns a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// +// If the GCE_METADATA_HOST environment variable is not defined, a default of +// 169.254.169.254 will be used instead. +// +// If the requested metadata is not defined, the returned error will +// be of type NotDefinedError. +func Get(suffix string) (string, error) { + val, _, err := getETag(suffix) + return val, err +} + +// getETag returns a value from the metadata service as well as the associated +// ETag. This func is otherwise equivalent to Get. +func getETag(suffix string) (value, etag string, err error) { + // Using a fixed IP makes it very difficult to spoof the metadata service in + // a container, which is an important use-case for local testing of cloud + // deployments. To enable spoofing of the metadata service, the environment + // variable GCE_METADATA_HOST is first inspected to decide where metadata + // requests shall go. + host := os.Getenv("GCE_METADATA_HOST") + if host == "" { + // Using 169.254.169.254 instead of "metadata" here because Go + // binaries built with the "netgo" tag and without cgo won't + // know the search suffix for "metadata" is + // ".google.internal", and this IP address is documented as + // being stable anyway. + host = "169.254.169.254" + } + url := "http://" + host + "/computeMetadata/v1/" + suffix + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("Metadata-Flavor", "Google") + res, err := metaClient.Do(req) + if err != nil { + return "", "", err + } + defer res.Body.Close() + if res.StatusCode == http.StatusNotFound { + return "", "", NotDefinedError(suffix) + } + if res.StatusCode != 200 { + return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url) + } + all, err := ioutil.ReadAll(res.Body) + if err != nil { + return "", "", err + } + return string(all), res.Header.Get("Etag"), nil +} + +func getTrimmed(suffix string) (s string, err error) { + s, err = Get(suffix) + s = strings.TrimSpace(s) + return +} + +func (c *cachedValue) get() (v string, err error) { + defer c.mu.Unlock() + c.mu.Lock() + if c.v != "" { + return c.v, nil + } + if c.trim { + v, err = getTrimmed(c.k) + } else { + v, err = Get(c.k) + } + if err == nil { + c.v = v + } + return +} + +var onGCE struct { + sync.Mutex + set bool + v bool +} + +// OnGCE reports whether this process is running on Google Compute Engine. +func OnGCE() bool { + defer onGCE.Unlock() + onGCE.Lock() + if onGCE.set { + return onGCE.v + } + onGCE.set = true + + // We use the DNS name of the metadata service here instead of the IP address + // because we expect that to fail faster in the not-on-GCE case. + res, err := metaClient.Get("http://metadata.google.internal") + if err != nil { + return false + } + onGCE.v = res.Header.Get("Metadata-Flavor") == "Google" + return onGCE.v +} + +// Subscribe subscribes to a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// The suffix may contain query parameters. +// +// Subscribe calls fn with the latest metadata value indicated by the provided +// suffix. If the metadata value is deleted, fn is called with the empty string +// and ok false. Subscribe blocks until fn returns a non-nil error or the value +// is deleted. Subscribe returns the error value returned from the last call to +// fn, which may be nil when ok == false. +func Subscribe(suffix string, fn func(v string, ok bool) error) error { + const failedSubscribeSleep = time.Second * 5 + + // First check to see if the metadata value exists at all. + val, lastETag, err := getETag(suffix) + if err != nil { + return err + } + + if err := fn(val, true); err != nil { + return err + } + + ok := true + if strings.ContainsRune(suffix, '?') { + suffix += "&wait_for_change=true&last_etag=" + } else { + suffix += "?wait_for_change=true&last_etag=" + } + for { + val, etag, err := getETag(suffix + url.QueryEscape(lastETag)) + if err != nil { + if _, deleted := err.(NotDefinedError); !deleted { + time.Sleep(failedSubscribeSleep) + continue // Retry on other errors. + } + ok = false + } + lastETag = etag + + if err := fn(val, ok); err != nil || !ok { + return err + } + } +} + +// ProjectID returns the current instance's project ID string. +func ProjectID() (string, error) { return projID.get() } + +// NumericProjectID returns the current instance's numeric project ID. +func NumericProjectID() (string, error) { return projNum.get() } + +// InternalIP returns the instance's primary internal IP address. +func InternalIP() (string, error) { + return getTrimmed("instance/network-interfaces/0/ip") +} + +// ExternalIP returns the instance's primary external (public) IP address. +func ExternalIP() (string, error) { + return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip") +} + +// Hostname returns the instance's hostname. This will be of the form +// ".c..internal". +func Hostname() (string, error) { + return getTrimmed("instance/hostname") +} + +// InstanceTags returns the list of user-defined instance tags, +// assigned when initially creating a GCE instance. +func InstanceTags() ([]string, error) { + var s []string + j, err := Get("instance/tags") + if err != nil { + return nil, err + } + if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil { + return nil, err + } + return s, nil +} + +// InstanceID returns the current VM's numeric instance ID. +func InstanceID() (string, error) { + return instID.get() +} + +// InstanceName returns the current VM's instance ID string. +func InstanceName() (string, error) { + host, err := Hostname() + if err != nil { + return "", err + } + return strings.Split(host, ".")[0], nil +} + +// Zone returns the current VM's zone, such as "us-central1-b". +func Zone() (string, error) { + zone, err := getTrimmed("instance/zone") + // zone is of the form "projects//zones/". + if err != nil { + return "", err + } + return zone[strings.LastIndex(zone, "/")+1:], nil +} + +// InstanceAttributes returns the list of user-defined attributes, +// assigned when initially creating a GCE VM instance. The value of an +// attribute can be obtained with InstanceAttributeValue. +func InstanceAttributes() ([]string, error) { return lines("instance/attributes/") } + +// ProjectAttributes returns the list of user-defined attributes +// applying to the project as a whole, not just this VM. The value of +// an attribute can be obtained with ProjectAttributeValue. +func ProjectAttributes() ([]string, error) { return lines("project/attributes/") } + +func lines(suffix string) ([]string, error) { + j, err := Get(suffix) + if err != nil { + return nil, err + } + s := strings.Split(strings.TrimSpace(j), "\n") + for i := range s { + s[i] = strings.TrimSpace(s[i]) + } + return s, nil +} + +// InstanceAttributeValue returns the value of the provided VM +// instance attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// InstanceAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func InstanceAttributeValue(attr string) (string, error) { + return Get("instance/attributes/" + attr) +} + +// ProjectAttributeValue returns the value of the provided +// project attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// ProjectAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func ProjectAttributeValue(attr string) (string, error) { + return Get("project/attributes/" + attr) +} + +// Scopes returns the service account scopes for the given account. +// The account may be empty or the string "default" to use the instance's +// main account. +func Scopes(serviceAccount string) ([]string, error) { + if serviceAccount == "" { + serviceAccount = "default" + } + return lines("instance/service-accounts/" + serviceAccount + "/scopes") +} diff --git a/vendor/google.golang.org/cloud/internal/cloud.go b/vendor/google.golang.org/cloud/internal/cloud.go new file mode 100644 index 000000000..59428803d --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/cloud.go @@ -0,0 +1,128 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package internal provides support for the cloud packages. +// +// Users should not import this package directly. +package internal + +import ( + "fmt" + "net/http" + "sync" + + "golang.org/x/net/context" +) + +type contextKey struct{} + +func WithContext(parent context.Context, projID string, c *http.Client) context.Context { + if c == nil { + panic("nil *http.Client passed to WithContext") + } + if projID == "" { + panic("empty project ID passed to WithContext") + } + return context.WithValue(parent, contextKey{}, &cloudContext{ + ProjectID: projID, + HTTPClient: c, + }) +} + +const userAgent = "gcloud-golang/0.1" + +type cloudContext struct { + ProjectID string + HTTPClient *http.Client + + mu sync.Mutex // guards svc + svc map[string]interface{} // e.g. "storage" => *rawStorage.Service +} + +// Service returns the result of the fill function if it's never been +// called before for the given name (which is assumed to be an API +// service name, like "datastore"). If it has already been cached, the fill +// func is not run. +// It's safe for concurrent use by multiple goroutines. +func Service(ctx context.Context, name string, fill func(*http.Client) interface{}) interface{} { + return cc(ctx).service(name, fill) +} + +func (c *cloudContext) service(name string, fill func(*http.Client) interface{}) interface{} { + c.mu.Lock() + defer c.mu.Unlock() + + if c.svc == nil { + c.svc = make(map[string]interface{}) + } else if v, ok := c.svc[name]; ok { + return v + } + v := fill(c.HTTPClient) + c.svc[name] = v + return v +} + +// Transport is an http.RoundTripper that appends +// Google Cloud client's user-agent to the original +// request's user-agent header. +type Transport struct { + // Base is the actual http.RoundTripper + // requests will use. It must not be nil. + Base http.RoundTripper +} + +// RoundTrip appends a user-agent to the existing user-agent +// header and delegates the request to the base http.RoundTripper. +func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + req = cloneRequest(req) + ua := req.Header.Get("User-Agent") + if ua == "" { + ua = userAgent + } else { + ua = fmt.Sprintf("%s %s", ua, userAgent) + } + req.Header.Set("User-Agent", ua) + return t.Base.RoundTrip(req) +} + +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header) + for k, s := range r.Header { + r2.Header[k] = s + } + return r2 +} + +func ProjID(ctx context.Context) string { + return cc(ctx).ProjectID +} + +func HTTPClient(ctx context.Context) *http.Client { + return cc(ctx).HTTPClient +} + +// cc returns the internal *cloudContext (cc) state for a context.Context. +// It panics if the user did it wrong. +func cc(ctx context.Context) *cloudContext { + if c, ok := ctx.Value(contextKey{}).(*cloudContext); ok { + return c + } + panic("invalid context.Context type; it should be created with cloud.NewContext") +} diff --git a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go new file mode 100644 index 000000000..9cb9be528 --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go @@ -0,0 +1,1633 @@ +// Code generated by protoc-gen-go. +// source: datastore_v1.proto +// DO NOT EDIT! + +/* +Package datastore is a generated protocol buffer package. + +It is generated from these files: + datastore_v1.proto + +It has these top-level messages: + PartitionId + Key + Value + Property + Entity + EntityResult + Query + KindExpression + PropertyReference + PropertyExpression + PropertyOrder + Filter + CompositeFilter + PropertyFilter + GqlQuery + GqlQueryArg + QueryResultBatch + Mutation + MutationResult + ReadOptions + LookupRequest + LookupResponse + RunQueryRequest + RunQueryResponse + BeginTransactionRequest + BeginTransactionResponse + RollbackRequest + RollbackResponse + CommitRequest + CommitResponse + AllocateIdsRequest + AllocateIdsResponse +*/ +package datastore + +import proto "github.com/golang/protobuf/proto" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = math.Inf + +// Specifies what data the 'entity' field contains. +// A ResultType is either implied (for example, in LookupResponse.found it +// is always FULL) or specified by context (for example, in message +// QueryResultBatch, field 'entity_result_type' specifies a ResultType +// for all the values in field 'entity_result'). +type EntityResult_ResultType int32 + +const ( + EntityResult_FULL EntityResult_ResultType = 1 + EntityResult_PROJECTION EntityResult_ResultType = 2 + // The entity may have no key. + // A property value may have meaning 18. + EntityResult_KEY_ONLY EntityResult_ResultType = 3 +) + +var EntityResult_ResultType_name = map[int32]string{ + 1: "FULL", + 2: "PROJECTION", + 3: "KEY_ONLY", +} +var EntityResult_ResultType_value = map[string]int32{ + "FULL": 1, + "PROJECTION": 2, + "KEY_ONLY": 3, +} + +func (x EntityResult_ResultType) Enum() *EntityResult_ResultType { + p := new(EntityResult_ResultType) + *p = x + return p +} +func (x EntityResult_ResultType) String() string { + return proto.EnumName(EntityResult_ResultType_name, int32(x)) +} +func (x *EntityResult_ResultType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(EntityResult_ResultType_value, data, "EntityResult_ResultType") + if err != nil { + return err + } + *x = EntityResult_ResultType(value) + return nil +} + +type PropertyExpression_AggregationFunction int32 + +const ( + PropertyExpression_FIRST PropertyExpression_AggregationFunction = 1 +) + +var PropertyExpression_AggregationFunction_name = map[int32]string{ + 1: "FIRST", +} +var PropertyExpression_AggregationFunction_value = map[string]int32{ + "FIRST": 1, +} + +func (x PropertyExpression_AggregationFunction) Enum() *PropertyExpression_AggregationFunction { + p := new(PropertyExpression_AggregationFunction) + *p = x + return p +} +func (x PropertyExpression_AggregationFunction) String() string { + return proto.EnumName(PropertyExpression_AggregationFunction_name, int32(x)) +} +func (x *PropertyExpression_AggregationFunction) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PropertyExpression_AggregationFunction_value, data, "PropertyExpression_AggregationFunction") + if err != nil { + return err + } + *x = PropertyExpression_AggregationFunction(value) + return nil +} + +type PropertyOrder_Direction int32 + +const ( + PropertyOrder_ASCENDING PropertyOrder_Direction = 1 + PropertyOrder_DESCENDING PropertyOrder_Direction = 2 +) + +var PropertyOrder_Direction_name = map[int32]string{ + 1: "ASCENDING", + 2: "DESCENDING", +} +var PropertyOrder_Direction_value = map[string]int32{ + "ASCENDING": 1, + "DESCENDING": 2, +} + +func (x PropertyOrder_Direction) Enum() *PropertyOrder_Direction { + p := new(PropertyOrder_Direction) + *p = x + return p +} +func (x PropertyOrder_Direction) String() string { + return proto.EnumName(PropertyOrder_Direction_name, int32(x)) +} +func (x *PropertyOrder_Direction) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PropertyOrder_Direction_value, data, "PropertyOrder_Direction") + if err != nil { + return err + } + *x = PropertyOrder_Direction(value) + return nil +} + +type CompositeFilter_Operator int32 + +const ( + CompositeFilter_AND CompositeFilter_Operator = 1 +) + +var CompositeFilter_Operator_name = map[int32]string{ + 1: "AND", +} +var CompositeFilter_Operator_value = map[string]int32{ + "AND": 1, +} + +func (x CompositeFilter_Operator) Enum() *CompositeFilter_Operator { + p := new(CompositeFilter_Operator) + *p = x + return p +} +func (x CompositeFilter_Operator) String() string { + return proto.EnumName(CompositeFilter_Operator_name, int32(x)) +} +func (x *CompositeFilter_Operator) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CompositeFilter_Operator_value, data, "CompositeFilter_Operator") + if err != nil { + return err + } + *x = CompositeFilter_Operator(value) + return nil +} + +type PropertyFilter_Operator int32 + +const ( + PropertyFilter_LESS_THAN PropertyFilter_Operator = 1 + PropertyFilter_LESS_THAN_OR_EQUAL PropertyFilter_Operator = 2 + PropertyFilter_GREATER_THAN PropertyFilter_Operator = 3 + PropertyFilter_GREATER_THAN_OR_EQUAL PropertyFilter_Operator = 4 + PropertyFilter_EQUAL PropertyFilter_Operator = 5 + PropertyFilter_HAS_ANCESTOR PropertyFilter_Operator = 11 +) + +var PropertyFilter_Operator_name = map[int32]string{ + 1: "LESS_THAN", + 2: "LESS_THAN_OR_EQUAL", + 3: "GREATER_THAN", + 4: "GREATER_THAN_OR_EQUAL", + 5: "EQUAL", + 11: "HAS_ANCESTOR", +} +var PropertyFilter_Operator_value = map[string]int32{ + "LESS_THAN": 1, + "LESS_THAN_OR_EQUAL": 2, + "GREATER_THAN": 3, + "GREATER_THAN_OR_EQUAL": 4, + "EQUAL": 5, + "HAS_ANCESTOR": 11, +} + +func (x PropertyFilter_Operator) Enum() *PropertyFilter_Operator { + p := new(PropertyFilter_Operator) + *p = x + return p +} +func (x PropertyFilter_Operator) String() string { + return proto.EnumName(PropertyFilter_Operator_name, int32(x)) +} +func (x *PropertyFilter_Operator) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PropertyFilter_Operator_value, data, "PropertyFilter_Operator") + if err != nil { + return err + } + *x = PropertyFilter_Operator(value) + return nil +} + +// The possible values for the 'more_results' field. +type QueryResultBatch_MoreResultsType int32 + +const ( + QueryResultBatch_NOT_FINISHED QueryResultBatch_MoreResultsType = 1 + QueryResultBatch_MORE_RESULTS_AFTER_LIMIT QueryResultBatch_MoreResultsType = 2 + // results after the limit. + QueryResultBatch_NO_MORE_RESULTS QueryResultBatch_MoreResultsType = 3 +) + +var QueryResultBatch_MoreResultsType_name = map[int32]string{ + 1: "NOT_FINISHED", + 2: "MORE_RESULTS_AFTER_LIMIT", + 3: "NO_MORE_RESULTS", +} +var QueryResultBatch_MoreResultsType_value = map[string]int32{ + "NOT_FINISHED": 1, + "MORE_RESULTS_AFTER_LIMIT": 2, + "NO_MORE_RESULTS": 3, +} + +func (x QueryResultBatch_MoreResultsType) Enum() *QueryResultBatch_MoreResultsType { + p := new(QueryResultBatch_MoreResultsType) + *p = x + return p +} +func (x QueryResultBatch_MoreResultsType) String() string { + return proto.EnumName(QueryResultBatch_MoreResultsType_name, int32(x)) +} +func (x *QueryResultBatch_MoreResultsType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(QueryResultBatch_MoreResultsType_value, data, "QueryResultBatch_MoreResultsType") + if err != nil { + return err + } + *x = QueryResultBatch_MoreResultsType(value) + return nil +} + +type ReadOptions_ReadConsistency int32 + +const ( + ReadOptions_DEFAULT ReadOptions_ReadConsistency = 0 + ReadOptions_STRONG ReadOptions_ReadConsistency = 1 + ReadOptions_EVENTUAL ReadOptions_ReadConsistency = 2 +) + +var ReadOptions_ReadConsistency_name = map[int32]string{ + 0: "DEFAULT", + 1: "STRONG", + 2: "EVENTUAL", +} +var ReadOptions_ReadConsistency_value = map[string]int32{ + "DEFAULT": 0, + "STRONG": 1, + "EVENTUAL": 2, +} + +func (x ReadOptions_ReadConsistency) Enum() *ReadOptions_ReadConsistency { + p := new(ReadOptions_ReadConsistency) + *p = x + return p +} +func (x ReadOptions_ReadConsistency) String() string { + return proto.EnumName(ReadOptions_ReadConsistency_name, int32(x)) +} +func (x *ReadOptions_ReadConsistency) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ReadOptions_ReadConsistency_value, data, "ReadOptions_ReadConsistency") + if err != nil { + return err + } + *x = ReadOptions_ReadConsistency(value) + return nil +} + +type BeginTransactionRequest_IsolationLevel int32 + +const ( + BeginTransactionRequest_SNAPSHOT BeginTransactionRequest_IsolationLevel = 0 + // conflict if their mutations conflict. For example: + // Read(A),Write(B) may not conflict with Read(B),Write(A), + // but Read(B),Write(B) does conflict with Read(B),Write(B). + BeginTransactionRequest_SERIALIZABLE BeginTransactionRequest_IsolationLevel = 1 +) + +var BeginTransactionRequest_IsolationLevel_name = map[int32]string{ + 0: "SNAPSHOT", + 1: "SERIALIZABLE", +} +var BeginTransactionRequest_IsolationLevel_value = map[string]int32{ + "SNAPSHOT": 0, + "SERIALIZABLE": 1, +} + +func (x BeginTransactionRequest_IsolationLevel) Enum() *BeginTransactionRequest_IsolationLevel { + p := new(BeginTransactionRequest_IsolationLevel) + *p = x + return p +} +func (x BeginTransactionRequest_IsolationLevel) String() string { + return proto.EnumName(BeginTransactionRequest_IsolationLevel_name, int32(x)) +} +func (x *BeginTransactionRequest_IsolationLevel) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(BeginTransactionRequest_IsolationLevel_value, data, "BeginTransactionRequest_IsolationLevel") + if err != nil { + return err + } + *x = BeginTransactionRequest_IsolationLevel(value) + return nil +} + +type CommitRequest_Mode int32 + +const ( + CommitRequest_TRANSACTIONAL CommitRequest_Mode = 1 + CommitRequest_NON_TRANSACTIONAL CommitRequest_Mode = 2 +) + +var CommitRequest_Mode_name = map[int32]string{ + 1: "TRANSACTIONAL", + 2: "NON_TRANSACTIONAL", +} +var CommitRequest_Mode_value = map[string]int32{ + "TRANSACTIONAL": 1, + "NON_TRANSACTIONAL": 2, +} + +func (x CommitRequest_Mode) Enum() *CommitRequest_Mode { + p := new(CommitRequest_Mode) + *p = x + return p +} +func (x CommitRequest_Mode) String() string { + return proto.EnumName(CommitRequest_Mode_name, int32(x)) +} +func (x *CommitRequest_Mode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(CommitRequest_Mode_value, data, "CommitRequest_Mode") + if err != nil { + return err + } + *x = CommitRequest_Mode(value) + return nil +} + +// An identifier for a particular subset of entities. +// +// Entities are partitioned into various subsets, each used by different +// datasets and different namespaces within a dataset and so forth. +// +// All input partition IDs are normalized before use. +// A partition ID is normalized as follows: +// If the partition ID is unset or is set to an empty partition ID, replace it +// with the context partition ID. +// Otherwise, if the partition ID has no dataset ID, assign it the context +// partition ID's dataset ID. +// Unless otherwise documented, the context partition ID has the dataset ID set +// to the context dataset ID and no other partition dimension set. +// +// A partition ID is empty if all of its fields are unset. +// +// Partition dimension: +// A dimension may be unset. +// A dimension's value must never be "". +// A dimension's value must match [A-Za-z\d\.\-_]{1,100} +// If the value of any dimension matches regex "__.*__", +// the partition is reserved/read-only. +// A reserved/read-only partition ID is forbidden in certain documented contexts. +// +// Dataset ID: +// A dataset id's value must never be "". +// A dataset id's value must match +// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} +type PartitionId struct { + // The dataset ID. + DatasetId *string `protobuf:"bytes,3,opt,name=dataset_id" json:"dataset_id,omitempty"` + // The namespace. + Namespace *string `protobuf:"bytes,4,opt,name=namespace" json:"namespace,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PartitionId) Reset() { *m = PartitionId{} } +func (m *PartitionId) String() string { return proto.CompactTextString(m) } +func (*PartitionId) ProtoMessage() {} + +func (m *PartitionId) GetDatasetId() string { + if m != nil && m.DatasetId != nil { + return *m.DatasetId + } + return "" +} + +func (m *PartitionId) GetNamespace() string { + if m != nil && m.Namespace != nil { + return *m.Namespace + } + return "" +} + +// A unique identifier for an entity. +// If a key's partition id or any of its path kinds or names are +// reserved/read-only, the key is reserved/read-only. +// A reserved/read-only key is forbidden in certain documented contexts. +type Key struct { + // Entities are partitioned into subsets, currently identified by a dataset + // (usually implicitly specified by the project) and namespace ID. + // Queries are scoped to a single partition. + PartitionId *PartitionId `protobuf:"bytes,1,opt,name=partition_id" json:"partition_id,omitempty"` + // The entity path. + // An entity path consists of one or more elements composed of a kind and a + // string or numerical identifier, which identify entities. The first + // element identifies a root entity, the second element identifies + // a child of the root entity, the third element a child of the + // second entity, and so forth. The entities identified by all prefixes of + // the path are called the element's ancestors. + // An entity path is always fully complete: ALL of the entity's ancestors + // are required to be in the path along with the entity identifier itself. + // The only exception is that in some documented cases, the identifier in the + // last path element (for the entity) itself may be omitted. A path can never + // be empty. + PathElement []*Key_PathElement `protobuf:"bytes,2,rep,name=path_element" json:"path_element,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Key) Reset() { *m = Key{} } +func (m *Key) String() string { return proto.CompactTextString(m) } +func (*Key) ProtoMessage() {} + +func (m *Key) GetPartitionId() *PartitionId { + if m != nil { + return m.PartitionId + } + return nil +} + +func (m *Key) GetPathElement() []*Key_PathElement { + if m != nil { + return m.PathElement + } + return nil +} + +// A (kind, ID/name) pair used to construct a key path. +// +// At most one of name or ID may be set. +// If either is set, the element is complete. +// If neither is set, the element is incomplete. +type Key_PathElement struct { + // The kind of the entity. + // A kind matching regex "__.*__" is reserved/read-only. + // A kind must not contain more than 500 characters. + // Cannot be "". + Kind *string `protobuf:"bytes,1,req,name=kind" json:"kind,omitempty"` + // The ID of the entity. + // Never equal to zero. Values less than zero are discouraged and will not + // be supported in the future. + Id *int64 `protobuf:"varint,2,opt,name=id" json:"id,omitempty"` + // The name of the entity. + // A name matching regex "__.*__" is reserved/read-only. + // A name must not be more than 500 characters. + // Cannot be "". + Name *string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Key_PathElement) Reset() { *m = Key_PathElement{} } +func (m *Key_PathElement) String() string { return proto.CompactTextString(m) } +func (*Key_PathElement) ProtoMessage() {} + +func (m *Key_PathElement) GetKind() string { + if m != nil && m.Kind != nil { + return *m.Kind + } + return "" +} + +func (m *Key_PathElement) GetId() int64 { + if m != nil && m.Id != nil { + return *m.Id + } + return 0 +} + +func (m *Key_PathElement) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +// A message that can hold any of the supported value types and associated +// metadata. +// +// At most one of the Value fields may be set. +// If none are set the value is "null". +// +type Value struct { + // A boolean value. + BooleanValue *bool `protobuf:"varint,1,opt,name=boolean_value" json:"boolean_value,omitempty"` + // An integer value. + IntegerValue *int64 `protobuf:"varint,2,opt,name=integer_value" json:"integer_value,omitempty"` + // A double value. + DoubleValue *float64 `protobuf:"fixed64,3,opt,name=double_value" json:"double_value,omitempty"` + // A timestamp value. + TimestampMicrosecondsValue *int64 `protobuf:"varint,4,opt,name=timestamp_microseconds_value" json:"timestamp_microseconds_value,omitempty"` + // A key value. + KeyValue *Key `protobuf:"bytes,5,opt,name=key_value" json:"key_value,omitempty"` + // A blob key value. + BlobKeyValue *string `protobuf:"bytes,16,opt,name=blob_key_value" json:"blob_key_value,omitempty"` + // A UTF-8 encoded string value. + StringValue *string `protobuf:"bytes,17,opt,name=string_value" json:"string_value,omitempty"` + // A blob value. + BlobValue []byte `protobuf:"bytes,18,opt,name=blob_value" json:"blob_value,omitempty"` + // An entity value. + // May have no key. + // May have a key with an incomplete key path. + // May have a reserved/read-only key. + EntityValue *Entity `protobuf:"bytes,6,opt,name=entity_value" json:"entity_value,omitempty"` + // A list value. + // Cannot contain another list value. + // Cannot also have a meaning and indexing set. + ListValue []*Value `protobuf:"bytes,7,rep,name=list_value" json:"list_value,omitempty"` + // The meaning field is reserved and should not be used. + Meaning *int32 `protobuf:"varint,14,opt,name=meaning" json:"meaning,omitempty"` + // If the value should be indexed. + // + // The indexed property may be set for a + // null value. + // When indexed is true, stringValue + // is limited to 500 characters and the blob value is limited to 500 bytes. + // Exception: If meaning is set to 2, string_value is limited to 2038 + // characters regardless of indexed. + // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 + // will be ignored on input (and will never be set on output). + // Input values by default have indexed set to + // true; however, you can explicitly set indexed to + // true if you want. (An output value never has + // indexed explicitly set to true.) If a value is + // itself an entity, it cannot have indexed set to + // true. + // Exception: An entity value with meaning 9, 20 or 21 may be indexed. + Indexed *bool `protobuf:"varint,15,opt,name=indexed,def=1" json:"indexed,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} + +const Default_Value_Indexed bool = true + +func (m *Value) GetBooleanValue() bool { + if m != nil && m.BooleanValue != nil { + return *m.BooleanValue + } + return false +} + +func (m *Value) GetIntegerValue() int64 { + if m != nil && m.IntegerValue != nil { + return *m.IntegerValue + } + return 0 +} + +func (m *Value) GetDoubleValue() float64 { + if m != nil && m.DoubleValue != nil { + return *m.DoubleValue + } + return 0 +} + +func (m *Value) GetTimestampMicrosecondsValue() int64 { + if m != nil && m.TimestampMicrosecondsValue != nil { + return *m.TimestampMicrosecondsValue + } + return 0 +} + +func (m *Value) GetKeyValue() *Key { + if m != nil { + return m.KeyValue + } + return nil +} + +func (m *Value) GetBlobKeyValue() string { + if m != nil && m.BlobKeyValue != nil { + return *m.BlobKeyValue + } + return "" +} + +func (m *Value) GetStringValue() string { + if m != nil && m.StringValue != nil { + return *m.StringValue + } + return "" +} + +func (m *Value) GetBlobValue() []byte { + if m != nil { + return m.BlobValue + } + return nil +} + +func (m *Value) GetEntityValue() *Entity { + if m != nil { + return m.EntityValue + } + return nil +} + +func (m *Value) GetListValue() []*Value { + if m != nil { + return m.ListValue + } + return nil +} + +func (m *Value) GetMeaning() int32 { + if m != nil && m.Meaning != nil { + return *m.Meaning + } + return 0 +} + +func (m *Value) GetIndexed() bool { + if m != nil && m.Indexed != nil { + return *m.Indexed + } + return Default_Value_Indexed +} + +// An entity property. +type Property struct { + // The name of the property. + // A property name matching regex "__.*__" is reserved. + // A reserved property name is forbidden in certain documented contexts. + // The name must not contain more than 500 characters. + // Cannot be "". + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + // The value(s) of the property. + // Each value can have only one value property populated. For example, + // you cannot have a values list of { value: { integerValue: 22, + // stringValue: "a" } }, but you can have { value: { listValue: + // [ { integerValue: 22 }, { stringValue: "a" } ] }. + Value *Value `protobuf:"bytes,4,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Property) Reset() { *m = Property{} } +func (m *Property) String() string { return proto.CompactTextString(m) } +func (*Property) ProtoMessage() {} + +func (m *Property) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *Property) GetValue() *Value { + if m != nil { + return m.Value + } + return nil +} + +// An entity. +// +// An entity is limited to 1 megabyte when stored. That roughly +// corresponds to a limit of 1 megabyte for the serialized form of this +// message. +type Entity struct { + // The entity's key. + // + // An entity must have a key, unless otherwise documented (for example, + // an entity in Value.entityValue may have no key). + // An entity's kind is its key's path's last element's kind, + // or null if it has no key. + Key *Key `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + // The entity's properties. + // Each property's name must be unique for its entity. + Property []*Property `protobuf:"bytes,2,rep,name=property" json:"property,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Entity) Reset() { *m = Entity{} } +func (m *Entity) String() string { return proto.CompactTextString(m) } +func (*Entity) ProtoMessage() {} + +func (m *Entity) GetKey() *Key { + if m != nil { + return m.Key + } + return nil +} + +func (m *Entity) GetProperty() []*Property { + if m != nil { + return m.Property + } + return nil +} + +// The result of fetching an entity from the datastore. +type EntityResult struct { + // The resulting entity. + Entity *Entity `protobuf:"bytes,1,req,name=entity" json:"entity,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EntityResult) Reset() { *m = EntityResult{} } +func (m *EntityResult) String() string { return proto.CompactTextString(m) } +func (*EntityResult) ProtoMessage() {} + +func (m *EntityResult) GetEntity() *Entity { + if m != nil { + return m.Entity + } + return nil +} + +// A query. +type Query struct { + // The projection to return. If not set the entire entity is returned. + Projection []*PropertyExpression `protobuf:"bytes,2,rep,name=projection" json:"projection,omitempty"` + // The kinds to query (if empty, returns entities from all kinds). + Kind []*KindExpression `protobuf:"bytes,3,rep,name=kind" json:"kind,omitempty"` + // The filter to apply (optional). + Filter *Filter `protobuf:"bytes,4,opt,name=filter" json:"filter,omitempty"` + // The order to apply to the query results (if empty, order is unspecified). + Order []*PropertyOrder `protobuf:"bytes,5,rep,name=order" json:"order,omitempty"` + // The properties to group by (if empty, no grouping is applied to the + // result set). + GroupBy []*PropertyReference `protobuf:"bytes,6,rep,name=group_by" json:"group_by,omitempty"` + // A starting point for the query results. Optional. Query cursors are + // returned in query result batches. + StartCursor []byte `protobuf:"bytes,7,opt,name=start_cursor" json:"start_cursor,omitempty"` + // An ending point for the query results. Optional. Query cursors are + // returned in query result batches. + EndCursor []byte `protobuf:"bytes,8,opt,name=end_cursor" json:"end_cursor,omitempty"` + // The number of results to skip. Applies before limit, but after all other + // constraints (optional, defaults to 0). + Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` + // The maximum number of results to return. Applies after all other + // constraints. Optional. + Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Query) Reset() { *m = Query{} } +func (m *Query) String() string { return proto.CompactTextString(m) } +func (*Query) ProtoMessage() {} + +const Default_Query_Offset int32 = 0 + +func (m *Query) GetProjection() []*PropertyExpression { + if m != nil { + return m.Projection + } + return nil +} + +func (m *Query) GetKind() []*KindExpression { + if m != nil { + return m.Kind + } + return nil +} + +func (m *Query) GetFilter() *Filter { + if m != nil { + return m.Filter + } + return nil +} + +func (m *Query) GetOrder() []*PropertyOrder { + if m != nil { + return m.Order + } + return nil +} + +func (m *Query) GetGroupBy() []*PropertyReference { + if m != nil { + return m.GroupBy + } + return nil +} + +func (m *Query) GetStartCursor() []byte { + if m != nil { + return m.StartCursor + } + return nil +} + +func (m *Query) GetEndCursor() []byte { + if m != nil { + return m.EndCursor + } + return nil +} + +func (m *Query) GetOffset() int32 { + if m != nil && m.Offset != nil { + return *m.Offset + } + return Default_Query_Offset +} + +func (m *Query) GetLimit() int32 { + if m != nil && m.Limit != nil { + return *m.Limit + } + return 0 +} + +// A representation of a kind. +type KindExpression struct { + // The name of the kind. + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *KindExpression) Reset() { *m = KindExpression{} } +func (m *KindExpression) String() string { return proto.CompactTextString(m) } +func (*KindExpression) ProtoMessage() {} + +func (m *KindExpression) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +// A reference to a property relative to the kind expressions. +// exactly. +type PropertyReference struct { + // The name of the property. + Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyReference) Reset() { *m = PropertyReference{} } +func (m *PropertyReference) String() string { return proto.CompactTextString(m) } +func (*PropertyReference) ProtoMessage() {} + +func (m *PropertyReference) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +// A representation of a property in a projection. +type PropertyExpression struct { + // The property to project. + Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` + // The aggregation function to apply to the property. Optional. + // Can only be used when grouping by at least one property. Must + // then be set on all properties in the projection that are not + // being grouped by. + AggregationFunction *PropertyExpression_AggregationFunction `protobuf:"varint,2,opt,name=aggregation_function,enum=datastore.PropertyExpression_AggregationFunction" json:"aggregation_function,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyExpression) Reset() { *m = PropertyExpression{} } +func (m *PropertyExpression) String() string { return proto.CompactTextString(m) } +func (*PropertyExpression) ProtoMessage() {} + +func (m *PropertyExpression) GetProperty() *PropertyReference { + if m != nil { + return m.Property + } + return nil +} + +func (m *PropertyExpression) GetAggregationFunction() PropertyExpression_AggregationFunction { + if m != nil && m.AggregationFunction != nil { + return *m.AggregationFunction + } + return PropertyExpression_FIRST +} + +// The desired order for a specific property. +type PropertyOrder struct { + // The property to order by. + Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` + // The direction to order by. + Direction *PropertyOrder_Direction `protobuf:"varint,2,opt,name=direction,enum=datastore.PropertyOrder_Direction,def=1" json:"direction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyOrder) Reset() { *m = PropertyOrder{} } +func (m *PropertyOrder) String() string { return proto.CompactTextString(m) } +func (*PropertyOrder) ProtoMessage() {} + +const Default_PropertyOrder_Direction PropertyOrder_Direction = PropertyOrder_ASCENDING + +func (m *PropertyOrder) GetProperty() *PropertyReference { + if m != nil { + return m.Property + } + return nil +} + +func (m *PropertyOrder) GetDirection() PropertyOrder_Direction { + if m != nil && m.Direction != nil { + return *m.Direction + } + return Default_PropertyOrder_Direction +} + +// A holder for any type of filter. Exactly one field should be specified. +type Filter struct { + // A composite filter. + CompositeFilter *CompositeFilter `protobuf:"bytes,1,opt,name=composite_filter" json:"composite_filter,omitempty"` + // A filter on a property. + PropertyFilter *PropertyFilter `protobuf:"bytes,2,opt,name=property_filter" json:"property_filter,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Filter) Reset() { *m = Filter{} } +func (m *Filter) String() string { return proto.CompactTextString(m) } +func (*Filter) ProtoMessage() {} + +func (m *Filter) GetCompositeFilter() *CompositeFilter { + if m != nil { + return m.CompositeFilter + } + return nil +} + +func (m *Filter) GetPropertyFilter() *PropertyFilter { + if m != nil { + return m.PropertyFilter + } + return nil +} + +// A filter that merges the multiple other filters using the given operation. +type CompositeFilter struct { + // The operator for combining multiple filters. + Operator *CompositeFilter_Operator `protobuf:"varint,1,req,name=operator,enum=datastore.CompositeFilter_Operator" json:"operator,omitempty"` + // The list of filters to combine. + // Must contain at least one filter. + Filter []*Filter `protobuf:"bytes,2,rep,name=filter" json:"filter,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CompositeFilter) Reset() { *m = CompositeFilter{} } +func (m *CompositeFilter) String() string { return proto.CompactTextString(m) } +func (*CompositeFilter) ProtoMessage() {} + +func (m *CompositeFilter) GetOperator() CompositeFilter_Operator { + if m != nil && m.Operator != nil { + return *m.Operator + } + return CompositeFilter_AND +} + +func (m *CompositeFilter) GetFilter() []*Filter { + if m != nil { + return m.Filter + } + return nil +} + +// A filter on a specific property. +type PropertyFilter struct { + // The property to filter by. + Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` + // The operator to filter by. + Operator *PropertyFilter_Operator `protobuf:"varint,2,req,name=operator,enum=datastore.PropertyFilter_Operator" json:"operator,omitempty"` + // The value to compare the property to. + Value *Value `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PropertyFilter) Reset() { *m = PropertyFilter{} } +func (m *PropertyFilter) String() string { return proto.CompactTextString(m) } +func (*PropertyFilter) ProtoMessage() {} + +func (m *PropertyFilter) GetProperty() *PropertyReference { + if m != nil { + return m.Property + } + return nil +} + +func (m *PropertyFilter) GetOperator() PropertyFilter_Operator { + if m != nil && m.Operator != nil { + return *m.Operator + } + return PropertyFilter_LESS_THAN +} + +func (m *PropertyFilter) GetValue() *Value { + if m != nil { + return m.Value + } + return nil +} + +// A GQL query. +type GqlQuery struct { + QueryString *string `protobuf:"bytes,1,req,name=query_string" json:"query_string,omitempty"` + // When false, the query string must not contain a literal. + AllowLiteral *bool `protobuf:"varint,2,opt,name=allow_literal,def=0" json:"allow_literal,omitempty"` + // A named argument must set field GqlQueryArg.name. + // No two named arguments may have the same name. + // For each non-reserved named binding site in the query string, + // there must be a named argument with that name, + // but not necessarily the inverse. + NameArg []*GqlQueryArg `protobuf:"bytes,3,rep,name=name_arg" json:"name_arg,omitempty"` + // Numbered binding site @1 references the first numbered argument, + // effectively using 1-based indexing, rather than the usual 0. + // A numbered argument must NOT set field GqlQueryArg.name. + // For each binding site numbered i in query_string, + // there must be an ith numbered argument. + // The inverse must also be true. + NumberArg []*GqlQueryArg `protobuf:"bytes,4,rep,name=number_arg" json:"number_arg,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GqlQuery) Reset() { *m = GqlQuery{} } +func (m *GqlQuery) String() string { return proto.CompactTextString(m) } +func (*GqlQuery) ProtoMessage() {} + +const Default_GqlQuery_AllowLiteral bool = false + +func (m *GqlQuery) GetQueryString() string { + if m != nil && m.QueryString != nil { + return *m.QueryString + } + return "" +} + +func (m *GqlQuery) GetAllowLiteral() bool { + if m != nil && m.AllowLiteral != nil { + return *m.AllowLiteral + } + return Default_GqlQuery_AllowLiteral +} + +func (m *GqlQuery) GetNameArg() []*GqlQueryArg { + if m != nil { + return m.NameArg + } + return nil +} + +func (m *GqlQuery) GetNumberArg() []*GqlQueryArg { + if m != nil { + return m.NumberArg + } + return nil +} + +// A binding argument for a GQL query. +// Exactly one of fields value and cursor must be set. +type GqlQueryArg struct { + // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". + // Must not match regex "__.*__". + // Must not be "". + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value *Value `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + Cursor []byte `protobuf:"bytes,3,opt,name=cursor" json:"cursor,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GqlQueryArg) Reset() { *m = GqlQueryArg{} } +func (m *GqlQueryArg) String() string { return proto.CompactTextString(m) } +func (*GqlQueryArg) ProtoMessage() {} + +func (m *GqlQueryArg) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *GqlQueryArg) GetValue() *Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *GqlQueryArg) GetCursor() []byte { + if m != nil { + return m.Cursor + } + return nil +} + +// A batch of results produced by a query. +type QueryResultBatch struct { + // The result type for every entity in entityResults. + EntityResultType *EntityResult_ResultType `protobuf:"varint,1,req,name=entity_result_type,enum=datastore.EntityResult_ResultType" json:"entity_result_type,omitempty"` + // The results for this batch. + EntityResult []*EntityResult `protobuf:"bytes,2,rep,name=entity_result" json:"entity_result,omitempty"` + // A cursor that points to the position after the last result in the batch. + // May be absent. + EndCursor []byte `protobuf:"bytes,4,opt,name=end_cursor" json:"end_cursor,omitempty"` + // The state of the query after the current batch. + MoreResults *QueryResultBatch_MoreResultsType `protobuf:"varint,5,req,name=more_results,enum=datastore.QueryResultBatch_MoreResultsType" json:"more_results,omitempty"` + // The number of results skipped because of Query.offset. + SkippedResults *int32 `protobuf:"varint,6,opt,name=skipped_results" json:"skipped_results,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *QueryResultBatch) Reset() { *m = QueryResultBatch{} } +func (m *QueryResultBatch) String() string { return proto.CompactTextString(m) } +func (*QueryResultBatch) ProtoMessage() {} + +func (m *QueryResultBatch) GetEntityResultType() EntityResult_ResultType { + if m != nil && m.EntityResultType != nil { + return *m.EntityResultType + } + return EntityResult_FULL +} + +func (m *QueryResultBatch) GetEntityResult() []*EntityResult { + if m != nil { + return m.EntityResult + } + return nil +} + +func (m *QueryResultBatch) GetEndCursor() []byte { + if m != nil { + return m.EndCursor + } + return nil +} + +func (m *QueryResultBatch) GetMoreResults() QueryResultBatch_MoreResultsType { + if m != nil && m.MoreResults != nil { + return *m.MoreResults + } + return QueryResultBatch_NOT_FINISHED +} + +func (m *QueryResultBatch) GetSkippedResults() int32 { + if m != nil && m.SkippedResults != nil { + return *m.SkippedResults + } + return 0 +} + +// A set of changes to apply. +// +// No entity in this message may have a reserved property name, +// not even a property in an entity in a value. +// No value in this message may have meaning 18, +// not even a value in an entity in another value. +// +// If entities with duplicate keys are present, an arbitrary choice will +// be made as to which is written. +type Mutation struct { + // Entities to upsert. + // Each upserted entity's key must have a complete path and + // must not be reserved/read-only. + Upsert []*Entity `protobuf:"bytes,1,rep,name=upsert" json:"upsert,omitempty"` + // Entities to update. + // Each updated entity's key must have a complete path and + // must not be reserved/read-only. + Update []*Entity `protobuf:"bytes,2,rep,name=update" json:"update,omitempty"` + // Entities to insert. + // Each inserted entity's key must have a complete path and + // must not be reserved/read-only. + Insert []*Entity `protobuf:"bytes,3,rep,name=insert" json:"insert,omitempty"` + // Insert entities with a newly allocated ID. + // Each inserted entity's key must omit the final identifier in its path and + // must not be reserved/read-only. + InsertAutoId []*Entity `protobuf:"bytes,4,rep,name=insert_auto_id" json:"insert_auto_id,omitempty"` + // Keys of entities to delete. + // Each key must have a complete key path and must not be reserved/read-only. + Delete []*Key `protobuf:"bytes,5,rep,name=delete" json:"delete,omitempty"` + // Ignore a user specified read-only period. Optional. + Force *bool `protobuf:"varint,6,opt,name=force" json:"force,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Mutation) Reset() { *m = Mutation{} } +func (m *Mutation) String() string { return proto.CompactTextString(m) } +func (*Mutation) ProtoMessage() {} + +func (m *Mutation) GetUpsert() []*Entity { + if m != nil { + return m.Upsert + } + return nil +} + +func (m *Mutation) GetUpdate() []*Entity { + if m != nil { + return m.Update + } + return nil +} + +func (m *Mutation) GetInsert() []*Entity { + if m != nil { + return m.Insert + } + return nil +} + +func (m *Mutation) GetInsertAutoId() []*Entity { + if m != nil { + return m.InsertAutoId + } + return nil +} + +func (m *Mutation) GetDelete() []*Key { + if m != nil { + return m.Delete + } + return nil +} + +func (m *Mutation) GetForce() bool { + if m != nil && m.Force != nil { + return *m.Force + } + return false +} + +// The result of applying a mutation. +type MutationResult struct { + // Number of index writes. + IndexUpdates *int32 `protobuf:"varint,1,req,name=index_updates" json:"index_updates,omitempty"` + // Keys for insertAutoId entities. One per entity from the + // request, in the same order. + InsertAutoIdKey []*Key `protobuf:"bytes,2,rep,name=insert_auto_id_key" json:"insert_auto_id_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MutationResult) Reset() { *m = MutationResult{} } +func (m *MutationResult) String() string { return proto.CompactTextString(m) } +func (*MutationResult) ProtoMessage() {} + +func (m *MutationResult) GetIndexUpdates() int32 { + if m != nil && m.IndexUpdates != nil { + return *m.IndexUpdates + } + return 0 +} + +func (m *MutationResult) GetInsertAutoIdKey() []*Key { + if m != nil { + return m.InsertAutoIdKey + } + return nil +} + +// Options shared by read requests. +type ReadOptions struct { + // The read consistency to use. + // Cannot be set when transaction is set. + // Lookup and ancestor queries default to STRONG, global queries default to + // EVENTUAL and cannot be set to STRONG. + ReadConsistency *ReadOptions_ReadConsistency `protobuf:"varint,1,opt,name=read_consistency,enum=datastore.ReadOptions_ReadConsistency,def=0" json:"read_consistency,omitempty"` + // The transaction to use. Optional. + Transaction []byte `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ReadOptions) Reset() { *m = ReadOptions{} } +func (m *ReadOptions) String() string { return proto.CompactTextString(m) } +func (*ReadOptions) ProtoMessage() {} + +const Default_ReadOptions_ReadConsistency ReadOptions_ReadConsistency = ReadOptions_DEFAULT + +func (m *ReadOptions) GetReadConsistency() ReadOptions_ReadConsistency { + if m != nil && m.ReadConsistency != nil { + return *m.ReadConsistency + } + return Default_ReadOptions_ReadConsistency +} + +func (m *ReadOptions) GetTransaction() []byte { + if m != nil { + return m.Transaction + } + return nil +} + +// The request for Lookup. +type LookupRequest struct { + // Options for this lookup request. Optional. + ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` + // Keys of entities to look up from the datastore. + Key []*Key `protobuf:"bytes,3,rep,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LookupRequest) Reset() { *m = LookupRequest{} } +func (m *LookupRequest) String() string { return proto.CompactTextString(m) } +func (*LookupRequest) ProtoMessage() {} + +func (m *LookupRequest) GetReadOptions() *ReadOptions { + if m != nil { + return m.ReadOptions + } + return nil +} + +func (m *LookupRequest) GetKey() []*Key { + if m != nil { + return m.Key + } + return nil +} + +// The response for Lookup. +type LookupResponse struct { + // Entities found as ResultType.FULL entities. + Found []*EntityResult `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` + // Entities not found as ResultType.KEY_ONLY entities. + Missing []*EntityResult `protobuf:"bytes,2,rep,name=missing" json:"missing,omitempty"` + // A list of keys that were not looked up due to resource constraints. + Deferred []*Key `protobuf:"bytes,3,rep,name=deferred" json:"deferred,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LookupResponse) Reset() { *m = LookupResponse{} } +func (m *LookupResponse) String() string { return proto.CompactTextString(m) } +func (*LookupResponse) ProtoMessage() {} + +func (m *LookupResponse) GetFound() []*EntityResult { + if m != nil { + return m.Found + } + return nil +} + +func (m *LookupResponse) GetMissing() []*EntityResult { + if m != nil { + return m.Missing + } + return nil +} + +func (m *LookupResponse) GetDeferred() []*Key { + if m != nil { + return m.Deferred + } + return nil +} + +// The request for RunQuery. +type RunQueryRequest struct { + // The options for this query. + ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` + // Entities are partitioned into subsets, identified by a dataset (usually + // implicitly specified by the project) and namespace ID. Queries are scoped + // to a single partition. + // This partition ID is normalized with the standard default context + // partition ID, but all other partition IDs in RunQueryRequest are + // normalized with this partition ID as the context partition ID. + PartitionId *PartitionId `protobuf:"bytes,2,opt,name=partition_id" json:"partition_id,omitempty"` + // The query to run. + // Either this field or field gql_query must be set, but not both. + Query *Query `protobuf:"bytes,3,opt,name=query" json:"query,omitempty"` + // The GQL query to run. + // Either this field or field query must be set, but not both. + GqlQuery *GqlQuery `protobuf:"bytes,7,opt,name=gql_query" json:"gql_query,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RunQueryRequest) Reset() { *m = RunQueryRequest{} } +func (m *RunQueryRequest) String() string { return proto.CompactTextString(m) } +func (*RunQueryRequest) ProtoMessage() {} + +func (m *RunQueryRequest) GetReadOptions() *ReadOptions { + if m != nil { + return m.ReadOptions + } + return nil +} + +func (m *RunQueryRequest) GetPartitionId() *PartitionId { + if m != nil { + return m.PartitionId + } + return nil +} + +func (m *RunQueryRequest) GetQuery() *Query { + if m != nil { + return m.Query + } + return nil +} + +func (m *RunQueryRequest) GetGqlQuery() *GqlQuery { + if m != nil { + return m.GqlQuery + } + return nil +} + +// The response for RunQuery. +type RunQueryResponse struct { + // A batch of query results (always present). + Batch *QueryResultBatch `protobuf:"bytes,1,opt,name=batch" json:"batch,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RunQueryResponse) Reset() { *m = RunQueryResponse{} } +func (m *RunQueryResponse) String() string { return proto.CompactTextString(m) } +func (*RunQueryResponse) ProtoMessage() {} + +func (m *RunQueryResponse) GetBatch() *QueryResultBatch { + if m != nil { + return m.Batch + } + return nil +} + +// The request for BeginTransaction. +type BeginTransactionRequest struct { + // The transaction isolation level. + IsolationLevel *BeginTransactionRequest_IsolationLevel `protobuf:"varint,1,opt,name=isolation_level,enum=datastore.BeginTransactionRequest_IsolationLevel,def=0" json:"isolation_level,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } +func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } +func (*BeginTransactionRequest) ProtoMessage() {} + +const Default_BeginTransactionRequest_IsolationLevel BeginTransactionRequest_IsolationLevel = BeginTransactionRequest_SNAPSHOT + +func (m *BeginTransactionRequest) GetIsolationLevel() BeginTransactionRequest_IsolationLevel { + if m != nil && m.IsolationLevel != nil { + return *m.IsolationLevel + } + return Default_BeginTransactionRequest_IsolationLevel +} + +// The response for BeginTransaction. +type BeginTransactionResponse struct { + // The transaction identifier (always present). + Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *BeginTransactionResponse) Reset() { *m = BeginTransactionResponse{} } +func (m *BeginTransactionResponse) String() string { return proto.CompactTextString(m) } +func (*BeginTransactionResponse) ProtoMessage() {} + +func (m *BeginTransactionResponse) GetTransaction() []byte { + if m != nil { + return m.Transaction + } + return nil +} + +// The request for Rollback. +type RollbackRequest struct { + // The transaction identifier, returned by a call to + // beginTransaction. + Transaction []byte `protobuf:"bytes,1,req,name=transaction" json:"transaction,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } +func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } +func (*RollbackRequest) ProtoMessage() {} + +func (m *RollbackRequest) GetTransaction() []byte { + if m != nil { + return m.Transaction + } + return nil +} + +// The response for Rollback. +type RollbackResponse struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } +func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } +func (*RollbackResponse) ProtoMessage() {} + +// The request for Commit. +type CommitRequest struct { + // The transaction identifier, returned by a call to + // beginTransaction. Must be set when mode is TRANSACTIONAL. + Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` + // The mutation to perform. Optional. + Mutation *Mutation `protobuf:"bytes,2,opt,name=mutation" json:"mutation,omitempty"` + // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. + Mode *CommitRequest_Mode `protobuf:"varint,5,opt,name=mode,enum=datastore.CommitRequest_Mode,def=1" json:"mode,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CommitRequest) Reset() { *m = CommitRequest{} } +func (m *CommitRequest) String() string { return proto.CompactTextString(m) } +func (*CommitRequest) ProtoMessage() {} + +const Default_CommitRequest_Mode CommitRequest_Mode = CommitRequest_TRANSACTIONAL + +func (m *CommitRequest) GetTransaction() []byte { + if m != nil { + return m.Transaction + } + return nil +} + +func (m *CommitRequest) GetMutation() *Mutation { + if m != nil { + return m.Mutation + } + return nil +} + +func (m *CommitRequest) GetMode() CommitRequest_Mode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_CommitRequest_Mode +} + +// The response for Commit. +type CommitResponse struct { + // The result of performing the mutation (if any). + MutationResult *MutationResult `protobuf:"bytes,1,opt,name=mutation_result" json:"mutation_result,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CommitResponse) Reset() { *m = CommitResponse{} } +func (m *CommitResponse) String() string { return proto.CompactTextString(m) } +func (*CommitResponse) ProtoMessage() {} + +func (m *CommitResponse) GetMutationResult() *MutationResult { + if m != nil { + return m.MutationResult + } + return nil +} + +// The request for AllocateIds. +type AllocateIdsRequest struct { + // A list of keys with incomplete key paths to allocate IDs for. + // No key may be reserved/read-only. + Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } +func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsRequest) ProtoMessage() {} + +func (m *AllocateIdsRequest) GetKey() []*Key { + if m != nil { + return m.Key + } + return nil +} + +// The response for AllocateIds. +type AllocateIdsResponse struct { + // The keys specified in the request (in the same order), each with + // its key path completed with a newly allocated ID. + Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } +func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsResponse) ProtoMessage() {} + +func (m *AllocateIdsResponse) GetKey() []*Key { + if m != nil { + return m.Key + } + return nil +} + +func init() { + proto.RegisterEnum("datastore.EntityResult_ResultType", EntityResult_ResultType_name, EntityResult_ResultType_value) + proto.RegisterEnum("datastore.PropertyExpression_AggregationFunction", PropertyExpression_AggregationFunction_name, PropertyExpression_AggregationFunction_value) + proto.RegisterEnum("datastore.PropertyOrder_Direction", PropertyOrder_Direction_name, PropertyOrder_Direction_value) + proto.RegisterEnum("datastore.CompositeFilter_Operator", CompositeFilter_Operator_name, CompositeFilter_Operator_value) + proto.RegisterEnum("datastore.PropertyFilter_Operator", PropertyFilter_Operator_name, PropertyFilter_Operator_value) + proto.RegisterEnum("datastore.QueryResultBatch_MoreResultsType", QueryResultBatch_MoreResultsType_name, QueryResultBatch_MoreResultsType_value) + proto.RegisterEnum("datastore.ReadOptions_ReadConsistency", ReadOptions_ReadConsistency_name, ReadOptions_ReadConsistency_value) + proto.RegisterEnum("datastore.BeginTransactionRequest_IsolationLevel", BeginTransactionRequest_IsolationLevel_name, BeginTransactionRequest_IsolationLevel_value) + proto.RegisterEnum("datastore.CommitRequest_Mode", CommitRequest_Mode_name, CommitRequest_Mode_value) +} diff --git a/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto new file mode 100644 index 000000000..d752beaa5 --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/datastore/datastore_v1.proto @@ -0,0 +1,606 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The datastore v1 service proto definitions + +syntax = "proto2"; + +package datastore; +option java_package = "com.google.api.services.datastore"; + + +// An identifier for a particular subset of entities. +// +// Entities are partitioned into various subsets, each used by different +// datasets and different namespaces within a dataset and so forth. +// +// All input partition IDs are normalized before use. +// A partition ID is normalized as follows: +// If the partition ID is unset or is set to an empty partition ID, replace it +// with the context partition ID. +// Otherwise, if the partition ID has no dataset ID, assign it the context +// partition ID's dataset ID. +// Unless otherwise documented, the context partition ID has the dataset ID set +// to the context dataset ID and no other partition dimension set. +// +// A partition ID is empty if all of its fields are unset. +// +// Partition dimension: +// A dimension may be unset. +// A dimension's value must never be "". +// A dimension's value must match [A-Za-z\d\.\-_]{1,100} +// If the value of any dimension matches regex "__.*__", +// the partition is reserved/read-only. +// A reserved/read-only partition ID is forbidden in certain documented contexts. +// +// Dataset ID: +// A dataset id's value must never be "". +// A dataset id's value must match +// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} +message PartitionId { + // The dataset ID. + optional string dataset_id = 3; + // The namespace. + optional string namespace = 4; +} + +// A unique identifier for an entity. +// If a key's partition id or any of its path kinds or names are +// reserved/read-only, the key is reserved/read-only. +// A reserved/read-only key is forbidden in certain documented contexts. +message Key { + // Entities are partitioned into subsets, currently identified by a dataset + // (usually implicitly specified by the project) and namespace ID. + // Queries are scoped to a single partition. + optional PartitionId partition_id = 1; + + // A (kind, ID/name) pair used to construct a key path. + // + // At most one of name or ID may be set. + // If either is set, the element is complete. + // If neither is set, the element is incomplete. + message PathElement { + // The kind of the entity. + // A kind matching regex "__.*__" is reserved/read-only. + // A kind must not contain more than 500 characters. + // Cannot be "". + required string kind = 1; + // The ID of the entity. + // Never equal to zero. Values less than zero are discouraged and will not + // be supported in the future. + optional int64 id = 2; + // The name of the entity. + // A name matching regex "__.*__" is reserved/read-only. + // A name must not be more than 500 characters. + // Cannot be "". + optional string name = 3; + } + + // The entity path. + // An entity path consists of one or more elements composed of a kind and a + // string or numerical identifier, which identify entities. The first + // element identifies a root entity, the second element identifies + // a child of the root entity, the third element a child of the + // second entity, and so forth. The entities identified by all prefixes of + // the path are called the element's ancestors. + // An entity path is always fully complete: ALL of the entity's ancestors + // are required to be in the path along with the entity identifier itself. + // The only exception is that in some documented cases, the identifier in the + // last path element (for the entity) itself may be omitted. A path can never + // be empty. + repeated PathElement path_element = 2; +} + +// A message that can hold any of the supported value types and associated +// metadata. +// +// At most one of the Value fields may be set. +// If none are set the value is "null". +// +message Value { + // A boolean value. + optional bool boolean_value = 1; + // An integer value. + optional int64 integer_value = 2; + // A double value. + optional double double_value = 3; + // A timestamp value. + optional int64 timestamp_microseconds_value = 4; + // A key value. + optional Key key_value = 5; + // A blob key value. + optional string blob_key_value = 16; + // A UTF-8 encoded string value. + optional string string_value = 17; + // A blob value. + optional bytes blob_value = 18; + // An entity value. + // May have no key. + // May have a key with an incomplete key path. + // May have a reserved/read-only key. + optional Entity entity_value = 6; + // A list value. + // Cannot contain another list value. + // Cannot also have a meaning and indexing set. + repeated Value list_value = 7; + + // The meaning field is reserved and should not be used. + optional int32 meaning = 14; + + // If the value should be indexed. + // + // The indexed property may be set for a + // null value. + // When indexed is true, stringValue + // is limited to 500 characters and the blob value is limited to 500 bytes. + // Exception: If meaning is set to 2, string_value is limited to 2038 + // characters regardless of indexed. + // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 + // will be ignored on input (and will never be set on output). + // Input values by default have indexed set to + // true; however, you can explicitly set indexed to + // true if you want. (An output value never has + // indexed explicitly set to true.) If a value is + // itself an entity, it cannot have indexed set to + // true. + // Exception: An entity value with meaning 9, 20 or 21 may be indexed. + optional bool indexed = 15 [default = true]; +} + +// An entity property. +message Property { + // The name of the property. + // A property name matching regex "__.*__" is reserved. + // A reserved property name is forbidden in certain documented contexts. + // The name must not contain more than 500 characters. + // Cannot be "". + required string name = 1; + + // The value(s) of the property. + // Each value can have only one value property populated. For example, + // you cannot have a values list of { value: { integerValue: 22, + // stringValue: "a" } }, but you can have { value: { listValue: + // [ { integerValue: 22 }, { stringValue: "a" } ] }. + required Value value = 4; +} + +// An entity. +// +// An entity is limited to 1 megabyte when stored. That roughly +// corresponds to a limit of 1 megabyte for the serialized form of this +// message. +message Entity { + // The entity's key. + // + // An entity must have a key, unless otherwise documented (for example, + // an entity in Value.entityValue may have no key). + // An entity's kind is its key's path's last element's kind, + // or null if it has no key. + optional Key key = 1; + // The entity's properties. + // Each property's name must be unique for its entity. + repeated Property property = 2; +} + +// The result of fetching an entity from the datastore. +message EntityResult { + // Specifies what data the 'entity' field contains. + // A ResultType is either implied (for example, in LookupResponse.found it + // is always FULL) or specified by context (for example, in message + // QueryResultBatch, field 'entity_result_type' specifies a ResultType + // for all the values in field 'entity_result'). + enum ResultType { + FULL = 1; // The entire entity. + PROJECTION = 2; // A projected subset of properties. + // The entity may have no key. + // A property value may have meaning 18. + KEY_ONLY = 3; // Only the key. + } + + // The resulting entity. + required Entity entity = 1; +} + +// A query. +message Query { + // The projection to return. If not set the entire entity is returned. + repeated PropertyExpression projection = 2; + + // The kinds to query (if empty, returns entities from all kinds). + repeated KindExpression kind = 3; + + // The filter to apply (optional). + optional Filter filter = 4; + + // The order to apply to the query results (if empty, order is unspecified). + repeated PropertyOrder order = 5; + + // The properties to group by (if empty, no grouping is applied to the + // result set). + repeated PropertyReference group_by = 6; + + // A starting point for the query results. Optional. Query cursors are + // returned in query result batches. + optional bytes /* serialized QueryCursor */ start_cursor = 7; + + // An ending point for the query results. Optional. Query cursors are + // returned in query result batches. + optional bytes /* serialized QueryCursor */ end_cursor = 8; + + // The number of results to skip. Applies before limit, but after all other + // constraints (optional, defaults to 0). + optional int32 offset = 10 [default=0]; + + // The maximum number of results to return. Applies after all other + // constraints. Optional. + optional int32 limit = 11; +} + +// A representation of a kind. +message KindExpression { + // The name of the kind. + required string name = 1; +} + +// A reference to a property relative to the kind expressions. +// exactly. +message PropertyReference { + // The name of the property. + required string name = 2; +} + +// A representation of a property in a projection. +message PropertyExpression { + enum AggregationFunction { + FIRST = 1; + } + // The property to project. + required PropertyReference property = 1; + // The aggregation function to apply to the property. Optional. + // Can only be used when grouping by at least one property. Must + // then be set on all properties in the projection that are not + // being grouped by. + optional AggregationFunction aggregation_function = 2; +} + +// The desired order for a specific property. +message PropertyOrder { + enum Direction { + ASCENDING = 1; + DESCENDING = 2; + } + // The property to order by. + required PropertyReference property = 1; + // The direction to order by. + optional Direction direction = 2 [default=ASCENDING]; +} + +// A holder for any type of filter. Exactly one field should be specified. +message Filter { + // A composite filter. + optional CompositeFilter composite_filter = 1; + // A filter on a property. + optional PropertyFilter property_filter = 2; +} + +// A filter that merges the multiple other filters using the given operation. +message CompositeFilter { + enum Operator { + AND = 1; + } + + // The operator for combining multiple filters. + required Operator operator = 1; + // The list of filters to combine. + // Must contain at least one filter. + repeated Filter filter = 2; +} + +// A filter on a specific property. +message PropertyFilter { + enum Operator { + LESS_THAN = 1; + LESS_THAN_OR_EQUAL = 2; + GREATER_THAN = 3; + GREATER_THAN_OR_EQUAL = 4; + EQUAL = 5; + + HAS_ANCESTOR = 11; + } + + // The property to filter by. + required PropertyReference property = 1; + // The operator to filter by. + required Operator operator = 2; + // The value to compare the property to. + required Value value = 3; +} + +// A GQL query. +message GqlQuery { + required string query_string = 1; + // When false, the query string must not contain a literal. + optional bool allow_literal = 2 [default = false]; + // A named argument must set field GqlQueryArg.name. + // No two named arguments may have the same name. + // For each non-reserved named binding site in the query string, + // there must be a named argument with that name, + // but not necessarily the inverse. + repeated GqlQueryArg name_arg = 3; + // Numbered binding site @1 references the first numbered argument, + // effectively using 1-based indexing, rather than the usual 0. + // A numbered argument must NOT set field GqlQueryArg.name. + // For each binding site numbered i in query_string, + // there must be an ith numbered argument. + // The inverse must also be true. + repeated GqlQueryArg number_arg = 4; +} + +// A binding argument for a GQL query. +// Exactly one of fields value and cursor must be set. +message GqlQueryArg { + // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". + // Must not match regex "__.*__". + // Must not be "". + optional string name = 1; + optional Value value = 2; + optional bytes cursor = 3; +} + +// A batch of results produced by a query. +message QueryResultBatch { + // The possible values for the 'more_results' field. + enum MoreResultsType { + NOT_FINISHED = 1; // There are additional batches to fetch from this query. + MORE_RESULTS_AFTER_LIMIT = 2; // The query is finished, but there are more + // results after the limit. + NO_MORE_RESULTS = 3; // The query has been exhausted. + } + + // The result type for every entity in entityResults. + required EntityResult.ResultType entity_result_type = 1; + // The results for this batch. + repeated EntityResult entity_result = 2; + + // A cursor that points to the position after the last result in the batch. + // May be absent. + optional bytes /* serialized QueryCursor */ end_cursor = 4; + + // The state of the query after the current batch. + required MoreResultsType more_results = 5; + + // The number of results skipped because of Query.offset. + optional int32 skipped_results = 6; +} + +// A set of changes to apply. +// +// No entity in this message may have a reserved property name, +// not even a property in an entity in a value. +// No value in this message may have meaning 18, +// not even a value in an entity in another value. +// +// If entities with duplicate keys are present, an arbitrary choice will +// be made as to which is written. +message Mutation { + // Entities to upsert. + // Each upserted entity's key must have a complete path and + // must not be reserved/read-only. + repeated Entity upsert = 1; + // Entities to update. + // Each updated entity's key must have a complete path and + // must not be reserved/read-only. + repeated Entity update = 2; + // Entities to insert. + // Each inserted entity's key must have a complete path and + // must not be reserved/read-only. + repeated Entity insert = 3; + // Insert entities with a newly allocated ID. + // Each inserted entity's key must omit the final identifier in its path and + // must not be reserved/read-only. + repeated Entity insert_auto_id = 4; + // Keys of entities to delete. + // Each key must have a complete key path and must not be reserved/read-only. + repeated Key delete = 5; + // Ignore a user specified read-only period. Optional. + optional bool force = 6; +} + +// The result of applying a mutation. +message MutationResult { + // Number of index writes. + required int32 index_updates = 1; + // Keys for insertAutoId entities. One per entity from the + // request, in the same order. + repeated Key insert_auto_id_key = 2; +} + +// Options shared by read requests. +message ReadOptions { + enum ReadConsistency { + DEFAULT = 0; + STRONG = 1; + EVENTUAL = 2; + } + + // The read consistency to use. + // Cannot be set when transaction is set. + // Lookup and ancestor queries default to STRONG, global queries default to + // EVENTUAL and cannot be set to STRONG. + optional ReadConsistency read_consistency = 1 [default=DEFAULT]; + + // The transaction to use. Optional. + optional bytes /* serialized Transaction */ transaction = 2; +} + +// The request for Lookup. +message LookupRequest { + + // Options for this lookup request. Optional. + optional ReadOptions read_options = 1; + // Keys of entities to look up from the datastore. + repeated Key key = 3; +} + +// The response for Lookup. +message LookupResponse { + + // The order of results in these fields is undefined and has no relation to + // the order of the keys in the input. + + // Entities found as ResultType.FULL entities. + repeated EntityResult found = 1; + + // Entities not found as ResultType.KEY_ONLY entities. + repeated EntityResult missing = 2; + + // A list of keys that were not looked up due to resource constraints. + repeated Key deferred = 3; +} + + +// The request for RunQuery. +message RunQueryRequest { + + // The options for this query. + optional ReadOptions read_options = 1; + + // Entities are partitioned into subsets, identified by a dataset (usually + // implicitly specified by the project) and namespace ID. Queries are scoped + // to a single partition. + // This partition ID is normalized with the standard default context + // partition ID, but all other partition IDs in RunQueryRequest are + // normalized with this partition ID as the context partition ID. + optional PartitionId partition_id = 2; + + // The query to run. + // Either this field or field gql_query must be set, but not both. + optional Query query = 3; + // The GQL query to run. + // Either this field or field query must be set, but not both. + optional GqlQuery gql_query = 7; +} + +// The response for RunQuery. +message RunQueryResponse { + + // A batch of query results (always present). + optional QueryResultBatch batch = 1; + +} + +// The request for BeginTransaction. +message BeginTransactionRequest { + + enum IsolationLevel { + SNAPSHOT = 0; // Read from a consistent snapshot. Concurrent transactions + // conflict if their mutations conflict. For example: + // Read(A),Write(B) may not conflict with Read(B),Write(A), + // but Read(B),Write(B) does conflict with Read(B),Write(B). + SERIALIZABLE = 1; // Read from a consistent snapshot. Concurrent + // transactions conflict if they cannot be serialized. + // For example Read(A),Write(B) does conflict with + // Read(B),Write(A) but Read(A) may not conflict with + // Write(A). + } + + // The transaction isolation level. + optional IsolationLevel isolation_level = 1 [default=SNAPSHOT]; +} + +// The response for BeginTransaction. +message BeginTransactionResponse { + + // The transaction identifier (always present). + optional bytes /* serialized Transaction */ transaction = 1; +} + +// The request for Rollback. +message RollbackRequest { + + // The transaction identifier, returned by a call to + // beginTransaction. + required bytes /* serialized Transaction */ transaction = 1; +} + +// The response for Rollback. +message RollbackResponse { +// Empty +} + +// The request for Commit. +message CommitRequest { + + enum Mode { + TRANSACTIONAL = 1; + NON_TRANSACTIONAL = 2; + } + + // The transaction identifier, returned by a call to + // beginTransaction. Must be set when mode is TRANSACTIONAL. + optional bytes /* serialized Transaction */ transaction = 1; + // The mutation to perform. Optional. + optional Mutation mutation = 2; + // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. + optional Mode mode = 5 [default=TRANSACTIONAL]; +} + +// The response for Commit. +message CommitResponse { + + // The result of performing the mutation (if any). + optional MutationResult mutation_result = 1; +} + +// The request for AllocateIds. +message AllocateIdsRequest { + + // A list of keys with incomplete key paths to allocate IDs for. + // No key may be reserved/read-only. + repeated Key key = 1; +} + +// The response for AllocateIds. +message AllocateIdsResponse { + + // The keys specified in the request (in the same order), each with + // its key path completed with a newly allocated ID. + repeated Key key = 1; +} + +// Each rpc normalizes the partition IDs of the keys in its input entities, +// and always returns entities with keys with normalized partition IDs. +// (Note that applies to all entities, including entities in values.) +service DatastoreService { + // Look up some entities by key. + rpc Lookup(LookupRequest) returns (LookupResponse) { + }; + // Query for entities. + rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) { + }; + // Begin a new transaction. + rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { + }; + // Commit a transaction, optionally creating, deleting or modifying some + // entities. + rpc Commit(CommitRequest) returns (CommitResponse) { + }; + // Roll back a transaction. + rpc Rollback(RollbackRequest) returns (RollbackResponse) { + }; + // Allocate IDs for incomplete keys (useful for referencing an entity before + // it is inserted). + rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) { + }; +} diff --git a/vendor/google.golang.org/cloud/internal/opts/option.go b/vendor/google.golang.org/cloud/internal/opts/option.go new file mode 100644 index 000000000..844d31044 --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/opts/option.go @@ -0,0 +1,25 @@ +// Package opts holds the DialOpts struct, configurable by +// cloud.ClientOptions to set up transports for cloud packages. +// +// This is a separate page to prevent cycles between the core +// cloud packages. +package opts + +import ( + "net/http" + + "golang.org/x/oauth2" + "google.golang.org/grpc" +) + +type DialOpt struct { + Endpoint string + Scopes []string + UserAgent string + + TokenSource oauth2.TokenSource + + HTTPClient *http.Client + GRPCClient *grpc.ClientConn + GRPCDialOpts []grpc.DialOption +} diff --git a/vendor/google.golang.org/cloud/internal/testutil/context.go b/vendor/google.golang.org/cloud/internal/testutil/context.go new file mode 100644 index 000000000..c10142757 --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/testutil/context.go @@ -0,0 +1,71 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package testutil contains helper functions for writing tests. +package testutil + +import ( + "io/ioutil" + "log" + "os" + + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "google.golang.org/cloud" +) + +const ( + envProjID = "GCLOUD_TESTS_GOLANG_PROJECT_ID" + envPrivateKey = "GCLOUD_TESTS_GOLANG_KEY" +) + +// ProjID returns the project ID to use in integration tests, or the empty +// string if none is configured. +func ProjID() string { + projID := os.Getenv(envProjID) + if projID == "" { + return "" + } + return projID +} + +// TokenSource returns the OAuth2 token source to use in integration tests, +// or nil if none is configured. TokenSource will log.Fatal if the token +// source is specified but missing or invalid. +func TokenSource(ctx context.Context, scopes ...string) oauth2.TokenSource { + key := os.Getenv(envPrivateKey) + if key == "" { + return nil + } + jsonKey, err := ioutil.ReadFile(key) + if err != nil { + log.Fatalf("Cannot read the JSON key file, err: %v", err) + } + conf, err := google.JWTConfigFromJSON(jsonKey, scopes...) + if err != nil { + log.Fatalf("google.JWTConfigFromJSON: %v", err) + } + return conf.TokenSource(ctx) +} + +// TODO(djd): Delete this function when it's no longer used. +func Context(scopes ...string) context.Context { + ctx := oauth2.NoContext + ts := TokenSource(ctx, scopes...) + if ts == nil { + return nil + } + return cloud.NewContext(ProjID(), oauth2.NewClient(ctx, ts)) +} diff --git a/vendor/google.golang.org/cloud/internal/transport/cancelreq.go b/vendor/google.golang.org/cloud/internal/transport/cancelreq.go new file mode 100644 index 000000000..ddae71cce --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/transport/cancelreq.go @@ -0,0 +1,29 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build go1.5 + +package transport + +import "net/http" + +// makeReqCancel returns a closure that cancels the given http.Request +// when called. +func makeReqCancel(req *http.Request) func(http.RoundTripper) { + c := make(chan struct{}) + req.Cancel = c + return func(http.RoundTripper) { + close(c) + } +} diff --git a/vendor/google.golang.org/cloud/internal/transport/cancelreq_legacy.go b/vendor/google.golang.org/cloud/internal/transport/cancelreq_legacy.go new file mode 100644 index 000000000..c11a4ddeb --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/transport/cancelreq_legacy.go @@ -0,0 +1,31 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !go1.5 + +package transport + +import "net/http" + +// makeReqCancel returns a closure that cancels the given http.Request +// when called. +func makeReqCancel(req *http.Request) func(http.RoundTripper) { + // Go 1.4 and prior do not have a reliable way of cancelling a request. + // Transport.CancelRequest will only work if the request is already in-flight. + return func(r http.RoundTripper) { + if t, ok := r.(*http.Transport); ok { + t.CancelRequest(req) + } + } +} diff --git a/vendor/google.golang.org/cloud/internal/transport/dial.go b/vendor/google.golang.org/cloud/internal/transport/dial.go new file mode 100644 index 000000000..ae2baf9fd --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/transport/dial.go @@ -0,0 +1,135 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "errors" + "fmt" + "net/http" + + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "google.golang.org/cloud" + "google.golang.org/cloud/internal/opts" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/oauth" +) + +// ErrHTTP is returned when on a non-200 HTTP response. +type ErrHTTP struct { + StatusCode int + Body []byte + err error +} + +func (e *ErrHTTP) Error() string { + if e.err == nil { + return fmt.Sprintf("error during call, http status code: %v %s", e.StatusCode, e.Body) + } + return e.err.Error() +} + +// NewHTTPClient returns an HTTP client for use communicating with a Google cloud +// service, configured with the given ClientOptions. It also returns the endpoint +// for the service as specified in the options. +func NewHTTPClient(ctx context.Context, opt ...cloud.ClientOption) (*http.Client, string, error) { + var o opts.DialOpt + for _, opt := range opt { + opt.Resolve(&o) + } + if o.GRPCClient != nil { + return nil, "", errors.New("unsupported GRPC base transport specified") + } + // TODO(djd): Wrap all http.Clients with appropriate internal version to add + // UserAgent header and prepend correct endpoint. + if o.HTTPClient != nil { + return o.HTTPClient, o.Endpoint, nil + } + if o.TokenSource == nil { + var err error + o.TokenSource, err = google.DefaultTokenSource(ctx, o.Scopes...) + if err != nil { + return nil, "", fmt.Errorf("google.DefaultTokenSource: %v", err) + } + } + return oauth2.NewClient(ctx, o.TokenSource), o.Endpoint, nil +} + +// NewProtoClient returns a ProtoClient for communicating with a Google cloud service, +// configured with the given ClientOptions. +func NewProtoClient(ctx context.Context, opt ...cloud.ClientOption) (*ProtoClient, error) { + var o opts.DialOpt + for _, opt := range opt { + opt.Resolve(&o) + } + if o.GRPCClient != nil { + return nil, errors.New("unsupported GRPC base transport specified") + } + var client *http.Client + switch { + case o.HTTPClient != nil: + if o.TokenSource != nil { + return nil, errors.New("at most one of WithTokenSource or WithBaseHTTP may be provided") + } + client = o.HTTPClient + case o.TokenSource != nil: + client = oauth2.NewClient(ctx, o.TokenSource) + default: + var err error + client, err = google.DefaultClient(ctx, o.Scopes...) + if err != nil { + return nil, err + } + } + + return &ProtoClient{ + client: client, + endpoint: o.Endpoint, + userAgent: o.UserAgent, + }, nil +} + +// DialGRPC returns a GRPC connection for use communicating with a Google cloud +// service, configured with the given ClientOptions. +func DialGRPC(ctx context.Context, opt ...cloud.ClientOption) (*grpc.ClientConn, error) { + var o opts.DialOpt + for _, opt := range opt { + opt.Resolve(&o) + } + if o.HTTPClient != nil { + return nil, errors.New("unsupported HTTP base transport specified") + } + if o.GRPCClient != nil { + return o.GRPCClient, nil + } + if o.TokenSource == nil { + var err error + o.TokenSource, err = google.DefaultTokenSource(ctx, o.Scopes...) + if err != nil { + return nil, fmt.Errorf("google.DefaultTokenSource: %v", err) + } + } + grpcOpts := []grpc.DialOption{ + grpc.WithPerRPCCredentials(oauth.TokenSource{o.TokenSource}), + grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")), + } + grpcOpts = append(grpcOpts, o.GRPCDialOpts...) + if o.UserAgent != "" { + grpcOpts = append(grpcOpts, grpc.WithUserAgent(o.UserAgent)) + } + return grpc.Dial(o.Endpoint, grpcOpts...) +} diff --git a/vendor/google.golang.org/cloud/internal/transport/proto.go b/vendor/google.golang.org/cloud/internal/transport/proto.go new file mode 100644 index 000000000..05b11cde1 --- /dev/null +++ b/vendor/google.golang.org/cloud/internal/transport/proto.go @@ -0,0 +1,80 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "bytes" + "io/ioutil" + "net/http" + + "github.com/golang/protobuf/proto" + "golang.org/x/net/context" +) + +type ProtoClient struct { + client *http.Client + endpoint string + userAgent string +} + +func (c *ProtoClient) Call(ctx context.Context, method string, req, resp proto.Message) error { + payload, err := proto.Marshal(req) + if err != nil { + return err + } + + httpReq, err := http.NewRequest("POST", c.endpoint+method, bytes.NewReader(payload)) + if err != nil { + return err + } + httpReq.Header.Set("Content-Type", "application/x-protobuf") + if ua := c.userAgent; ua != "" { + httpReq.Header.Set("User-Agent", ua) + } + + errc := make(chan error, 1) + cancel := makeReqCancel(httpReq) + + go func() { + r, err := c.client.Do(httpReq) + if err != nil { + errc <- err + return + } + defer r.Body.Close() + + body, err := ioutil.ReadAll(r.Body) + if r.StatusCode != http.StatusOK { + err = &ErrHTTP{ + StatusCode: r.StatusCode, + Body: body, + err: err, + } + } + if err != nil { + errc <- err + return + } + errc <- proto.Unmarshal(body, resp) + }() + + select { + case <-ctx.Done(): + cancel(c.client.Transport) // Cancel the HTTP request. + return ctx.Err() + case err := <-errc: + return err + } +} diff --git a/vendor/gopkg.in/fsnotify.v1/.gitignore b/vendor/gopkg.in/fsnotify.v1/.gitignore new file mode 100644 index 000000000..4cd0cbaf4 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/.gitignore @@ -0,0 +1,6 @@ +# Setup a Global .gitignore for OS and editor generated files: +# https://help.github.com/articles/ignoring-files +# git config --global core.excludesfile ~/.gitignore_global + +.vagrant +*.sublime-project diff --git a/vendor/gopkg.in/fsnotify.v1/.travis.yml b/vendor/gopkg.in/fsnotify.v1/.travis.yml new file mode 100644 index 000000000..70988769c --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: go + +go: + - 1.5.2 + +before_script: + - go get -u github.com/golang/lint/golint + +script: + - go test -v --race ./... + +after_script: + - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" + - test -z "$(golint ./... | tee /dev/stderr)" + - go vet ./... + +os: + - linux + - osx + +notifications: + email: false diff --git a/vendor/gopkg.in/fsnotify.v1/AUTHORS b/vendor/gopkg.in/fsnotify.v1/AUTHORS new file mode 100644 index 000000000..2b9d1fdd6 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/AUTHORS @@ -0,0 +1,40 @@ +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# You can update this list using the following command: +# +# $ git shortlog -se | awk '{print $2 " " $3 " " $4}' + +# Please keep the list sorted. + +Adrien Bustany +Caleb Spare +Case Nelson +Chris Howey +Christoffer Buchholz +Daniel Wagner-Hall +Dave Cheney +Evan Phoenix +Francisco Souza +Hari haran +John C Barstow +Kelvin Fo +Ken-ichirou MATSUZAWA +Matt Layher +Nathan Youngman +Paul Hammond +Pawel Knap +Pieter Droogendijk +Pursuit92 +Riku Voipio +Rob Figueiredo +Soge Zhang +Tilak Sharma +Travis Cline +Tudor Golubenco +Yukang +bronze1man +debrando +henrikedwards +é“å“¥ diff --git a/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md b/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md new file mode 100644 index 000000000..d37247e0b --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md @@ -0,0 +1,283 @@ +# Changelog + +## v1.2.9 / 2016-01-13 + +kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/go-fsnotify/fsnotify/pull/111) (thanks @bep) + +## v1.2.8 / 2015-12-17 + +* kqueue: fix race condition in Close [#105](https://github.com/go-fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test) +* inotify: fix race in test +* enable race detection for continuous integration (Linux, Mac, Windows) + +## v1.2.5 / 2015-10-17 + +* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/go-fsnotify/fsnotify/pull/100) (thanks @suihkulokki) +* inotify: fix path leaks [#73](https://github.com/go-fsnotify/fsnotify/pull/73) (thanks @chamaken) +* kqueue: watch for rename events on subdirectories [#83](https://github.com/go-fsnotify/fsnotify/pull/83) (thanks @guotie) +* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/go-fsnotify/fsnotify/pull/101) (thanks @illicitonion) + +## v1.2.1 / 2015-10-14 + +* kqueue: don't watch named pipes [#98](https://github.com/go-fsnotify/fsnotify/pull/98) (thanks @evanphx) + +## v1.2.0 / 2015-02-08 + +* inotify: use epoll to wake up readEvents [#66](https://github.com/go-fsnotify/fsnotify/pull/66) (thanks @PieterD) +* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/go-fsnotify/fsnotify/pull/63) (thanks @PieterD) +* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/go-fsnotify/fsnotify/issues/59) + +## v1.1.1 / 2015-02-05 + +* inotify: Retry read on EINTR [#61](https://github.com/go-fsnotify/fsnotify/issues/61) (thanks @PieterD) + +## v1.1.0 / 2014-12-12 + +* kqueue: rework internals [#43](https://github.com/go-fsnotify/fsnotify/pull/43) + * add low-level functions + * only need to store flags on directories + * less mutexes [#13](https://github.com/go-fsnotify/fsnotify/issues/13) + * done can be an unbuffered channel + * remove calls to os.NewSyscallError +* More efficient string concatenation for Event.String() [#52](https://github.com/go-fsnotify/fsnotify/pull/52) (thanks @mdlayher) +* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/go-fsnotify/fsnotify/issues/48) +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/go-fsnotify/fsnotify/issues/51) + +## v1.0.4 / 2014-09-07 + +* kqueue: add dragonfly to the build tags. +* Rename source code files, rearrange code so exported APIs are at the top. +* Add done channel to example code. [#37](https://github.com/go-fsnotify/fsnotify/pull/37) (thanks @chenyukang) + +## v1.0.3 / 2014-08-19 + +* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/go-fsnotify/fsnotify/issues/36) + +## v1.0.2 / 2014-08-17 + +* [Fix] Missing create events on OS X. [#14](https://github.com/go-fsnotify/fsnotify/issues/14) (thanks @zhsso) +* [Fix] Make ./path and path equivalent. (thanks @zhsso) + +## v1.0.0 / 2014-08-15 + +* [API] Remove AddWatch on Windows, use Add. +* Improve documentation for exported identifiers. [#30](https://github.com/go-fsnotify/fsnotify/issues/30) +* Minor updates based on feedback from golint. + +## dev / 2014-07-09 + +* Moved to [github.com/go-fsnotify/fsnotify](https://github.com/go-fsnotify/fsnotify). +* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno) + +## dev / 2014-07-04 + +* kqueue: fix incorrect mutex used in Close() +* Update example to demonstrate usage of Op. + +## dev / 2014-06-28 + +* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/go-fsnotify/fsnotify/issues/4) +* Fix for String() method on Event (thanks Alex Brainman) +* Don't build on Plan 9 or Solaris (thanks @4ad) + +## dev / 2014-06-21 + +* Events channel of type Event rather than *Event. +* [internal] use syscall constants directly for inotify and kqueue. +* [internal] kqueue: rename events to kevents and fileEvent to event. + +## dev / 2014-06-19 + +* Go 1.3+ required on Windows (uses syscall.ERROR_MORE_DATA internally). +* [internal] remove cookie from Event struct (unused). +* [internal] Event struct has the same definition across every OS. +* [internal] remove internal watch and removeWatch methods. + +## dev / 2014-06-12 + +* [API] Renamed Watch() to Add() and RemoveWatch() to Remove(). +* [API] Pluralized channel names: Events and Errors. +* [API] Renamed FileEvent struct to Event. +* [API] Op constants replace methods like IsCreate(). + +## dev / 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## dev / 2014-05-23 + +* [API] Remove current implementation of WatchFlags. + * current implementation doesn't take advantage of OS for efficiency + * provides little benefit over filtering events as they are received, but has extra bookkeeping and mutexes + * no tests for the current implementation + * not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195) + +## v0.9.3 / 2014-12-31 + +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/go-fsnotify/fsnotify/issues/51) + +## v0.9.2 / 2014-08-17 + +* [Backport] Fix missing create events on OS X. [#14](https://github.com/go-fsnotify/fsnotify/issues/14) (thanks @zhsso) + +## v0.9.1 / 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## v0.9.0 / 2014-01-17 + +* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany) +* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare) +* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library. + +## v0.8.12 / 2013-11-13 + +* [API] Remove FD_SET and friends from Linux adapter + +## v0.8.11 / 2013-11-02 + +* [Doc] Add Changelog [#72][] (thanks @nathany) +* [Doc] Spotlight and double modify events on OS X [#62][] (reported by @paulhammond) + +## v0.8.10 / 2013-10-19 + +* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott) +* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer) +* [Doc] specify OS-specific limits in README (thanks @debrando) + +## v0.8.9 / 2013-09-08 + +* [Doc] Contributing (thanks @nathany) +* [Doc] update package path in example code [#63][] (thanks @paulhammond) +* [Doc] GoCI badge in README (Linux only) [#60][] +* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany) + +## v0.8.8 / 2013-06-17 + +* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie) + +## v0.8.7 / 2013-06-03 + +* [API] Make syscall flags internal +* [Fix] inotify: ignore event changes +* [Fix] race in symlink test [#45][] (reported by @srid) +* [Fix] tests on Windows +* lower case error messages + +## v0.8.6 / 2013-05-23 + +* kqueue: Use EVT_ONLY flag on Darwin +* [Doc] Update README with full example + +## v0.8.5 / 2013-05-09 + +* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg) + +## v0.8.4 / 2013-04-07 + +* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz) + +## v0.8.3 / 2013-03-13 + +* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin) +* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin) + +## v0.8.2 / 2013-02-07 + +* [Doc] add Authors +* [Fix] fix data races for map access [#29][] (thanks @fsouza) + +## v0.8.1 / 2013-01-09 + +* [Fix] Windows path separators +* [Doc] BSD License + +## v0.8.0 / 2012-11-09 + +* kqueue: directory watching improvements (thanks @vmirage) +* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto) +* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr) + +## v0.7.4 / 2012-10-09 + +* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji) +* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig) +* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig) +* [Fix] kqueue: modify after recreation of file + +## v0.7.3 / 2012-09-27 + +* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage) +* [Fix] kqueue: no longer get duplicate CREATE events + +## v0.7.2 / 2012-09-01 + +* kqueue: events for created directories + +## v0.7.1 / 2012-07-14 + +* [Fix] for renaming files + +## v0.7.0 / 2012-07-02 + +* [Feature] FSNotify flags +* [Fix] inotify: Added file name back to event path + +## v0.6.0 / 2012-06-06 + +* kqueue: watch files after directory created (thanks @tmc) + +## v0.5.1 / 2012-05-22 + +* [Fix] inotify: remove all watches before Close() + +## v0.5.0 / 2012-05-03 + +* [API] kqueue: return errors during watch instead of sending over channel +* kqueue: match symlink behavior on Linux +* inotify: add `DELETE_SELF` (requested by @taralx) +* [Fix] kqueue: handle EINTR (reported by @robfig) +* [Doc] Godoc example [#1][] (thanks @davecheney) + +## v0.4.0 / 2012-03-30 + +* Go 1 released: build with go tool +* [Feature] Windows support using winfsnotify +* Windows does not have attribute change notifications +* Roll attribute notifications into IsModify + +## v0.3.0 / 2012-02-19 + +* kqueue: add files when watch directory + +## v0.2.0 / 2011-12-30 + +* update to latest Go weekly code + +## v0.1.0 / 2011-10-19 + +* kqueue: add watch on file creation to match inotify +* kqueue: create file event +* inotify: ignore `IN_IGNORED` events +* event String() +* linux: common FileEvent functions +* initial commit + +[#79]: https://github.com/howeyc/fsnotify/pull/79 +[#77]: https://github.com/howeyc/fsnotify/pull/77 +[#72]: https://github.com/howeyc/fsnotify/issues/72 +[#71]: https://github.com/howeyc/fsnotify/issues/71 +[#70]: https://github.com/howeyc/fsnotify/issues/70 +[#63]: https://github.com/howeyc/fsnotify/issues/63 +[#62]: https://github.com/howeyc/fsnotify/issues/62 +[#60]: https://github.com/howeyc/fsnotify/issues/60 +[#59]: https://github.com/howeyc/fsnotify/issues/59 +[#49]: https://github.com/howeyc/fsnotify/issues/49 +[#45]: https://github.com/howeyc/fsnotify/issues/45 +[#40]: https://github.com/howeyc/fsnotify/issues/40 +[#36]: https://github.com/howeyc/fsnotify/issues/36 +[#33]: https://github.com/howeyc/fsnotify/issues/33 +[#29]: https://github.com/howeyc/fsnotify/issues/29 +[#25]: https://github.com/howeyc/fsnotify/issues/25 +[#24]: https://github.com/howeyc/fsnotify/issues/24 +[#21]: https://github.com/howeyc/fsnotify/issues/21 diff --git a/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md b/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md new file mode 100644 index 000000000..0f377f341 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md @@ -0,0 +1,77 @@ +# Contributing + +## Issues + +* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/go-fsnotify/fsnotify/issues). +* Please indicate the platform you are using fsnotify on. +* A code example to reproduce the problem is appreciated. + +## Pull Requests + +### Contributor License Agreement + +fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/go-fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/go-fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). + +Please indicate that you have signed the CLA in your pull request. + +### How fsnotify is Developed + +* Development is done on feature branches. +* Tests are run on BSD, Linux, OS X and Windows. +* Pull requests are reviewed and [applied to master][am] using [hub][]. + * Maintainers may modify or squash commits rather than asking contributors to. +* To issue a new release, the maintainers will: + * Update the CHANGELOG + * Tag a version, which will become available through gopkg.in. + +### How to Fork + +For smooth sailing, always use the original import path. Installing with `go get` makes this easy. + +1. Install from GitHub (`go get -u github.com/go-fsnotify/fsnotify`) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Ensure everything works and the tests pass (see below) +4. Commit your changes (`git commit -am 'Add some feature'`) + +Contribute upstream: + +1. Fork fsnotify on GitHub +2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) +3. Push to the branch (`git push fork my-new-feature`) +4. Create a new Pull Request on GitHub + +This workflow is [thoroughly explained by Katrina Owen](https://blog.splice.com/contributing-open-source-git-repositories-go/). + +### Testing + +fsnotify uses build tags to compile different code on Linux, BSD, OS X, and Windows. + +Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. + +To aid in cross-platform testing there is a Vagrantfile for Linux and BSD. + +* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) +* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder. +* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password) +* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd go-fsnotify/fsnotify; go test'`. +* When you're done, you will want to halt or destroy the Vagrant boxes. + +Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory. + +Right now there is no equivalent solution for Windows and OS X, but there are Windows VMs [freely available from Microsoft](http://www.modern.ie/en-us/virtualization-tools#downloads). + +### Maintainers + +Help maintaining fsnotify is welcome. To be a maintainer: + +* Submit a pull request and sign the CLA as above. +* You must be able to run the test suite on Mac, Windows, Linux and BSD. + +To keep master clean, the fsnotify project uses the "apply mail" workflow outlined in Nathaniel Talbott's post ["Merge pull request" Considered Harmful][am]. This requires installing [hub][]. + +All code changes should be internal pull requests. + +Releases are tagged using [Semantic Versioning](http://semver.org/). + +[hub]: https://github.com/github/hub +[am]: http://blog.spreedly.com/2014/06/24/merge-pull-request-considered-harmful/#.VGa5yZPF_Zs diff --git a/vendor/gopkg.in/fsnotify.v1/LICENSE b/vendor/gopkg.in/fsnotify.v1/LICENSE new file mode 100644 index 000000000..f21e54080 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2012 fsnotify Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/gopkg.in/fsnotify.v1/README.md b/vendor/gopkg.in/fsnotify.v1/README.md new file mode 100644 index 000000000..f2b432e96 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/README.md @@ -0,0 +1,64 @@ +# File system notifications for Go + +[![GoDoc](https://godoc.org/gopkg.in/fsnotify.v1?status.svg)](https://godoc.org/gopkg.in/fsnotify.v1) [![Coverage](http://gocover.io/_badge/github.com/go-fsnotify/fsnotify)](http://gocover.io/github.com/go-fsnotify/fsnotify) + +Go 1.3+ required. + +Cross platform: Windows, Linux, BSD and OS X. + +|Adapter |OS |Status | +|----------|----------|----------| +|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/go-fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/go-fsnotify/fsnotify)| +|kqueue |BSD, OS X, iOS\*|Supported [![Build Status](https://travis-ci.org/go-fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/go-fsnotify/fsnotify)| +|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)| +|FSEvents |OS X |[Planned](https://github.com/go-fsnotify/fsnotify/issues/11)| +|FEN |Solaris 11 |[Planned](https://github.com/go-fsnotify/fsnotify/issues/12)| +|fanotify |Linux 2.6.37+ | | +|USN Journals |Windows |[Maybe](https://github.com/go-fsnotify/fsnotify/issues/53)| +|Polling |*All* |[Maybe](https://github.com/go-fsnotify/fsnotify/issues/9)| + +\* Android and iOS are untested. + +Please see [the documentation](https://godoc.org/gopkg.in/fsnotify.v1) for usage. Consult the [Wiki](https://github.com/go-fsnotify/fsnotify/wiki) for the FAQ and further information. + +## API stability + +Two major versions of fsnotify exist. + +**[fsnotify.v0](https://gopkg.in/fsnotify.v0)** is API-compatible with [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify). Bugfixes *may* be backported, but I recommend upgrading to v1. + +```go +import "gopkg.in/fsnotify.v0" +``` + +\* Refer to the package as fsnotify (without the .v0 suffix). + +**[fsnotify.v1](https://gopkg.in/fsnotify.v1)** provides [a new API](https://godoc.org/gopkg.in/fsnotify.v1) based on [this design document](http://goo.gl/MrYxyA). You can import v1 with: + +```go +import "gopkg.in/fsnotify.v1" +``` + +Further API changes are [planned](https://github.com/go-fsnotify/fsnotify/milestones), but a new major revision will be tagged, so you can depend on the v1 API. + +**Master** may have unreleased changes. Use it to test the very latest code or when [contributing][], but don't expect it to remain API-compatible: + +```go +import "github.com/go-fsnotify/fsnotify" +``` + +## Contributing + +Please refer to [CONTRIBUTING][] before opening an issue or pull request. + +## Example + +See [example_test.go](https://github.com/go-fsnotify/fsnotify/blob/master/example_test.go). + +[contributing]: https://github.com/go-fsnotify/fsnotify/blob/master/CONTRIBUTING.md + +## Related Projects + +* [notify](https://github.com/rjeczalik/notify) +* [fsevents](https://github.com/go-fsnotify/fsevents) + diff --git a/vendor/gopkg.in/fsnotify.v1/fsnotify.go b/vendor/gopkg.in/fsnotify.v1/fsnotify.go new file mode 100644 index 000000000..c899ee008 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/fsnotify.go @@ -0,0 +1,62 @@ +// Copyright 2012 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. + +// +build !plan9,!solaris + +// Package fsnotify provides a platform-independent interface for file system notifications. +package fsnotify + +import ( + "bytes" + "fmt" +) + +// Event represents a single file system notification. +type Event struct { + Name string // Relative path to the file or directory. + Op Op // File operation that triggered the event. +} + +// Op describes a set of file operations. +type Op uint32 + +// These are the generalized file operations that can trigger a notification. +const ( + Create Op = 1 << iota + Write + Remove + Rename + Chmod +) + +// String returns a string representation of the event in the form +// "file: REMOVE|WRITE|..." +func (e Event) String() string { + // Use a buffer for efficient string concatenation + var buffer bytes.Buffer + + if e.Op&Create == Create { + buffer.WriteString("|CREATE") + } + if e.Op&Remove == Remove { + buffer.WriteString("|REMOVE") + } + if e.Op&Write == Write { + buffer.WriteString("|WRITE") + } + if e.Op&Rename == Rename { + buffer.WriteString("|RENAME") + } + if e.Op&Chmod == Chmod { + buffer.WriteString("|CHMOD") + } + + // If buffer remains empty, return no event names + if buffer.Len() == 0 { + return fmt.Sprintf("%q: ", e.Name) + } + + // Return a list of event names, with leading pipe character stripped + return fmt.Sprintf("%q: %s", e.Name, buffer.String()[1:]) +} diff --git a/vendor/gopkg.in/fsnotify.v1/inotify.go b/vendor/gopkg.in/fsnotify.v1/inotify.go new file mode 100644 index 000000000..06f4bba88 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/inotify.go @@ -0,0 +1,324 @@ +// Copyright 2010 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. + +// +build linux + +package fsnotify + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "sync" + "syscall" + "unsafe" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + mu sync.Mutex // Map access + cv *sync.Cond // sync removing on rm_watch with IN_IGNORE + fd int + poller *fdPoller + watches map[string]*watch // Map of inotify watches (key: path) + paths map[int]string // Map of watched paths (key: watch descriptor) + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneResp chan struct{} // Channel to respond to Close +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + // Create inotify fd + fd, errno := syscall.InotifyInit() + if fd == -1 { + return nil, errno + } + // Create epoll + poller, err := newFdPoller(fd) + if err != nil { + syscall.Close(fd) + return nil, err + } + w := &Watcher{ + fd: fd, + poller: poller, + watches: make(map[string]*watch), + paths: make(map[int]string), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + doneResp: make(chan struct{}), + } + w.cv = sync.NewCond(&w.mu) + + go w.readEvents() + return w, nil +} + +func (w *Watcher) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed() { + return nil + } + + // Send 'close' signal to goroutine, and set the Watcher to closed. + close(w.done) + + // Wake up goroutine + w.poller.wake() + + // Wait for goroutine to close + <-w.doneResp + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + name = filepath.Clean(name) + if w.isClosed() { + return errors.New("inotify instance already closed") + } + + const agnosticEvents = syscall.IN_MOVED_TO | syscall.IN_MOVED_FROM | + syscall.IN_CREATE | syscall.IN_ATTRIB | syscall.IN_MODIFY | + syscall.IN_MOVE_SELF | syscall.IN_DELETE | syscall.IN_DELETE_SELF + + var flags uint32 = agnosticEvents + + w.mu.Lock() + watchEntry, found := w.watches[name] + w.mu.Unlock() + if found { + watchEntry.flags |= flags + flags |= syscall.IN_MASK_ADD + } + wd, errno := syscall.InotifyAddWatch(w.fd, name, flags) + if wd == -1 { + return errno + } + + w.mu.Lock() + w.watches[name] = &watch{wd: uint32(wd), flags: flags} + w.paths[wd] = name + w.mu.Unlock() + + return nil +} + +// Remove stops watching the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + + // Fetch the watch. + w.mu.Lock() + defer w.mu.Unlock() + watch, ok := w.watches[name] + + // Remove it from inotify. + if !ok { + return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) + } + // inotify_rm_watch will return EINVAL if the file has been deleted; + // the inotify will already have been removed. + // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously + // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE + // so that EINVAL means that the wd is being rm_watch()ed or its file removed + // by another thread and we have not received IN_IGNORE event. + success, errno := syscall.InotifyRmWatch(w.fd, watch.wd) + if success == -1 { + // TODO: Perhaps it's not helpful to return an error here in every case. + // the only two possible errors are: + // EBADF, which happens when w.fd is not a valid file descriptor of any kind. + // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. + // Watch descriptors are invalidated when they are removed explicitly or implicitly; + // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. + return errno + } + + // wait until ignoreLinux() deleting maps + exists := true + for exists { + w.cv.Wait() + _, exists = w.watches[name] + } + + return nil +} + +type watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Events channel +func (w *Watcher) readEvents() { + var ( + buf [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events + n int // Number of bytes read with read() + errno error // Syscall errno + ok bool // For poller.wait + ) + + defer close(w.doneResp) + defer close(w.Errors) + defer close(w.Events) + defer syscall.Close(w.fd) + defer w.poller.close() + + for { + // See if we have been closed. + if w.isClosed() { + return + } + + ok, errno = w.poller.wait() + if errno != nil { + select { + case w.Errors <- errno: + case <-w.done: + return + } + continue + } + + if !ok { + continue + } + + n, errno = syscall.Read(w.fd, buf[:]) + // If a signal interrupted execution, see if we've been asked to close, and try again. + // http://man7.org/linux/man-pages/man7/signal.7.html : + // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" + if errno == syscall.EINTR { + continue + } + + // syscall.Read might have been woken up by Close. If so, we're done. + if w.isClosed() { + return + } + + if n < syscall.SizeofInotifyEvent { + var err error + if n == 0 { + // If EOF is received. This should really never happen. + err = io.EOF + } else if n < 0 { + // If an error occured while reading. + err = errno + } else { + // Read was too short. + err = errors.New("notify: short read in readEvents()") + } + select { + case w.Errors <- err: + case <-w.done: + return + } + continue + } + + var offset uint32 + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + for offset <= uint32(n-syscall.SizeofInotifyEvent) { + // Point "raw" to the event in the buffer + raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset])) + + mask := uint32(raw.Mask) + nameLen := uint32(raw.Len) + // If the event happened to the watched directory or the watched file, the kernel + // doesn't append the filename to the event, but we would like to always fill the + // the "Name" field with a valid filename. We retrieve the path of the watch from + // the "paths" map. + w.mu.Lock() + name := w.paths[int(raw.Wd)] + w.mu.Unlock() + if nameLen > 0 { + // Point "bytes" at the first byte of the filename + bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent])) + // The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + event := newEvent(name, mask) + + // Send the events that are not ignored on the events channel + if !event.ignoreLinux(w, raw.Wd, mask) { + select { + case w.Events <- event: + case <-w.done: + return + } + } + + // Move to the next event in the buffer + offset += syscall.SizeofInotifyEvent + nameLen + } + } +} + +// Certain types of events can be "ignored" and not sent over the Events +// channel. Such as events marked ignore by the kernel, or MODIFY events +// against files that do not exist. +func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool { + // Ignore anything the inotify API says to ignore + if mask&syscall.IN_IGNORED == syscall.IN_IGNORED { + w.mu.Lock() + defer w.mu.Unlock() + name := w.paths[int(wd)] + delete(w.paths, int(wd)) + delete(w.watches, name) + w.cv.Broadcast() + return true + } + + // If the event is not a DELETE or RENAME, the file must exist. + // Otherwise the event is ignored. + // *Note*: this was put in place because it was seen that a MODIFY + // event was sent after the DELETE. This ignores that MODIFY and + // assumes a DELETE will come or has come if the file doesn't exist. + if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { + _, statErr := os.Lstat(e.Name) + return os.IsNotExist(statErr) + } + return false +} + +// newEvent returns an platform-independent Event based on an inotify mask. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&syscall.IN_CREATE == syscall.IN_CREATE || mask&syscall.IN_MOVED_TO == syscall.IN_MOVED_TO { + e.Op |= Create + } + if mask&syscall.IN_DELETE_SELF == syscall.IN_DELETE_SELF || mask&syscall.IN_DELETE == syscall.IN_DELETE { + e.Op |= Remove + } + if mask&syscall.IN_MODIFY == syscall.IN_MODIFY { + e.Op |= Write + } + if mask&syscall.IN_MOVE_SELF == syscall.IN_MOVE_SELF || mask&syscall.IN_MOVED_FROM == syscall.IN_MOVED_FROM { + e.Op |= Rename + } + if mask&syscall.IN_ATTRIB == syscall.IN_ATTRIB { + e.Op |= Chmod + } + return e +} diff --git a/vendor/gopkg.in/fsnotify.v1/inotify_poller.go b/vendor/gopkg.in/fsnotify.v1/inotify_poller.go new file mode 100644 index 000000000..23a5ca146 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/inotify_poller.go @@ -0,0 +1,186 @@ +// Copyright 2015 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. + +// +build linux + +package fsnotify + +import ( + "errors" + "syscall" +) + +type fdPoller struct { + fd int // File descriptor (as returned by the inotify_init() syscall) + epfd int // Epoll file descriptor + pipe [2]int // Pipe for waking up +} + +func emptyPoller(fd int) *fdPoller { + poller := new(fdPoller) + poller.fd = fd + poller.epfd = -1 + poller.pipe[0] = -1 + poller.pipe[1] = -1 + return poller +} + +// Create a new inotify poller. +// This creates an inotify handler, and an epoll handler. +func newFdPoller(fd int) (*fdPoller, error) { + var errno error + poller := emptyPoller(fd) + defer func() { + if errno != nil { + poller.close() + } + }() + poller.fd = fd + + // Create epoll fd + poller.epfd, errno = syscall.EpollCreate1(0) + if poller.epfd == -1 { + return nil, errno + } + // Create pipe; pipe[0] is the read end, pipe[1] the write end. + errno = syscall.Pipe2(poller.pipe[:], syscall.O_NONBLOCK) + if errno != nil { + return nil, errno + } + + // Register inotify fd with epoll + event := syscall.EpollEvent{ + Fd: int32(poller.fd), + Events: syscall.EPOLLIN, + } + errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.fd, &event) + if errno != nil { + return nil, errno + } + + // Register pipe fd with epoll + event = syscall.EpollEvent{ + Fd: int32(poller.pipe[0]), + Events: syscall.EPOLLIN, + } + errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.pipe[0], &event) + if errno != nil { + return nil, errno + } + + return poller, nil +} + +// Wait using epoll. +// Returns true if something is ready to be read, +// false if there is not. +func (poller *fdPoller) wait() (bool, error) { + // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. + // I don't know whether epoll_wait returns the number of events returned, + // or the total number of events ready. + // I decided to catch both by making the buffer one larger than the maximum. + events := make([]syscall.EpollEvent, 7) + for { + n, errno := syscall.EpollWait(poller.epfd, events, -1) + if n == -1 { + if errno == syscall.EINTR { + continue + } + return false, errno + } + if n == 0 { + // If there are no events, try again. + continue + } + if n > 6 { + // This should never happen. More events were returned than should be possible. + return false, errors.New("epoll_wait returned more events than I know what to do with") + } + ready := events[:n] + epollhup := false + epollerr := false + epollin := false + for _, event := range ready { + if event.Fd == int32(poller.fd) { + if event.Events&syscall.EPOLLHUP != 0 { + // This should not happen, but if it does, treat it as a wakeup. + epollhup = true + } + if event.Events&syscall.EPOLLERR != 0 { + // If an error is waiting on the file descriptor, we should pretend + // something is ready to read, and let syscall.Read pick up the error. + epollerr = true + } + if event.Events&syscall.EPOLLIN != 0 { + // There is data to read. + epollin = true + } + } + if event.Fd == int32(poller.pipe[0]) { + if event.Events&syscall.EPOLLHUP != 0 { + // Write pipe descriptor was closed, by us. This means we're closing down the + // watcher, and we should wake up. + } + if event.Events&syscall.EPOLLERR != 0 { + // If an error is waiting on the pipe file descriptor. + // This is an absolute mystery, and should never ever happen. + return false, errors.New("Error on the pipe descriptor.") + } + if event.Events&syscall.EPOLLIN != 0 { + // This is a regular wakeup, so we have to clear the buffer. + err := poller.clearWake() + if err != nil { + return false, err + } + } + } + } + + if epollhup || epollerr || epollin { + return true, nil + } + return false, nil + } +} + +// Close the write end of the poller. +func (poller *fdPoller) wake() error { + buf := make([]byte, 1) + n, errno := syscall.Write(poller.pipe[1], buf) + if n == -1 { + if errno == syscall.EAGAIN { + // Buffer is full, poller will wake. + return nil + } + return errno + } + return nil +} + +func (poller *fdPoller) clearWake() error { + // You have to be woken up a LOT in order to get to 100! + buf := make([]byte, 100) + n, errno := syscall.Read(poller.pipe[0], buf) + if n == -1 { + if errno == syscall.EAGAIN { + // Buffer is empty, someone else cleared our wake. + return nil + } + return errno + } + return nil +} + +// Close all poller file descriptors, but not the one passed to it. +func (poller *fdPoller) close() { + if poller.pipe[1] != -1 { + syscall.Close(poller.pipe[1]) + } + if poller.pipe[0] != -1 { + syscall.Close(poller.pipe[0]) + } + if poller.epfd != -1 { + syscall.Close(poller.epfd) + } +} diff --git a/vendor/gopkg.in/fsnotify.v1/kqueue.go b/vendor/gopkg.in/fsnotify.v1/kqueue.go new file mode 100644 index 000000000..b8ea30846 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/kqueue.go @@ -0,0 +1,502 @@ +// Copyright 2010 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. + +// +build freebsd openbsd netbsd dragonfly darwin + +package fsnotify + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sync" + "syscall" + "time" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + done chan bool // Channel for sending a "quit message" to the reader goroutine + + kq int // File descriptor (as returned by the kqueue() syscall). + + mu sync.Mutex // Protects access to watcher data + watches map[string]int // Map of watched file descriptors (key: path). + externalWatches map[string]bool // Map of watches added by user of the library. + dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. + paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. + fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). + isClosed bool // Set to true when Close() is first called +} + +type pathInfo struct { + name string + isDir bool +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + kq, err := kqueue() + if err != nil { + return nil, err + } + + w := &Watcher{ + kq: kq, + watches: make(map[string]int), + dirFlags: make(map[string]uint32), + paths: make(map[int]pathInfo), + fileExists: make(map[string]bool), + externalWatches: make(map[string]bool), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan bool), + } + + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } + w.isClosed = true + w.mu.Unlock() + + // copy paths to remove while locked + w.mu.Lock() + var pathsToRemove = make([]string, 0, len(w.watches)) + for name := range w.watches { + pathsToRemove = append(pathsToRemove, name) + } + w.mu.Unlock() + // unlock before calling Remove, which also locks + + var err error + for _, name := range pathsToRemove { + if e := w.Remove(name); e != nil && err == nil { + err = e + } + } + + // Send "quit" message to the reader goroutine: + w.done <- true + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + w.mu.Lock() + w.externalWatches[name] = true + w.mu.Unlock() + _, err := w.addWatch(name, noteAllEvents) + return err +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + w.mu.Lock() + watchfd, ok := w.watches[name] + w.mu.Unlock() + if !ok { + return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) + } + + const registerRemove = syscall.EV_DELETE + if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { + return err + } + + syscall.Close(watchfd) + + w.mu.Lock() + isDir := w.paths[watchfd].isDir + delete(w.watches, name) + delete(w.paths, watchfd) + delete(w.dirFlags, name) + w.mu.Unlock() + + // Find all watched paths that are in this directory that are not external. + if isDir { + var pathsToRemove []string + w.mu.Lock() + for _, path := range w.paths { + wdir, _ := filepath.Split(path.name) + if filepath.Clean(wdir) == name { + if !w.externalWatches[path.name] { + pathsToRemove = append(pathsToRemove, path.name) + } + } + } + w.mu.Unlock() + for _, name := range pathsToRemove { + // Since these are internal, not much sense in propagating error + // to the user, as that will just confuse them with an error about + // a path they did not explicitly watch themselves. + w.Remove(name) + } + } + + return nil +} + +// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) +const noteAllEvents = syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_RENAME + +// keventWaitTime to block on each read from kevent +var keventWaitTime = durationToTimespec(100 * time.Millisecond) + +// addWatch adds name to the watched file set. +// The flags are interpreted as described in kevent(2). +// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. +func (w *Watcher) addWatch(name string, flags uint32) (string, error) { + var isDir bool + // Make ./name and name equivalent + name = filepath.Clean(name) + + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return "", errors.New("kevent instance already closed") + } + watchfd, alreadyWatching := w.watches[name] + // We already have a watch, but we can still override flags. + if alreadyWatching { + isDir = w.paths[watchfd].isDir + } + w.mu.Unlock() + + if !alreadyWatching { + fi, err := os.Lstat(name) + if err != nil { + return "", err + } + + // Don't watch sockets. + if fi.Mode()&os.ModeSocket == os.ModeSocket { + return "", nil + } + + // Don't watch named pipes. + if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { + return "", nil + } + + // Follow Symlinks + // Unfortunately, Linux can add bogus symlinks to watch list without + // issue, and Windows can't do symlinks period (AFAIK). To maintain + // consistency, we will act like everything is fine. There will simply + // be no file events for broken symlinks. + // Hence the returns of nil on errors. + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + name, err = filepath.EvalSymlinks(name) + if err != nil { + return "", nil + } + + w.mu.Lock() + _, alreadyWatching = w.watches[name] + w.mu.Unlock() + + if alreadyWatching { + return name, nil + } + + fi, err = os.Lstat(name) + if err != nil { + return "", nil + } + } + + watchfd, err = syscall.Open(name, openMode, 0700) + if watchfd == -1 { + return "", err + } + + isDir = fi.IsDir() + } + + const registerAdd = syscall.EV_ADD | syscall.EV_CLEAR | syscall.EV_ENABLE + if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { + syscall.Close(watchfd) + return "", err + } + + if !alreadyWatching { + w.mu.Lock() + w.watches[name] = watchfd + w.paths[watchfd] = pathInfo{name: name, isDir: isDir} + w.mu.Unlock() + } + + if isDir { + // Watch the directory if it has not been watched before, + // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + w.mu.Lock() + + watchDir := (flags&syscall.NOTE_WRITE) == syscall.NOTE_WRITE && + (!alreadyWatching || (w.dirFlags[name]&syscall.NOTE_WRITE) != syscall.NOTE_WRITE) + // Store flags so this watch can be updated later + w.dirFlags[name] = flags + w.mu.Unlock() + + if watchDir { + if err := w.watchDirectoryFiles(name); err != nil { + return "", err + } + } + } + return name, nil +} + +// readEvents reads from kqueue and converts the received kevents into +// Event values that it sends down the Events channel. +func (w *Watcher) readEvents() { + eventBuffer := make([]syscall.Kevent_t, 10) + + for { + // See if there is a message on the "done" channel + select { + case <-w.done: + err := syscall.Close(w.kq) + if err != nil { + w.Errors <- err + } + close(w.Events) + close(w.Errors) + return + default: + } + + // Get new events + kevents, err := read(w.kq, eventBuffer, &keventWaitTime) + // EINTR is okay, the syscall was interrupted before timeout expired. + if err != nil && err != syscall.EINTR { + w.Errors <- err + continue + } + + // Flush the events we received to the Events channel + for len(kevents) > 0 { + kevent := &kevents[0] + watchfd := int(kevent.Ident) + mask := uint32(kevent.Fflags) + w.mu.Lock() + path := w.paths[watchfd] + w.mu.Unlock() + event := newEvent(path.name, mask) + + if path.isDir && !(event.Op&Remove == Remove) { + // Double check to make sure the directory exists. This can happen when + // we do a rm -fr on a recursively watched folders and we receive a + // modification event first but the folder has been deleted and later + // receive the delete event + if _, err := os.Lstat(event.Name); os.IsNotExist(err) { + // mark is as delete event + event.Op |= Remove + } + } + + if event.Op&Rename == Rename || event.Op&Remove == Remove { + w.Remove(event.Name) + w.mu.Lock() + delete(w.fileExists, event.Name) + w.mu.Unlock() + } + + if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { + w.sendDirectoryChangeEvents(event.Name) + } else { + // Send the event on the Events channel + w.Events <- event + } + + if event.Op&Remove == Remove { + // Look for a file that may have overwritten this. + // For example, mv f1 f2 will delete f2, then create f2. + if path.isDir { + fileDir := filepath.Clean(event.Name) + w.mu.Lock() + _, found := w.watches[fileDir] + w.mu.Unlock() + if found { + // make sure the directory exists before we watch for changes. When we + // do a recursive watch and perform rm -fr, the parent directory might + // have gone missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the parent directory. + if _, err := os.Lstat(fileDir); err == nil { + w.sendDirectoryChangeEvents(fileDir) + } + } + } else { + filePath := filepath.Clean(event.Name) + if fileInfo, err := os.Lstat(filePath); err == nil { + w.sendFileCreatedEventIfNew(filePath, fileInfo) + } + } + } + + // Move to next event + kevents = kevents[1:] + } + } +} + +// newEvent returns an platform-independent Event based on kqueue Fflags. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&syscall.NOTE_DELETE == syscall.NOTE_DELETE { + e.Op |= Remove + } + if mask&syscall.NOTE_WRITE == syscall.NOTE_WRITE { + e.Op |= Write + } + if mask&syscall.NOTE_RENAME == syscall.NOTE_RENAME { + e.Op |= Rename + } + if mask&syscall.NOTE_ATTRIB == syscall.NOTE_ATTRIB { + e.Op |= Chmod + } + return e +} + +func newCreateEvent(name string) Event { + return Event{Name: name, Op: Create} +} + +// watchDirectoryFiles to mimic inotify when adding a watch on a directory +func (w *Watcher) watchDirectoryFiles(dirPath string) error { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + return err + } + + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + } + + return nil +} + +// sendDirectoryEvents searches the directory for newly created files +// and sends them over the event channel. This functionality is to have +// the BSD version of fsnotify match Linux inotify which provides a +// create event for files created in a watched directory. +func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + w.Errors <- err + } + + // Search for new files + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + err := w.sendFileCreatedEventIfNew(filePath, fileInfo) + + if err != nil { + return + } + } +} + +// sendFileCreatedEvent sends a create event if the file isn't already being tracked. +func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { + w.mu.Lock() + _, doesExist := w.fileExists[filePath] + w.mu.Unlock() + if !doesExist { + // Send create event + w.Events <- newCreateEvent(filePath) + } + + // like watchDirectoryFiles (but without doing another ReadDir) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + + return nil +} + +func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { + if fileInfo.IsDir() { + // mimic Linux providing delete events for subdirectories + // but preserve the flags used if currently watching subdirectory + w.mu.Lock() + flags := w.dirFlags[name] + w.mu.Unlock() + + flags |= syscall.NOTE_DELETE | syscall.NOTE_RENAME + return w.addWatch(name, flags) + } + + // watch file to mimic Linux inotify + return w.addWatch(name, noteAllEvents) +} + +// kqueue creates a new kernel event queue and returns a descriptor. +func kqueue() (kq int, err error) { + kq, err = syscall.Kqueue() + if kq == -1 { + return kq, err + } + return kq, nil +} + +// register events with the queue +func register(kq int, fds []int, flags int, fflags uint32) error { + changes := make([]syscall.Kevent_t, len(fds)) + + for i, fd := range fds { + // SetKevent converts int to the platform-specific types: + syscall.SetKevent(&changes[i], fd, syscall.EVFILT_VNODE, flags) + changes[i].Fflags = fflags + } + + // register the events + success, err := syscall.Kevent(kq, changes, nil, nil) + if success == -1 { + return err + } + return nil +} + +// read retrieves pending events, or waits until an event occurs. +// A timeout of nil blocks indefinitely, while 0 polls the queue. +func read(kq int, events []syscall.Kevent_t, timeout *syscall.Timespec) ([]syscall.Kevent_t, error) { + n, err := syscall.Kevent(kq, nil, events, timeout) + if err != nil { + return nil, err + } + return events[0:n], nil +} + +// durationToTimespec prepares a timeout value +func durationToTimespec(d time.Duration) syscall.Timespec { + return syscall.NsecToTimespec(d.Nanoseconds()) +} diff --git a/vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go b/vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go new file mode 100644 index 000000000..c57ccb427 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go @@ -0,0 +1,11 @@ +// Copyright 2013 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. + +// +build freebsd openbsd netbsd dragonfly + +package fsnotify + +import "syscall" + +const openMode = syscall.O_NONBLOCK | syscall.O_RDONLY diff --git a/vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go b/vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go new file mode 100644 index 000000000..174b2c331 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go @@ -0,0 +1,12 @@ +// Copyright 2013 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. + +// +build darwin + +package fsnotify + +import "syscall" + +// note: this constant is not defined on BSD +const openMode = syscall.O_EVTONLY diff --git a/vendor/gopkg.in/fsnotify.v1/windows.go b/vendor/gopkg.in/fsnotify.v1/windows.go new file mode 100644 index 000000000..811585227 --- /dev/null +++ b/vendor/gopkg.in/fsnotify.v1/windows.go @@ -0,0 +1,561 @@ +// Copyright 2011 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. + +// +build windows + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sync" + "syscall" + "unsafe" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + isClosed bool // Set to true when Close() is first called + mu sync.Mutex // Map access + port syscall.Handle // Handle to completion port + watches watchMap // Map of watches (key: i-number) + input chan *input // Inputs to the reader are sent on this channel + quit chan chan<- error +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) + if e != nil { + return nil, os.NewSyscallError("CreateIoCompletionPort", e) + } + w := &Watcher{ + port: port, + watches: make(watchMap), + input: make(chan *input, 1), + Events: make(chan Event, 50), + Errors: make(chan error), + quit: make(chan chan<- error, 1), + } + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed { + return nil + } + w.isClosed = true + + // Send "quit" message to the reader goroutine + ch := make(chan error) + w.quit <- ch + if err := w.wakeupReader(); err != nil { + return err + } + return <-ch +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + if w.isClosed { + return errors.New("watcher already closed") + } + in := &input{ + op: opAddWatch, + path: filepath.Clean(name), + flags: sys_FS_ALL_EVENTS, + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + in := &input{ + op: opRemoveWatch, + path: filepath.Clean(name), + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +const ( + // Options for AddWatch + sys_FS_ONESHOT = 0x80000000 + sys_FS_ONLYDIR = 0x1000000 + + // Events + sys_FS_ACCESS = 0x1 + sys_FS_ALL_EVENTS = 0xfff + sys_FS_ATTRIB = 0x4 + sys_FS_CLOSE = 0x18 + sys_FS_CREATE = 0x100 + sys_FS_DELETE = 0x200 + sys_FS_DELETE_SELF = 0x400 + sys_FS_MODIFY = 0x2 + sys_FS_MOVE = 0xc0 + sys_FS_MOVED_FROM = 0x40 + sys_FS_MOVED_TO = 0x80 + sys_FS_MOVE_SELF = 0x800 + + // Special events + sys_FS_IGNORED = 0x8000 + sys_FS_Q_OVERFLOW = 0x4000 +) + +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&sys_FS_CREATE == sys_FS_CREATE || mask&sys_FS_MOVED_TO == sys_FS_MOVED_TO { + e.Op |= Create + } + if mask&sys_FS_DELETE == sys_FS_DELETE || mask&sys_FS_DELETE_SELF == sys_FS_DELETE_SELF { + e.Op |= Remove + } + if mask&sys_FS_MODIFY == sys_FS_MODIFY { + e.Op |= Write + } + if mask&sys_FS_MOVE == sys_FS_MOVE || mask&sys_FS_MOVE_SELF == sys_FS_MOVE_SELF || mask&sys_FS_MOVED_FROM == sys_FS_MOVED_FROM { + e.Op |= Rename + } + if mask&sys_FS_ATTRIB == sys_FS_ATTRIB { + e.Op |= Chmod + } + return e +} + +const ( + opAddWatch = iota + opRemoveWatch +) + +const ( + provisional uint64 = 1 << (32 + iota) +) + +type input struct { + op int + path string + flags uint32 + reply chan error +} + +type inode struct { + handle syscall.Handle + volume uint32 + index uint64 +} + +type watch struct { + ov syscall.Overlapped + ino *inode // i-number + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf [4096]byte +} + +type indexMap map[uint64]*watch +type watchMap map[uint32]indexMap + +func (w *Watcher) wakeupReader() error { + e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) + if e != nil { + return os.NewSyscallError("PostQueuedCompletionStatus", e) + } + return nil +} + +func getDir(pathname string) (dir string, err error) { + attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) + if e != nil { + return "", os.NewSyscallError("GetFileAttributes", e) + } + if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { + dir = pathname + } else { + dir, _ = filepath.Split(pathname) + dir = filepath.Clean(dir) + } + return +} + +func getIno(path string) (ino *inode, err error) { + h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), + syscall.FILE_LIST_DIRECTORY, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + nil, syscall.OPEN_EXISTING, + syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) + if e != nil { + return nil, os.NewSyscallError("CreateFile", e) + } + var fi syscall.ByHandleFileInformation + if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { + syscall.CloseHandle(h) + return nil, os.NewSyscallError("GetFileInformationByHandle", e) + } + ino = &inode{ + handle: h, + volume: fi.VolumeSerialNumber, + index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), + } + return ino, nil +} + +// Must run within the I/O thread. +func (m watchMap) get(ino *inode) *watch { + if i := m[ino.volume]; i != nil { + return i[ino.index] + } + return nil +} + +// Must run within the I/O thread. +func (m watchMap) set(ino *inode, watch *watch) { + i := m[ino.volume] + if i == nil { + i = make(indexMap) + m[ino.volume] = i + } + i[ino.index] = watch +} + +// Must run within the I/O thread. +func (w *Watcher) addWatch(pathname string, flags uint64) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + if flags&sys_FS_ONLYDIR != 0 && pathname != dir { + return nil + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watchEntry := w.watches.get(ino) + w.mu.Unlock() + if watchEntry == nil { + if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { + syscall.CloseHandle(ino.handle) + return os.NewSyscallError("CreateIoCompletionPort", e) + } + watchEntry = &watch{ + ino: ino, + path: dir, + names: make(map[string]uint64), + } + w.mu.Lock() + w.watches.set(ino, watchEntry) + w.mu.Unlock() + flags |= provisional + } else { + syscall.CloseHandle(ino.handle) + } + if pathname == dir { + watchEntry.mask |= flags + } else { + watchEntry.names[filepath.Base(pathname)] |= flags + } + if err = w.startRead(watchEntry); err != nil { + return err + } + if pathname == dir { + watchEntry.mask &= ^provisional + } else { + watchEntry.names[filepath.Base(pathname)] &= ^provisional + } + return nil +} + +// Must run within the I/O thread. +func (w *Watcher) remWatch(pathname string) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watch := w.watches.get(ino) + w.mu.Unlock() + if watch == nil { + return fmt.Errorf("can't remove non-existent watch for: %s", pathname) + } + if pathname == dir { + w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED) + watch.mask = 0 + } else { + name := filepath.Base(pathname) + w.sendEvent(watch.path+"\\"+name, watch.names[name]&sys_FS_IGNORED) + delete(watch.names, name) + } + return w.startRead(watch) +} + +// Must run within the I/O thread. +func (w *Watcher) deleteWatch(watch *watch) { + for name, mask := range watch.names { + if mask&provisional == 0 { + w.sendEvent(watch.path+"\\"+name, mask&sys_FS_IGNORED) + } + delete(watch.names, name) + } + if watch.mask != 0 { + if watch.mask&provisional == 0 { + w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED) + } + watch.mask = 0 + } +} + +// Must run within the I/O thread. +func (w *Watcher) startRead(watch *watch) error { + if e := syscall.CancelIo(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CancelIo", e) + w.deleteWatch(watch) + } + mask := toWindowsFlags(watch.mask) + for _, m := range watch.names { + mask |= toWindowsFlags(m) + } + if mask == 0 { + if e := syscall.CloseHandle(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CloseHandle", e) + } + w.mu.Lock() + delete(w.watches[watch.ino.volume], watch.ino.index) + w.mu.Unlock() + return nil + } + e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], + uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + if e != nil { + err := os.NewSyscallError("ReadDirectoryChanges", e) + if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { + // Watched directory was probably removed + if w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF) { + if watch.mask&sys_FS_ONESHOT != 0 { + watch.mask = 0 + } + } + err = nil + } + w.deleteWatch(watch) + w.startRead(watch) + return err + } + return nil +} + +// readEvents reads from the I/O completion port, converts the +// received events into Event objects and sends them via the Events channel. +// Entry point to the I/O thread. +func (w *Watcher) readEvents() { + var ( + n, key uint32 + ov *syscall.Overlapped + ) + runtime.LockOSThread() + + for { + e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) + watch := (*watch)(unsafe.Pointer(ov)) + + if watch == nil { + select { + case ch := <-w.quit: + w.mu.Lock() + var indexes []indexMap + for _, index := range w.watches { + indexes = append(indexes, index) + } + w.mu.Unlock() + for _, index := range indexes { + for _, watch := range index { + w.deleteWatch(watch) + w.startRead(watch) + } + } + var err error + if e := syscall.CloseHandle(w.port); e != nil { + err = os.NewSyscallError("CloseHandle", e) + } + close(w.Events) + close(w.Errors) + ch <- err + return + case in := <-w.input: + switch in.op { + case opAddWatch: + in.reply <- w.addWatch(in.path, uint64(in.flags)) + case opRemoveWatch: + in.reply <- w.remWatch(in.path) + } + default: + } + continue + } + + switch e { + case syscall.ERROR_MORE_DATA: + if watch == nil { + w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") + } else { + // The i/o succeeded but the buffer is full. + // In theory we should be building up a full packet. + // In practice we can get away with just carrying on. + n = uint32(unsafe.Sizeof(watch.buf)) + } + case syscall.ERROR_ACCESS_DENIED: + // Watched directory was probably removed + w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF) + w.deleteWatch(watch) + w.startRead(watch) + continue + case syscall.ERROR_OPERATION_ABORTED: + // CancelIo was called on this handle + continue + default: + w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) + continue + case nil: + } + + var offset uint32 + for { + if n == 0 { + w.Events <- newEvent("", sys_FS_Q_OVERFLOW) + w.Errors <- errors.New("short read in readEvents()") + break + } + + // Point "raw" to the event in the buffer + raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) + buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName)) + name := syscall.UTF16ToString(buf[:raw.FileNameLength/2]) + fullname := watch.path + "\\" + name + + var mask uint64 + switch raw.Action { + case syscall.FILE_ACTION_REMOVED: + mask = sys_FS_DELETE_SELF + case syscall.FILE_ACTION_MODIFIED: + mask = sys_FS_MODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + watch.rename = name + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + if watch.names[watch.rename] != 0 { + watch.names[name] |= watch.names[watch.rename] + delete(watch.names, watch.rename) + mask = sys_FS_MOVE_SELF + } + } + + sendNameEvent := func() { + if w.sendEvent(fullname, watch.names[name]&mask) { + if watch.names[name]&sys_FS_ONESHOT != 0 { + delete(watch.names, name) + } + } + } + if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { + sendNameEvent() + } + if raw.Action == syscall.FILE_ACTION_REMOVED { + w.sendEvent(fullname, watch.names[name]&sys_FS_IGNORED) + delete(watch.names, name) + } + if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { + if watch.mask&sys_FS_ONESHOT != 0 { + watch.mask = 0 + } + } + if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { + fullname = watch.path + "\\" + watch.rename + sendNameEvent() + } + + // Move to the next event in the buffer + if raw.NextEntryOffset == 0 { + break + } + offset += raw.NextEntryOffset + + // Error! + if offset >= n { + w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") + break + } + } + + if err := w.startRead(watch); err != nil { + w.Errors <- err + } + } +} + +func (w *Watcher) sendEvent(name string, mask uint64) bool { + if mask == 0 { + return false + } + event := newEvent(name, uint32(mask)) + select { + case ch := <-w.quit: + w.quit <- ch + case w.Events <- event: + } + return true +} + +func toWindowsFlags(mask uint64) uint32 { + var m uint32 + if mask&sys_FS_ACCESS != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS + } + if mask&sys_FS_MODIFY != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE + } + if mask&sys_FS_ATTRIB != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES + } + if mask&(sys_FS_MOVE|sys_FS_CREATE|sys_FS_DELETE) != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME + } + return m +} + +func toFSnotifyFlags(action uint32) uint64 { + switch action { + case syscall.FILE_ACTION_ADDED: + return sys_FS_CREATE + case syscall.FILE_ACTION_REMOVED: + return sys_FS_DELETE + case syscall.FILE_ACTION_MODIFIED: + return sys_FS_MODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + return sys_FS_MOVED_FROM + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + return sys_FS_MOVED_TO + } + return 0 +} diff --git a/vendor/gopkg.in/tomb.v1/LICENSE b/vendor/gopkg.in/tomb.v1/LICENSE new file mode 100644 index 000000000..a4249bb31 --- /dev/null +++ b/vendor/gopkg.in/tomb.v1/LICENSE @@ -0,0 +1,29 @@ +tomb - support for clean goroutine termination in Go. + +Copyright (c) 2010-2011 - Gustavo Niemeyer + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/gopkg.in/tomb.v1/README.md b/vendor/gopkg.in/tomb.v1/README.md new file mode 100644 index 000000000..3ae8788e8 --- /dev/null +++ b/vendor/gopkg.in/tomb.v1/README.md @@ -0,0 +1,4 @@ +Installation and usage +---------------------- + +See [gopkg.in/tomb.v1](https://gopkg.in/tomb.v1) for documentation and usage details. diff --git a/vendor/gopkg.in/tomb.v1/tomb.go b/vendor/gopkg.in/tomb.v1/tomb.go new file mode 100644 index 000000000..9aec56d82 --- /dev/null +++ b/vendor/gopkg.in/tomb.v1/tomb.go @@ -0,0 +1,176 @@ +// Copyright (c) 2011 - Gustavo Niemeyer +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The tomb package offers a conventional API for clean goroutine termination. +// +// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead, +// and the reason for its death. +// +// The zero value of a Tomb assumes that a goroutine is about to be +// created or already alive. Once Kill or Killf is called with an +// argument that informs the reason for death, the goroutine is in +// a dying state and is expected to terminate soon. Right before the +// goroutine function or method returns, Done must be called to inform +// that the goroutine is indeed dead and about to stop running. +// +// A Tomb exposes Dying and Dead channels. These channels are closed +// when the Tomb state changes in the respective way. They enable +// explicit blocking until the state changes, and also to selectively +// unblock select statements accordingly. +// +// When the tomb state changes to dying and there's still logic going +// on within the goroutine, nested functions and methods may choose to +// return ErrDying as their error value, as this error won't alter the +// tomb state if provided to the Kill method. This is a convenient way to +// follow standard Go practices in the context of a dying tomb. +// +// For background and a detailed example, see the following blog post: +// +// http://blog.labix.org/2011/10/09/death-of-goroutines-under-control +// +// For a more complex code snippet demonstrating the use of multiple +// goroutines with a single Tomb, see: +// +// http://play.golang.org/p/Xh7qWsDPZP +// +package tomb + +import ( + "errors" + "fmt" + "sync" +) + +// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead, +// and the reason for its death. +// +// See the package documentation for details. +type Tomb struct { + m sync.Mutex + dying chan struct{} + dead chan struct{} + reason error +} + +var ( + ErrStillAlive = errors.New("tomb: still alive") + ErrDying = errors.New("tomb: dying") +) + +func (t *Tomb) init() { + t.m.Lock() + if t.dead == nil { + t.dead = make(chan struct{}) + t.dying = make(chan struct{}) + t.reason = ErrStillAlive + } + t.m.Unlock() +} + +// Dead returns the channel that can be used to wait +// until t.Done has been called. +func (t *Tomb) Dead() <-chan struct{} { + t.init() + return t.dead +} + +// Dying returns the channel that can be used to wait +// until t.Kill or t.Done has been called. +func (t *Tomb) Dying() <-chan struct{} { + t.init() + return t.dying +} + +// Wait blocks until the goroutine is in a dead state and returns the +// reason for its death. +func (t *Tomb) Wait() error { + t.init() + <-t.dead + t.m.Lock() + reason := t.reason + t.m.Unlock() + return reason +} + +// Done flags the goroutine as dead, and should be called a single time +// right before the goroutine function or method returns. +// If the goroutine was not already in a dying state before Done is +// called, it will be flagged as dying and dead at once with no +// error. +func (t *Tomb) Done() { + t.Kill(nil) + close(t.dead) +} + +// Kill flags the goroutine as dying for the given reason. +// Kill may be called multiple times, but only the first +// non-nil error is recorded as the reason for termination. +// +// If reason is ErrDying, the previous reason isn't replaced +// even if it is nil. It's a runtime error to call Kill with +// ErrDying if t is not in a dying state. +func (t *Tomb) Kill(reason error) { + t.init() + t.m.Lock() + defer t.m.Unlock() + if reason == ErrDying { + if t.reason == ErrStillAlive { + panic("tomb: Kill with ErrDying while still alive") + } + return + } + if t.reason == nil || t.reason == ErrStillAlive { + t.reason = reason + } + // If the receive on t.dying succeeds, then + // it can only be because we have already closed it. + // If it blocks, then we know that it needs to be closed. + select { + case <-t.dying: + default: + close(t.dying) + } +} + +// Killf works like Kill, but builds the reason providing the received +// arguments to fmt.Errorf. The generated error is also returned. +func (t *Tomb) Killf(f string, a ...interface{}) error { + err := fmt.Errorf(f, a...) + t.Kill(err) + return err +} + +// Err returns the reason for the goroutine death provided via Kill +// or Killf, or ErrStillAlive when the goroutine is still alive. +func (t *Tomb) Err() (reason error) { + t.init() + t.m.Lock() + reason = t.reason + t.m.Unlock() + return +} diff --git a/vendor/gopkg.in/xmlpath.v2/LICENSE b/vendor/gopkg.in/xmlpath.v2/LICENSE new file mode 100644 index 000000000..4ccd784ba --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/LICENSE @@ -0,0 +1,187 @@ +Copyright (c) 2013-2014 Canonical Inc. + +This software is licensed under the LGPLv3, included below. + +As a special exception to the GNU Lesser General Public License version 3 +("LGPL3"), the copyright holders of this Library give you permission to +convey to a third party a Combined Work that links statically or dynamically +to this Library without providing any Minimal Corresponding Source or +Minimal Application Code as set out in 4d or providing the installation +information set out in section 4e, provided that you comply with the other +provisions of LGPL3 and provided that you meet, for the Application the +terms and conditions of the license(s) which apply to the Application. + +Except as stated in this special exception, the provisions of LGPL3 will +continue to comply in full to this Library. If you modify this Library, you +may apply this exception to your version of this Library, but you are not +obliged to do so. If you do not wish to do so, delete this exception +statement from your version. This exception does not (and cannot) modify any +license terms which apply to the Application, with which you must still +comply. + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/gopkg.in/xmlpath.v2/README.md b/vendor/gopkg.in/xmlpath.v2/README.md new file mode 100644 index 000000000..4d10f697b --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/README.md @@ -0,0 +1,4 @@ +Installation and usage +---------------------- + +See [gopkg.in/xmlpath.v2](https://gopkg.in/xmlpath.v2) for documentation and usage details. diff --git a/vendor/gopkg.in/xmlpath.v2/cmd/webpath/main.go b/vendor/gopkg.in/xmlpath.v2/cmd/webpath/main.go new file mode 100644 index 000000000..0f66d40cc --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/cmd/webpath/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "flag" + "fmt" + "gopkg.in/xmlpath.v2" + "io" + "net/http" + "os" + "regexp" + "strings" +) + +var all = flag.Bool("all", false, "print all occurrences rather than the first one") +var trim = flag.Bool("trim", false, "trim spaces around results") +var line = flag.Bool("line", false, "reformat each match as a single line") +var quiet = flag.Bool("q", false, "run quietly with no stdout output") + +func main() { + flag.Parse() + if len(flag.Args()) != 2 { + fmt.Fprintf(os.Stderr, "usage: webpath \n") + os.Exit(1) + } + + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } +} + +var whitespace = regexp.MustCompile("[ \t\n]+") + +func run() error { + args := flag.Args() + + path, err := xmlpath.Compile(args[0]) + if err != nil { + return err + } + + loc := args[1] + + var body io.Reader + if strings.HasPrefix(loc, "https:") || strings.HasPrefix(loc, "http:") { + resp, err := http.Get(args[1]) + if err != nil { + return err + } + defer resp.Body.Close() + body = resp.Body + } else { + file, err := os.Open(loc) + if err != nil { + return err + } + defer file.Close() + body = file + } + + n, err := xmlpath.ParseHTML(body) + if err != nil { + return err + } + + iter := path.Iter(n) + ok := false + for iter.Next() { + ok = true + if *quiet { + break + } + s := iter.Node().String() + if *line { + s = strings.TrimSpace(whitespace.ReplaceAllString(s, " ")) + } else if *trim { + s = strings.TrimSpace(s) + } + fmt.Println(s) + if !*all { + break + } + } + if !ok { + os.Exit(1) + } + return nil +} diff --git a/vendor/gopkg.in/xmlpath.v2/doc.go b/vendor/gopkg.in/xmlpath.v2/doc.go new file mode 100644 index 000000000..e81d7370a --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/doc.go @@ -0,0 +1,75 @@ +// Package xmlpath implements a strict subset of the XPath specification for the Go language. +// +// The XPath specification is available at: +// +// http://www.w3.org/TR/xpath +// +// Path expressions supported by this package are in the following format, +// with all components being optional: +// +// /axis-name::node-test[predicate]/axis-name::node-test[predicate] +// +// At the moment, xmlpath is compatible with the XPath specification +// to the following extent: +// +// - All axes are supported ("child", "following-sibling", etc) +// - All abbreviated forms are supported (".", "//", etc) +// - All node types except for namespace are supported +// - Predicates may be [N], [path], [not(path)], [path=literal] or [contains(path, literal)] +// - Predicates may be joined with "or", "and", and parenthesis +// - Richer expressions and namespaces are not supported +// +// For example, assuming the following document: +// +// +// +// +// 0836217462 +// Being a Dog Is a Full-Time Job +// I'd dog paddle the deepest ocean. +// +// +// Charles M Schulz +// 1922-11-26 +// 2000-02-12 +// +// +// Peppermint Patty +// 1966-08-22 +// bold, brash and tomboyish +// +// +// Snoopy +// 1950-10-04 +// extroverted beagle +// +// +// +// +// The following examples are valid path expressions, and the first +// match has the indicated value: +// +// /library/book/isbn => "0836217462" +// library/*/isbn => "0836217462" +// /library/book/../book/./isbn => "0836217462" +// /library/book/character[2]/name => "Snoopy" +// /library/book/character[born='1950-10-04']/name => "Snoopy" +// /library/book//node()[@id='PP']/name => "Peppermint Patty" +// //book[author/@id='CMS']/title => "Being a Dog Is a Full-Time Job", +// /library/book/preceding::comment() => " Great book. " +// //*[contains(born,'1922')]/name => "Charles M Schulz" +// //*[@id='PP' or @id='Snoopy']/born => {"1966-08-22", "1950-10-04"} +// +// To run an expression, compile it, and then apply the compiled path to any +// number of context nodes, from one or more parsed xml documents: +// +// path := xmlpath.MustCompile("/library/book/isbn") +// root, err := xmlpath.Parse(file) +// if err != nil { +// log.Fatal(err) +// } +// if value, ok := path.String(root); ok { +// fmt.Println("Found:", value) +// } +// +package xmlpath diff --git a/vendor/gopkg.in/xmlpath.v2/parser.go b/vendor/gopkg.in/xmlpath.v2/parser.go new file mode 100644 index 000000000..64267aa49 --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/parser.go @@ -0,0 +1,396 @@ +package xmlpath + +import ( + "golang.org/x/net/html" + "encoding/xml" + "io" + "strings" +) + +// Node is an item in an xml tree that was compiled to +// be processed via xml paths. A node may represent: +// +// - An element in the xml document () +// - An attribute of an element in the xml document (href="...") +// - A comment in the xml document () +// - A processing instruction in the xml document () +// - Some text within the xml document +// +type Node struct { + kind nodeKind + name xml.Name + attr string + text []byte + + nodes []Node + pos int + end int + + up *Node + down []*Node +} + +type nodeKind int + +const ( + anyNode nodeKind = iota + startNode + endNode + attrNode + textNode + commentNode + procInstNode +) + +// String returns the string value of node. +// +// The string value of a node is: +// +// - For element nodes, the concatenation of all text nodes within the element. +// - For text nodes, the text itself. +// - For attribute nodes, the attribute value. +// - For comment nodes, the text within the comment delimiters. +// - For processing instruction nodes, the content of the instruction. +// +func (node *Node) String() string { + if node.kind == attrNode { + return node.attr + } + return string(node.Bytes()) +} + +// Bytes returns the string value of node as a byte slice. +// See Node.String for a description of what the string value of a node is. +func (node *Node) Bytes() []byte { + if node.kind == attrNode { + return []byte(node.attr) + } + if node.kind != startNode { + return node.text + } + size := 0 + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + size += len(node.nodes[i].text) + } + } + text := make([]byte, 0, size) + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + text = append(text, node.nodes[i].text...) + } + } + return text +} + +// equals returns whether the string value of node is equal to s, +// without allocating memory. +func (node *Node) equals(s string) bool { + if node.kind == attrNode { + return s == node.attr + } + if node.kind != startNode { + if len(s) != len(node.text) { + return false + } + for i := range s { + if s[i] != node.text[i] { + return false + } + } + return true + } + si := 0 + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + for _, c := range node.nodes[i].text { + if si > len(s) { + return false + } + if s[si] != c { + return false + } + si++ + } + } + } + return si == len(s) +} + +// contains returns whether the string value of node contains s, +// without allocating memory. +func (node *Node) contains(s string) (ok bool) { + if len(s) == 0 { + return true + } + if node.kind == attrNode { + return strings.Contains(node.attr, s) + } + s0 := s[0] + for i := node.pos; i < node.end; i++ { + if node.nodes[i].kind == textNode { + text := node.nodes[i].text + NextTry: + for ci, c := range text { + if c != s0 { + continue + } + si := 1 + for ci++; ci < len(text) && si < len(s); ci++ { + if s[si] != text[ci] { + continue NextTry + } + si++ + } + if si == len(s) { + return true + } + for j := i + 1; j < node.end; j++ { + if node.nodes[j].kind == textNode { + for _, c := range node.nodes[j].text { + if s[si] != c { + continue NextTry + } + si++ + if si == len(s) { + return true + } + } + } + } + } + } + } + return false +} + +// Parse reads an xml document from r, parses it, and returns its root node. +func Parse(r io.Reader) (*Node, error) { + return ParseDecoder(xml.NewDecoder(r)) +} + +// ParseDecoder parses the xml document being decoded by d and returns +// its root node. +func ParseDecoder(d *xml.Decoder) (*Node, error) { + var nodes []Node + var text []byte + + // The root node. + nodes = append(nodes, Node{kind: startNode}) + + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + switch t := t.(type) { + case xml.EndElement: + nodes = append(nodes, Node{ + kind: endNode, + }) + case xml.StartElement: + nodes = append(nodes, Node{ + kind: startNode, + name: t.Name, + }) + for _, attr := range t.Attr { + nodes = append(nodes, Node{ + kind: attrNode, + name: attr.Name, + attr: attr.Value, + }) + } + case xml.CharData: + texti := len(text) + text = append(text, t...) + nodes = append(nodes, Node{ + kind: textNode, + text: text[texti : texti+len(t)], + }) + case xml.Comment: + texti := len(text) + text = append(text, t...) + nodes = append(nodes, Node{ + kind: commentNode, + text: text[texti : texti+len(t)], + }) + case xml.ProcInst: + texti := len(text) + text = append(text, t.Inst...) + nodes = append(nodes, Node{ + kind: procInstNode, + name: xml.Name{Local: t.Target}, + text: text[texti : texti+len(t.Inst)], + }) + } + } + + // Close the root node. + nodes = append(nodes, Node{kind: endNode}) + + stack := make([]*Node, 0, len(nodes)) + downs := make([]*Node, len(nodes)) + downCount := 0 + + for pos := range nodes { + + switch nodes[pos].kind { + + case startNode, attrNode, textNode, commentNode, procInstNode: + node := &nodes[pos] + node.nodes = nodes + node.pos = pos + if len(stack) > 0 { + node.up = stack[len(stack)-1] + } + if node.kind == startNode { + stack = append(stack, node) + } else { + node.end = pos + 1 + } + + case endNode: + node := stack[len(stack)-1] + node.end = pos + stack = stack[:len(stack)-1] + + // Compute downs. Doing that here is what enables the + // use of a slice of a contiguous pre-allocated block. + node.down = downs[downCount:downCount] + for i := node.pos + 1; i < node.end; i++ { + if nodes[i].up == node { + switch nodes[i].kind { + case startNode, textNode, commentNode, procInstNode: + node.down = append(node.down, &nodes[i]) + downCount++ + } + } + } + if len(stack) == 0 { + return node, nil + } + } + } + return nil, io.EOF +} + +// ParseHTML reads an HTML document from r, parses it using a proper HTML +// parser, and returns its root node. +// +// The document will be processed as a properly structured HTML document, +// emulating the behavior of a browser when processing it. This includes +// putting the content inside proper and tags, if the +// provided text misses them. +func ParseHTML(r io.Reader) (*Node, error) { + ns, err := html.ParseFragment(r, nil) + if err != nil { + return nil, err + } + + var nodes []Node + var text []byte + + n := ns[0] + + // The root node. + nodes = append(nodes, Node{kind: startNode}) + + for n != nil { + switch n.Type { + case html.DocumentNode: + case html.ElementNode: + nodes = append(nodes, Node{ + kind: startNode, + name: xml.Name{Local: n.Data, Space: n.Namespace}, + }) + for _, attr := range n.Attr { + nodes = append(nodes, Node{ + kind: attrNode, + name: xml.Name{Local: attr.Key, Space: attr.Namespace}, + attr: attr.Val, + }) + } + case html.TextNode: + texti := len(text) + text = append(text, n.Data...) + nodes = append(nodes, Node{ + kind: textNode, + text: text[texti : texti+len(n.Data)], + }) + case html.CommentNode: + texti := len(text) + text = append(text, n.Data...) + nodes = append(nodes, Node{ + kind: commentNode, + text: text[texti : texti+len(n.Data)], + }) + } + + if n.FirstChild != nil { + n = n.FirstChild + continue + } + + for n != nil { + if n.Type == html.ElementNode { + nodes = append(nodes, Node{kind: endNode}) + } + if n.NextSibling != nil { + n = n.NextSibling + break + } + n = n.Parent + } + } + + // Close the root node. + nodes = append(nodes, Node{kind: endNode}) + + stack := make([]*Node, 0, len(nodes)) + downs := make([]*Node, len(nodes)) + downCount := 0 + + for pos := range nodes { + + switch nodes[pos].kind { + + case startNode, attrNode, textNode, commentNode, procInstNode: + node := &nodes[pos] + node.nodes = nodes + node.pos = pos + if len(stack) > 0 { + node.up = stack[len(stack)-1] + } + if node.kind == startNode { + stack = append(stack, node) + } else { + node.end = pos + 1 + } + + case endNode: + node := stack[len(stack)-1] + node.end = pos + stack = stack[:len(stack)-1] + + // Compute downs. Doing that here is what enables the + // use of a slice of a contiguous pre-allocated block. + node.down = downs[downCount:downCount] + for i := node.pos + 1; i < node.end; i++ { + if nodes[i].up == node { + switch nodes[i].kind { + case startNode, textNode, commentNode, procInstNode: + node.down = append(node.down, &nodes[i]) + downCount++ + } + } + } + if len(stack) == 0 { + return node, nil + } + } + } + return nil, io.EOF +} diff --git a/vendor/gopkg.in/xmlpath.v2/path.go b/vendor/gopkg.in/xmlpath.v2/path.go new file mode 100644 index 000000000..db38ed573 --- /dev/null +++ b/vendor/gopkg.in/xmlpath.v2/path.go @@ -0,0 +1,790 @@ +package xmlpath + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +// Path is a compiled path that can be applied to a context +// node to obtain a matching node set. +// A single Path can be applied concurrently to any number +// of context nodes. +type Path struct { + path string + steps []pathStep +} + +// Iter returns an iterator that goes over the list of nodes +// that p matches on the given context. +func (p *Path) Iter(context *Node) *Iter { + iter := Iter{ + make([]pathStepState, len(p.steps)), + make([]bool, len(context.nodes)), + } + for i := range p.steps { + iter.state[i].step = &p.steps[i] + } + iter.state[0].init(context) + return &iter +} + +// Exists returns whether any nodes match p on the given context. +func (p *Path) Exists(context *Node) bool { + return p.Iter(context).Next() +} + +// String returns the string value of the first node matched +// by p on the given context. +// +// See the documentation of Node.String. +func (p *Path) String(context *Node) (s string, ok bool) { + iter := p.Iter(context) + if iter.Next() { + return iter.Node().String(), true + } + return "", false +} + +// Bytes returns as a byte slice the string value of the first +// node matched by p on the given context. +// +// See the documentation of Node.String. +func (p *Path) Bytes(node *Node) (b []byte, ok bool) { + iter := p.Iter(node) + if iter.Next() { + return iter.Node().Bytes(), true + } + return nil, false +} + +// Iter iterates over node sets. +type Iter struct { + state []pathStepState + seen []bool +} + +// Node returns the current node. +// Must only be called after Iter.Next returns true. +func (iter *Iter) Node() *Node { + state := iter.state[len(iter.state)-1] + if state.pos == 0 { + panic("Iter.Node called before Iter.Next") + } + if state.node == nil { + panic("Iter.Node called after Iter.Next false") + } + return state.node +} + +// Next iterates to the next node in the set, if any, and +// returns whether there is a node available. +func (iter *Iter) Next() bool { + tip := len(iter.state) - 1 +outer: + for { + for !iter.state[tip].next() { + tip-- + if tip == -1 { + return false + } + } + for tip < len(iter.state)-1 { + tip++ + iter.state[tip].init(iter.state[tip-1].node) + if !iter.state[tip].next() { + tip-- + continue outer + } + } + if iter.seen[iter.state[tip].node.pos] { + continue + } + iter.seen[iter.state[tip].node.pos] = true + return true + } + panic("unreachable") +} + +type pathStepState struct { + step *pathStep + node *Node + pos int + idx int + aux int +} + +func (s *pathStepState) init(node *Node) { + s.node = node + s.pos = 0 + s.idx = 0 + s.aux = 0 +} + +func (s *pathStepState) next() bool { + for s._next() { + s.pos++ + if s.step.pred == nil || s.test(s.step.pred) { + return true + } + } + return false +} + +func (s *pathStepState) test(pred predicate) bool { + switch pred := pred.(type) { + case positionPredicate: + if pred.pos == s.pos { + return true + } + case existsPredicate: + if pred.path.Exists(s.node) { + return true + } + case equalsPredicate: + iter := pred.path.Iter(s.node) + for iter.Next() { + if iter.Node().equals(pred.value) { + return true + } + } + case containsPredicate: + iter := pred.path.Iter(s.node) + for iter.Next() { + if iter.Node().contains(pred.value) { + return true + } + } + case notPredicate: + iter := pred.path.Iter(s.node) + if !iter.Next() { + return true + } + case andPredicate: + for _, sub := range pred.sub { + if !s.test(sub) { + return false + } + } + return true + case orPredicate: + for _, sub := range pred.sub { + if s.test(sub) { + return true + } + } + default: + panic(fmt.Sprintf("internal error: unknown predicate type: %#v", s.step.pred)) + } + return false +} + +func (s *pathStepState) _next() bool { + if s.node == nil { + return false + } + if s.step.root && s.idx == 0 { + for s.node.up != nil { + s.node = s.node.up + } + } + + switch s.step.axis { + + case "self": + if s.idx == 0 && s.step.match(s.node) { + s.idx++ + return true + } + + case "parent": + if s.idx == 0 && s.node.up != nil && s.step.match(s.node.up) { + s.idx++ + s.node = s.node.up + return true + } + + case "ancestor", "ancestor-or-self": + if s.idx == 0 && s.step.axis == "ancestor-or-self" { + s.idx++ + if s.step.match(s.node) { + return true + } + } + for s.node.up != nil { + s.node = s.node.up + s.idx++ + if s.step.match(s.node) { + return true + } + } + + case "child": + var down []*Node + if s.idx == 0 { + down = s.node.down + } else { + down = s.node.up.down + } + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if s.step.match(node) { + s.node = node + return true + } + } + + case "descendant", "descendant-or-self": + if s.idx == 0 { + s.idx = s.node.pos + s.aux = s.node.end + if s.step.axis == "descendant" { + s.idx++ + } + } + for s.idx < s.aux { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind == attrNode { + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "following": + if s.idx == 0 { + s.idx = s.node.end + } + for s.idx < len(s.node.nodes) { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind == attrNode { + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "following-sibling": + var down []*Node + if s.node.up != nil { + down = s.node.up.down + if s.idx == 0 { + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if node == s.node { + break + } + } + } + } + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if s.step.match(node) { + s.node = node + return true + } + } + + case "preceding": + if s.idx == 0 { + s.aux = s.node.pos // Detect ancestors. + s.idx = s.node.pos - 1 + } + for s.idx >= 0 { + node := &s.node.nodes[s.idx] + s.idx-- + if node.kind == attrNode { + continue + } + if node == s.node.nodes[s.aux].up { + s.aux = s.node.nodes[s.aux].up.pos + continue + } + if s.step.match(node) { + s.node = node + return true + } + } + + case "preceding-sibling": + var down []*Node + if s.node.up != nil { + down = s.node.up.down + if s.aux == 0 { + s.aux = 1 + for s.idx < len(down) { + node := down[s.idx] + s.idx++ + if node == s.node { + s.idx-- + break + } + } + } + } + for s.idx >= 0 { + node := down[s.idx] + s.idx-- + if s.step.match(node) { + s.node = node + return true + } + } + + case "attribute": + if s.idx == 0 { + s.idx = s.node.pos + 1 + s.aux = s.node.end + } + for s.idx < s.aux { + node := &s.node.nodes[s.idx] + s.idx++ + if node.kind != attrNode { + break + } + if s.step.match(node) { + s.node = node + return true + } + } + + } + + s.node = nil + return false +} + +type positionPredicate struct { + pos int +} + +type existsPredicate struct { + path *Path +} + +type equalsPredicate struct { + path *Path + value string +} + +type containsPredicate struct { + path *Path + value string +} + +type notPredicate struct { + path *Path +} + +type andPredicate struct { + sub []predicate +} + +type orPredicate struct { + sub []predicate +} + +// predicate is a marker interface for predicate types. +type predicate interface { + predicate() +} + +func (positionPredicate) predicate() {} +func (existsPredicate) predicate() {} +func (equalsPredicate) predicate() {} +func (containsPredicate) predicate() {} +func (notPredicate) predicate() {} +func (andPredicate) predicate() {} +func (orPredicate) predicate() {} + +type pathStep struct { + root bool + axis string + name string + kind nodeKind + pred predicate +} + +func (step *pathStep) match(node *Node) bool { + return node.kind != endNode && + (step.kind == anyNode || step.kind == node.kind) && + (step.name == "*" || node.name.Local == step.name) +} + +// MustCompile returns the compiled path, and panics if +// there are any errors. +func MustCompile(path string) *Path { + e, err := Compile(path) + if err != nil { + panic(err) + } + return e +} + +// Compile returns the compiled path. +func Compile(path string) (*Path, error) { + c := pathCompiler{path, 0} + if path == "" { + return nil, c.errorf("empty path") + } + p, err := c.parsePath() + if err != nil { + return nil, err + } + return p, nil +} + +type pathCompiler struct { + path string + i int +} + +func (c *pathCompiler) errorf(format string, args ...interface{}) error { + return fmt.Errorf("compiling xml path %q:%d: %s", c.path, c.i, fmt.Sprintf(format, args...)) +} + +func (c *pathCompiler) parsePath() (path *Path, err error) { + var steps []pathStep + var start = c.i + for { + step := pathStep{axis: "child"} + + c.skipSpaces() + if c.i == 0 && c.skipByte('/') { + c.skipSpaces() + step.root = true + if len(c.path) == 1 { + step.name = "*" + } + } + if c.peekByte('/') { + step.axis = "descendant-or-self" + step.name = "*" + } else if c.skipByte('@') { + mark := c.i + if !c.skipName() { + return nil, c.errorf("missing name after @") + } + step.axis = "attribute" + step.name = c.path[mark:c.i] + step.kind = attrNode + } else { + mark := c.i + if c.skipName() { + step.name = c.path[mark:c.i] + c.skipSpaces() + } + if step.name == "" { + return nil, c.errorf("missing name") + } else if step.name == "*" { + step.kind = startNode + } else if step.name == "." { + step.axis = "self" + step.name = "*" + } else if step.name == ".." { + step.axis = "parent" + step.name = "*" + } else { + if c.skipByte(':') { + if !c.skipByte(':') { + return nil, c.errorf("missing ':'") + } + c.skipSpaces() + switch step.name { + case "attribute": + step.kind = attrNode + case "self", "child", "parent": + case "descendant", "descendant-or-self": + case "ancestor", "ancestor-or-self": + case "following", "following-sibling": + case "preceding", "preceding-sibling": + default: + return nil, c.errorf("unsupported axis: %q", step.name) + } + step.axis = step.name + + mark = c.i + if !c.skipName() { + return nil, c.errorf("missing name") + } + step.name = c.path[mark:c.i] + + c.skipSpaces() + } + if c.skipByte('(') { + c.skipSpaces() + conflict := step.kind != anyNode + switch step.name { + case "node": + // must be anyNode + case "text": + step.kind = textNode + case "comment": + step.kind = commentNode + case "processing-instruction": + step.kind = procInstNode + default: + return nil, c.errorf("unsupported expression: %s()", step.name) + } + if conflict { + return nil, c.errorf("%s() cannot succeed on axis %q", step.name, step.axis) + } + + name := step.name + literal, err := c.parseLiteral() + if err == errNoLiteral { + step.name = "*" + } else if err != nil { + return nil, c.errorf("%v", err) + } else if step.kind == procInstNode { + c.skipSpaces() + step.name = literal + } else { + return nil, c.errorf("%s() has no arguments", name) + } + if !c.skipByte(')') { + return nil, c.errorf("%s() missing ')'", name) + } + c.skipSpaces() + } else if step.name == "*" && step.kind == anyNode { + step.kind = startNode + } + } + } + if c.skipByte('[') { + c.skipSpaces() + type state struct { + sub []predicate + and bool + } + var stack []state + var sub []predicate + var and bool + NextPred: + if c.skipByte('(') { + stack = append(stack, state{sub, and}) + sub = nil + and = false + } + var next predicate + if pos, ok := c.parseInt(); ok { + if pos == 0 { + return nil, c.errorf("positions start at 1") + } + next = positionPredicate{pos} + } else if c.skipString("contains(") { + path, err := c.parsePath() + if err != nil { + return nil, err + } + c.skipSpaces() + if !c.skipByte(',') { + return nil, c.errorf("contains() expected ',' followed by a literal string") + } + c.skipSpaces() + value, err := c.parseLiteral() + if err != nil { + return nil, err + } + c.skipSpaces() + if !c.skipByte(')') { + return nil, c.errorf("contains() missing ')'") + } + next = containsPredicate{path, value} + } else if c.skipString("not(") { + // TODO Generalize to handle any predicate expression. + path, err := c.parsePath() + if err != nil { + return nil, err + } + c.skipSpaces() + if !c.skipByte(')') { + return nil, c.errorf("not() missing ')'") + } + next = notPredicate{path} + } else { + path, err := c.parsePath() + if err != nil { + return nil, err + } + if path.path[0] == '-' { + if _, err = strconv.Atoi(path.path); err == nil { + return nil, c.errorf("positions must be positive") + } + } + c.skipSpaces() + if c.skipByte('=') { + c.skipSpaces() + value, err := c.parseLiteral() + if err != nil { + return nil, c.errorf("%v", err) + } + next = equalsPredicate{path, value} + } else { + next = existsPredicate{path} + } + } + HandleNext: + if and { + p := sub[len(sub)-1].(andPredicate) + p.sub = append(p.sub, next) + sub[len(sub)-1] = p + } else { + sub = append(sub, next) + } + if c.skipSpaces() { + mark := c.i + if c.skipString("and") && c.skipSpaces() { + if !and { + and = true + sub[len(sub)-1] = andPredicate{[]predicate{sub[len(sub)-1]}} + } + goto NextPred + } else if c.skipString("or") && c.skipSpaces() { + and = false + goto NextPred + } else { + c.i = mark + } + } + if c.skipByte(')') { + if len(stack) == 0 { + return nil, c.errorf("unexpected ')'") + } + if len(sub) == 1 { + next = sub[0] + } else { + next = orPredicate{sub} + } + s := stack[len(stack)-1] + stack = stack[:len(stack)-1] + sub = s.sub + and = s.and + goto HandleNext + } + if len(stack) > 0 { + return nil, c.errorf("expected ')'") + } + if len(sub) == 1 { + step.pred = sub[0] + } else { + step.pred = orPredicate{sub} + } + if !c.skipByte(']') { + return nil, c.errorf("expected ']'") + } + c.skipSpaces() + } + steps = append(steps, step) + //fmt.Printf("step: %#v\n", step) + if !c.skipByte('/') { + if (start == 0 || start == c.i) && c.i < len(c.path) { + return nil, c.errorf("unexpected %q", c.path[c.i]) + } + return &Path{steps: steps, path: c.path[start:c.i]}, nil + } + } + panic("unreachable") +} + +var errNoLiteral = fmt.Errorf("expected a literal string") + +func (c *pathCompiler) parseLiteral() (string, error) { + if c.skipByte('"') { + mark := c.i + if !c.skipByteFind('"') { + return "", fmt.Errorf(`missing '"'`) + } + return c.path[mark : c.i-1], nil + } + if c.skipByte('\'') { + mark := c.i + if !c.skipByteFind('\'') { + return "", fmt.Errorf(`missing "'"`) + } + return c.path[mark : c.i-1], nil + } + return "", errNoLiteral +} + +func (c *pathCompiler) parseInt() (v int, ok bool) { + mark := c.i + for c.i < len(c.path) && c.path[c.i] >= '0' && c.path[c.i] <= '9' { + v *= 10 + v += int(c.path[c.i]) - '0' + c.i++ + } + if c.i == mark { + return 0, false + } + return v, true +} + +func (c *pathCompiler) skipByte(b byte) bool { + if c.i < len(c.path) && c.path[c.i] == b { + c.i++ + return true + } + return false +} + +func (c *pathCompiler) skipByteFind(b byte) bool { + for i := c.i; i < len(c.path); i++ { + if c.path[i] == b { + c.i = i + 1 + return true + } + } + return false +} + +func (c *pathCompiler) peekByte(b byte) bool { + return c.i < len(c.path) && c.path[c.i] == b +} + +func (c *pathCompiler) skipSpaces() bool { + mark := c.i + for c.i < len(c.path) { + if c.path[c.i] != ' ' { + break + } + c.i++ + } + return c.i != mark +} + +func (c *pathCompiler) skipString(s string) bool { + if c.i+len(s) <= len(c.path) && c.path[c.i:c.i+len(s)] == s { + c.i += len(s) + return true + } + return false +} + +func (c *pathCompiler) skipName() bool { + if c.i >= len(c.path) { + return false + } + if c.path[c.i] == '*' { + c.i++ + return true + } + start := c.i + for c.i < len(c.path) && (c.path[c.i] >= utf8.RuneSelf || isNameByte(c.path[c.i])) { + c.i++ + } + return c.i > start +} + +func isNameByte(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '.' || c == '-' +} From 3c8bb4ea68ed641e86016f73e5eafd50ad145f3d Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 11:16:39 -0800 Subject: [PATCH 04/12] Just run from root always --- scripts/generate-plugins.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/generate-plugins.go b/scripts/generate-plugins.go index 2dced41a3..84a69ae9c 100644 --- a/scripts/generate-plugins.go +++ b/scripts/generate-plugins.go @@ -20,16 +20,9 @@ import ( const target = "command/plugin.go" func main() { - // Normally this is run via go:generate from the command folder so we need - // to cd .. first. But when developing it's easier to use go run, so we'll - // support that too. wd, _ := os.Getwd() if filepath.Base(wd) != "packer" { - os.Chdir("..") - wd, _ = os.Getwd() - if filepath.Base(wd) != "packer" { - log.Fatalf("This program must be invoked in the packer project root; in %s", wd) - } + log.Fatalf("This program must be invoked in the packer project root; in %s", wd) } // Collect all of the data we need about plugins we have in the project From 33d1c17d29df32766862460a2b4ea25b0f813037 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 11:17:05 -0800 Subject: [PATCH 05/12] Generate plugins.go from main.go --- main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.go b/main.go index 5e67a326f..f75736e65 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,6 @@ // This is the main package for the `packer` application. + +//go:generate go run ./scripts/generate-plugins.go package main import ( From 171265c9831f256054f75e5b7fbfce7ecc787e0a Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 11:17:48 -0800 Subject: [PATCH 06/12] Remove generator from command/version because we can't go build ./... -- it also builds vendored stuff --- command/version.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/command/version.go b/command/version.go index f5898e77d..cd170f2df 100644 --- a/command/version.go +++ b/command/version.go @@ -1,7 +1,5 @@ package command -//go:generate go run ../scripts/generate-plugins.go - import ( "bytes" "fmt" From 4335d2f13a604c3a8164f18575fd024a5dea1b41 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 11:18:11 -0800 Subject: [PATCH 07/12] Update the makefile to work with vendored dependencies --- Makefile | 50 +++++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 806a018eb..8430b9e1b 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ -TEST?=./... +TEST?=$(shell go list ./... | grep -v vendor) # Get the current full sha from git GITSHA:=$(shell git rev-parse HEAD) # Get the current local branch name from git (if we can, this may be blank) GITBRANCH:=$(shell git symbolic-ref --short HEAD 2>/dev/null) -default: test dev +default: deps generate test dev ci: deps test -release: updatedeps test releasebin +release: deps test releasebin bin: deps @echo "WARN: 'make bin' is for debug / test builds only. Use 'make release' for release builds." @@ -22,7 +22,10 @@ releasebin: deps @sh -c "$(CURDIR)/scripts/build.sh" deps: - go get -v -d ./... + go get github.com/mitchellh/gox + go get golang.org/x/tools/cmd/stringer + go get golang.org/x/tools/cmd/vet + @echo "INFO: Packer deps are managed by godep. See CONTRIBUTING.md" dev: deps @grep 'const VersionPrerelease = ""' version.go > /dev/null ; if [ $$? -eq 0 ]; then \ @@ -34,13 +37,12 @@ dev: deps # generate runs `go generate` to build the dynamically generated # source files. generate: deps - go generate ./... + go generate . + go fmt command/plugin.go test: deps - go test $(TEST) $(TESTARGS) -timeout=15s | tee packer-test.log - @go vet 2>/dev/null ; if [ $$? -eq 3 ]; then \ - go get golang.org/x/tools/cmd/vet; \ - fi + @echo "INFO: Test results going to packer-test.log; this may take awhile" + @go test $(TEST) $(TESTARGS) -timeout=15s | tee packer-test.log @go vet $(TEST) ; if [ $$? -eq 1 ]; then \ echo "ERROR: Vet found problems in the code."; \ exit 1; \ @@ -52,35 +54,13 @@ testacc: deps generate PACKER_ACC=1 go test -v $(TEST) $(TESTARGS) -timeout=45m | tee packer-test-acc.log testrace: deps - go test -race $(TEST) $(TESTARGS) -timeout=15s | tee packer-test-race.log + @echo "INFO: Test results going to packer-test-race.log; this may take awhile" + @go test -race $(TEST) $(TESTARGS) -timeout=15s | tee packer-test-race.log -# `go get -u` causes git to revert packer to the master branch. This causes all -# kinds of headaches. We record the git sha when make starts try to correct it -# if we detect dift. DO NOT use `git checkout -f` for this because it will wipe -# out your changes without asking. updatedeps: - @echo "INFO: Currently on $(GITBRANCH) ($(GITSHA))" - @git diff-index --quiet HEAD ; if [ $$? -ne 0 ]; then \ - echo "ERROR: Your git working tree has uncommitted changes. updatedeps will fail. Please stash or commit your changes first."; \ - exit 1; \ - fi go get -u github.com/mitchellh/gox go get -u golang.org/x/tools/cmd/stringer - go get -u golang.org/x/sys/unix - go get -u google.golang.org/appengine - go list ./... \ - | xargs go list -f '{{join .Deps "\n"}}' \ - | grep -v github.com/mitchellh/packer \ - | grep -v '/internal/' \ - | sort -u \ - | xargs go get -f -u -v -d ; if [ $$? -ne 0 ]; then \ - echo "ERROR: go get failed. Your git branch may have changed; you were on $(GITBRANCH) ($(GITSHA))."; \ - fi - @if [ "$(GITBRANCH)" != "" ]; then git checkout -q $(GITBRANCH); else git checkout -q $(GITSHA); fi - @if [ `git rev-parse HEAD` != "$(GITSHA)" ]; then \ - echo "ERROR: git checkout has drifted and we weren't able to correct it. Was $(GITBRANCH) ($(GITSHA))"; \ - exit 1; \ - fi - @echo "INFO: Currently on $(GITBRANCH) ($(GITSHA))" + go get -u golang.org/x/tools/cmd/vet + @echo "INFO: Packer deps are managed by godep. See CONTRIBUTING.md" .PHONY: bin checkversion ci default deps generate releasebin test testacc testrace updatedeps From 93547ad91ce03d393a90e53136118ddde2ab125e Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 11:18:36 -0800 Subject: [PATCH 08/12] Regenerate command/plugin and apply go fmt (now handled by the makefile) --- command/plugin.go | 104 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/command/plugin.go b/command/plugin.go index cf213b3ef..64fb47e69 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -16,42 +16,42 @@ import ( amazonchrootbuilder "github.com/mitchellh/packer/builder/amazon/chroot" amazonebsbuilder "github.com/mitchellh/packer/builder/amazon/ebs" amazoninstancebuilder "github.com/mitchellh/packer/builder/amazon/instance" - ansiblelocalprovisioner "github.com/mitchellh/packer/provisioner/ansible-local" - artificepostprocessor "github.com/mitchellh/packer/post-processor/artifice" - atlaspostprocessor "github.com/mitchellh/packer/post-processor/atlas" - chefclientprovisioner "github.com/mitchellh/packer/provisioner/chef-client" - chefsoloprovisioner "github.com/mitchellh/packer/provisioner/chef-solo" - compresspostprocessor "github.com/mitchellh/packer/post-processor/compress" digitaloceanbuilder "github.com/mitchellh/packer/builder/digitalocean" dockerbuilder "github.com/mitchellh/packer/builder/docker" - dockerimportpostprocessor "github.com/mitchellh/packer/post-processor/docker-import" - dockerpushpostprocessor "github.com/mitchellh/packer/post-processor/docker-push" - dockersavepostprocessor "github.com/mitchellh/packer/post-processor/docker-save" - dockertagpostprocessor "github.com/mitchellh/packer/post-processor/docker-tag" filebuilder "github.com/mitchellh/packer/builder/file" - fileprovisioner "github.com/mitchellh/packer/provisioner/file" googlecomputebuilder "github.com/mitchellh/packer/builder/googlecompute" nullbuilder "github.com/mitchellh/packer/builder/null" openstackbuilder "github.com/mitchellh/packer/builder/openstack" parallelsisobuilder "github.com/mitchellh/packer/builder/parallels/iso" parallelspvmbuilder "github.com/mitchellh/packer/builder/parallels/pvm" - powershellprovisioner "github.com/mitchellh/packer/provisioner/powershell" - puppetmasterlessprovisioner "github.com/mitchellh/packer/provisioner/puppet-masterless" - puppetserverprovisioner "github.com/mitchellh/packer/provisioner/puppet-server" qemubuilder "github.com/mitchellh/packer/builder/qemu" - saltmasterlessprovisioner "github.com/mitchellh/packer/provisioner/salt-masterless" - shelllocalprovisioner "github.com/mitchellh/packer/provisioner/shell-local" - shellprovisioner "github.com/mitchellh/packer/provisioner/shell" - vagrantcloudpostprocessor "github.com/mitchellh/packer/post-processor/vagrant-cloud" - vagrantpostprocessor "github.com/mitchellh/packer/post-processor/vagrant" virtualboxisobuilder "github.com/mitchellh/packer/builder/virtualbox/iso" virtualboxovfbuilder "github.com/mitchellh/packer/builder/virtualbox/ovf" vmwareisobuilder "github.com/mitchellh/packer/builder/vmware/iso" vmwarevmxbuilder "github.com/mitchellh/packer/builder/vmware/vmx" + artificepostprocessor "github.com/mitchellh/packer/post-processor/artifice" + atlaspostprocessor "github.com/mitchellh/packer/post-processor/atlas" + compresspostprocessor "github.com/mitchellh/packer/post-processor/compress" + dockerimportpostprocessor "github.com/mitchellh/packer/post-processor/docker-import" + dockerpushpostprocessor "github.com/mitchellh/packer/post-processor/docker-push" + dockersavepostprocessor "github.com/mitchellh/packer/post-processor/docker-save" + dockertagpostprocessor "github.com/mitchellh/packer/post-processor/docker-tag" + vagrantpostprocessor "github.com/mitchellh/packer/post-processor/vagrant" + vagrantcloudpostprocessor "github.com/mitchellh/packer/post-processor/vagrant-cloud" vspherepostprocessor "github.com/mitchellh/packer/post-processor/vsphere" + ansibleprovisioner "github.com/mitchellh/packer/provisioner/ansible" + ansiblelocalprovisioner "github.com/mitchellh/packer/provisioner/ansible-local" + chefclientprovisioner "github.com/mitchellh/packer/provisioner/chef-client" + chefsoloprovisioner "github.com/mitchellh/packer/provisioner/chef-solo" + fileprovisioner "github.com/mitchellh/packer/provisioner/file" + powershellprovisioner "github.com/mitchellh/packer/provisioner/powershell" + puppetmasterlessprovisioner "github.com/mitchellh/packer/provisioner/puppet-masterless" + puppetserverprovisioner "github.com/mitchellh/packer/provisioner/puppet-server" + saltmasterlessprovisioner "github.com/mitchellh/packer/provisioner/salt-masterless" + shellprovisioner "github.com/mitchellh/packer/provisioner/shell" + shelllocalprovisioner "github.com/mitchellh/packer/provisioner/shell-local" windowsrestartprovisioner "github.com/mitchellh/packer/provisioner/windows-restart" windowsshellprovisioner "github.com/mitchellh/packer/provisioner/windows-shell" - ) type PluginCommand struct { @@ -60,54 +60,52 @@ type PluginCommand struct { var Builders = map[string]packer.Builder{ "amazon-chroot": new(amazonchrootbuilder.Builder), - "amazon-ebs": new(amazonebsbuilder.Builder), - "amazon-instance": new(amazoninstancebuilder.Builder), - "digitalocean": new(digitaloceanbuilder.Builder), - "docker": new(dockerbuilder.Builder), - "file": new(filebuilder.Builder), + "amazon-ebs": new(amazonebsbuilder.Builder), + "amazon-instance": new(amazoninstancebuilder.Builder), + "digitalocean": new(digitaloceanbuilder.Builder), + "docker": new(dockerbuilder.Builder), + "file": new(filebuilder.Builder), "googlecompute": new(googlecomputebuilder.Builder), - "null": new(nullbuilder.Builder), - "openstack": new(openstackbuilder.Builder), + "null": new(nullbuilder.Builder), + "openstack": new(openstackbuilder.Builder), "parallels-iso": new(parallelsisobuilder.Builder), "parallels-pvm": new(parallelspvmbuilder.Builder), - "qemu": new(qemubuilder.Builder), - "virtualbox-iso": new(virtualboxisobuilder.Builder), - "virtualbox-ovf": new(virtualboxovfbuilder.Builder), - "vmware-iso": new(vmwareisobuilder.Builder), - "vmware-vmx": new(vmwarevmxbuilder.Builder), + "qemu": new(qemubuilder.Builder), + "virtualbox-iso": new(virtualboxisobuilder.Builder), + "virtualbox-ovf": new(virtualboxovfbuilder.Builder), + "vmware-iso": new(vmwareisobuilder.Builder), + "vmware-vmx": new(vmwarevmxbuilder.Builder), } - var Provisioners = map[string]packer.Provisioner{ - "ansible-local": new(ansiblelocalprovisioner.Provisioner), - "chef-client": new(chefclientprovisioner.Provisioner), - "chef-solo": new(chefsoloprovisioner.Provisioner), - "file": new(fileprovisioner.Provisioner), - "powershell": new(powershellprovisioner.Provisioner), - "puppet-masterless": new(puppetmasterlessprovisioner.Provisioner), - "puppet-server": new(puppetserverprovisioner.Provisioner), + "ansible": new(ansibleprovisioner.Provisioner), + "ansible-local": new(ansiblelocalprovisioner.Provisioner), + "chef-client": new(chefclientprovisioner.Provisioner), + "chef-solo": new(chefsoloprovisioner.Provisioner), + "file": new(fileprovisioner.Provisioner), + "powershell": new(powershellprovisioner.Provisioner), + "puppet-masterless": new(puppetmasterlessprovisioner.Provisioner), + "puppet-server": new(puppetserverprovisioner.Provisioner), "salt-masterless": new(saltmasterlessprovisioner.Provisioner), - "shell": new(shellprovisioner.Provisioner), - "shell-local": new(shelllocalprovisioner.Provisioner), + "shell": new(shellprovisioner.Provisioner), + "shell-local": new(shelllocalprovisioner.Provisioner), "windows-restart": new(windowsrestartprovisioner.Provisioner), - "windows-shell": new(windowsshellprovisioner.Provisioner), + "windows-shell": new(windowsshellprovisioner.Provisioner), } - var PostProcessors = map[string]packer.PostProcessor{ - "artifice": new(artificepostprocessor.PostProcessor), - "atlas": new(atlaspostprocessor.PostProcessor), - "compress": new(compresspostprocessor.PostProcessor), - "docker-import": new(dockerimportpostprocessor.PostProcessor), + "artifice": new(artificepostprocessor.PostProcessor), + "atlas": new(atlaspostprocessor.PostProcessor), + "compress": new(compresspostprocessor.PostProcessor), + "docker-import": new(dockerimportpostprocessor.PostProcessor), "docker-push": new(dockerpushpostprocessor.PostProcessor), "docker-save": new(dockersavepostprocessor.PostProcessor), - "docker-tag": new(dockertagpostprocessor.PostProcessor), - "vagrant": new(vagrantpostprocessor.PostProcessor), - "vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor), - "vsphere": new(vspherepostprocessor.PostProcessor), + "docker-tag": new(dockertagpostprocessor.PostProcessor), + "vagrant": new(vagrantpostprocessor.PostProcessor), + "vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor), + "vsphere": new(vspherepostprocessor.PostProcessor), } - var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)") func (c *PluginCommand) Run(args []string) int { From c10e0eb398231bed7b2b98d27657ed161e8123ce Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 13:42:27 -0800 Subject: [PATCH 09/12] Removed go get from build scripts since we have these in vendor already --- scripts/build.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 2b5048ecb..343ea04cf 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -25,10 +25,6 @@ fi XC_ARCH=${XC_ARCH:-"386 amd64 arm"} XC_OS=${XC_OS:-linux darwin windows freebsd openbsd} -# Install dependencies -echo "==> Getting dependencies..." -go get -d ./... - # Delete the old dir echo "==> Removing old directory..." rm -f bin/* From ad5416e2e300fa307f2eb867880347d6566452eb Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 13:43:18 -0800 Subject: [PATCH 10/12] Updated CONTRIBUTING.md to have up-to-date information about building with Go --- CONTRIBUTING.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 174f5f642..c2f9579f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,35 +53,35 @@ it raises the chances we can quickly merge or address your contributions. If you have never worked with Go before, you will have to complete the following steps in order to be able to compile and test Packer. -1. Install Go. Make sure the Go version is at least Go 1.4. Packer will not work with anything less than - Go 1.4. On a Mac, you can `brew install go` to install Go 1.4. +1. [Download](https://golang.org/dl) and install Go. Make sure your Go version + is at least Go 1.5. Packer _may_ work with older versions of Go but these + are not supported. -2. Set and export the `GOPATH` environment variable and update your `PATH`. - For example, you can add to your `.bash_profile`. +2. Set and export the `GOPATH` environment variable and update your `PATH`. For + example, you can add to your `.bash_profile`. If you're using Go 1.5 also + set `GO15VENDOREXPERIMENT`. This is not necessary for Go 1.6 and up. ``` export GOPATH=$HOME/Documents/golang + export GO15VENDOREXPERIMENT=1 export PATH=$PATH:$GOPATH/bin ``` -3. Install and build `gox` with +3. Download the Packer source (and its dependencies) by running `go get + github.com/mitchellh/packer`. This will download the Packer source to + `$GOPATH/src/github.com/mitchellh/packer`. - ``` - go get github.com/mitchellh/gox - cd $GOPATH/src/github.com/mitchellh/gox - go build - ``` +4. When working on packer `cd $GOPATH/src/github.com/mitchellh/packer` so you + can run make and easily access other files. -4. Download the Packer source (and its dependencies) by running - `go get github.com/mitchellh/packer`. This will download the Packer - source to `$GOPATH/src/github.com/mitchellh/packer`. +5. Make your changes to the Packer source. You can run `make` in + `$GOPATH/src/github.com/mitchellh/packer` to run tests and build the packer + binary. Any compilation errors will be shown when the binaries are + rebuilding. -5. Make your changes to the Packer source. You can run `make` from the main - source directory to recompile all the binaries. Any compilation errors - will be shown when the binaries are rebuilding. - -6. Test your changes by running `make test` and then running - `$GOPATH/src/github.com/mitchellh/packer/bin/packer` to build a machine. +6. After running `make` successfully, use + `$GOPATH/src/github.com/mitchellh/packer/bin/packer` to build a machine and + verify your changes work. 7. If everything works well and the tests pass, run `go fmt` on your code - before submitting a pull request. + before submitting a pull-request. From 6ca15f7e1af629613fd13a85e120f726f18e9b29 Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 14:08:58 -0800 Subject: [PATCH 11/12] Updated appveyor script to (hopefully) work with a vendored build on Windows --- appveyor.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c5d317da6..023f823ba 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,25 +14,28 @@ environment: GOPATH: c:\gopath matrix: - GOARCH: 386 - GOVERSION: 1.4.2 + GOVERSION: 1.6rc2 - GOARCH: amd64 - GOVERSION: 1.4.2 + GOVERSION: 1.6rc2 clone_folder: c:\gopath\src\github.com\mitchellh\packer install: - set Path=c:\go\bin;%Path% + - set GO15VENDOREXPERIMENT=1 - echo %Path% - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-%GOARCH%.msi - msiexec /i go%GOVERSION%.windows-%GOARCH%.msi /q - go version - go env - - go get -d -v -t ./... + - go get github.com/mitchellh/gox + - go get golang.org/x/tools/cmd/stringer + - go get golang.org/x/tools/cmd/vet build_script: + - git rev-parse HEAD - go test -v ./... - go vet ./... - - git rev-parse HEAD test: off From f5777bca7bd278ede327e07cb1c4828a5cd4f96f Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 5 Feb 2016 14:21:10 -0800 Subject: [PATCH 12/12] Moved the bulk of go setup to CONTRIBUTING.md so it doesn't need to be maintained in two places --- CONTRIBUTING.md | 43 +++++++++++++++++++++++++ README.md | 86 +++---------------------------------------------- 2 files changed, 48 insertions(+), 81 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c2f9579f5..0e16c6c28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,3 +85,46 @@ following steps in order to be able to compile and test Packer. 7. If everything works well and the tests pass, run `go fmt` on your code before submitting a pull-request. + +### Tips for Working on Packer + +#### Godeps + +If you are submitting a change that requires a change in dependencies, DO NOT update the `vendor/` folder. This keeps the PR smaller and easier to review. Instead, please indicate which upstream has changed and which version we should be using. You _may_ do this using `Godeps/Godeps.json` but this is not required. + +#### Running Unit Tests + +You can run tests for individual packages using commands like this: + + $ make test TEST=./builder/amazon/... + +#### Running Acceptance Tests + +Packer has [acceptance tests](https://en.wikipedia.org/wiki/Acceptance_testing) +for various builders. These typically require an API key (AWS, GCE), or +additional software to be installed on your computer (VirtualBox, VMware). + +If you're working on a feature of a builder or a new builder and want verify it +is functioning (and also hasn't broken anything else), we recommend running the +acceptance tests. + +**Warning:** The acceptance tests create/destroy/modify *real resources*, which +may incur real costs in some cases. In the presence of a bug, it is technically +possible that broken backends could leave dangling data behind. Therefore, +please run the acceptance tests at your own risk. At the very least, we +recommend running them in their own private account for whatever builder you're +testing. + +To run the acceptance tests, invoke `make testacc`: + + $ make testacc TEST=./builder/amazon/ebs + ... + +The `TEST` variable lets you narrow the scope of the acceptance tests to a +specific package / folder. The `TESTARGS` variable is recommended to filter +down to a specific resource to test, since testing all of them at once can +sometimes take a very long time. + +Acceptance tests typically require other environment variables to be set for +things such as access keys. The test itself should error early and tell you +what to set, so it is not documented here. \ No newline at end of file diff --git a/README.md b/README.md index 7285fe6d4..55e8cd87d 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ Packer is a tool for building identical machine images for multiple platforms from a single source configuration. Packer is lightweight, runs on every major operating system, and is highly -performant, creating machine images for multiple platforms in parallel. -Packer comes out of the box with support for the following platforms: +performant, creating machine images for multiple platforms in parallel. Packer +comes out of the box with support for the following platforms: + * Amazon EC2 (AMI). Both EBS-backed and instance-store AMIs * DigitalOcean * Docker @@ -79,87 +80,10 @@ they're run, etc. is up to you. ## Documentation -Full, comprehensive documentation is viewable on the Packer website: +Comprehensive documentation is viewable on the Packer website: http://www.packer.io/docs ## Developing Packer -If you wish to work on Packer itself or any of its built-in providers, -you'll first need [Go](http://www.golang.org) installed (version 1.4+ is -_required_). Make sure Go is properly installed, including setting up -a [GOPATH](http://golang.org/doc/code.html#GOPATH). - -Next, install the following software packages, which are needed for some dependencies: - -- [Bazaar](http://bazaar.canonical.com/en/) -- [Git](http://git-scm.com/) -- [Mercurial](http://mercurial.selenic.com/) - -Then, install [Gox](https://github.com/mitchellh/gox), which is used -as a compilation tool on top of Go: - - $ go get -u github.com/mitchellh/gox - -Next, clone this repository into `$GOPATH/src/github.com/mitchellh/packer`: - - $ cd $GOPATH/src/github.com/mitchellh - $ git clone https://github.com/mitchellh/packer.git - $ cd packer - -Install the necessary dependencies by running `make updatedeps` and then just -type `make`. This will compile some more dependencies and then run the tests. If -this exits with exit status 0, then everything is working! - - $ make updatedeps - ... - $ make - ... - -To compile a development version of Packer and the built-in plugins, -run `make dev`. This will put Packer binaries in the `bin` folder: - - $ make dev - ... - $ bin/packer - ... - - -If you're developing a specific package, you can run tests for just that -package by specifying the `TEST` variable. For example below, only -`packer` package tests will be run. - - $ make test TEST=./packer - ... - -### Acceptance Tests - -Packer has comprehensive [acceptance tests](https://en.wikipedia.org/wiki/Acceptance_testing) -covering the builders of Packer. - -If you're working on a feature of a builder or a new builder and want -verify it is functioning (and also hasn't broken anything else), we recommend -running the acceptance tests. - -**Warning:** The acceptance tests create/destroy/modify *real resources*, which -may incur real costs in some cases. In the presence of a bug, it is technically -possible that broken backends could leave dangling data behind. Therefore, -please run the acceptance tests at your own risk. At the very least, -we recommend running them in their own private account for whatever builder -you're testing. - -To run the acceptance tests, invoke `make testacc`: - -```sh -$ make testacc TEST=./builder/amazon/ebs -... -``` - -The `TEST` variable is required, and you should specify the folder where the -backend is. The `TESTARGS` variable is recommended to filter down to a specific -resource to test, since testing all of them at once can sometimes take a very -long time. - -Acceptance tests typically require other environment variables to be set for -things such as access keys. The test itself should error early and tell -you what to set, so it is not documented here. +See [CONTRIBUTING.md](https://github.com/mitchellh/packer/blob/master/CONTRIBUTING.md) for best practices and instructions on setting up your development environment to work on Packer.

    Qgcjn4g^oJs_DDnZ<-EKxa?AMlg2!~vC42}P%} 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 $l7_Z5rpqT|55%g;SWEy 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�LyYP}Wyy!Yk2txQb zqWq#)A5UZ{jGLW;wdKwMllcuYY$McDDV8_4zE&>9BHvcTivqiq*3S8Fli!+BIdcmS`=WsU|cFCJuqRo2O9GVmO z1nl)aRsQc7Bjg(bA34TON2_d9NKwll&0EW80=>q?Nf_@VuzTxvG$s2J)~7vB%*>Us z!v1(FaxMPwRtn2@(6zNw;o7o1>#CqNWhS5;Kzq-3&(YH~Oom@{g@%g;Y}oM>)Cwnc zC~(yc^8Uc|$SXrm&XR+VT(}k1s7kGo6DR;Fd9($@D@38qQ<#=9h1EK;Jnacy&D(U~#VD9b z2Lrf>wB=?jT5Xeep2e-V+HA7IUj*Srn+v0bgK45iz}uqVVT&%BZ33h@^d|zam)601 zwXu1lJ=Ms8V=j3JcDbKvMG{{&!8w}zTAv< zuBSMwFdn5Rhf{Gt^WD(Y79rbKkOGdfs0vadjRlpF2@5iNl1$yUf>r+GLf3-I2o*MT zw@j!4N$mx3(eVfLQW4Lpk0`gY470BkIxmDRH2h+&p_9LMo6*={}#Tiubo7pZ3n?AbPz|{6XwQ@OP)L9){2$t|_Wt^@3t!?Y2)qK&lx$5J4! z@kDE&tkyVxoOS2uVF_$L&&6+{(1+9f0sqz+9&6c2{Tv)-EkY;7mZOxo(mmirikb~H zLxYD*axP(N?%@C&(#k9;cQVXMqr8iE!hzH>qgS;g4LwBy3#D z&jxV^lzcW(p^vB8mxCQ)yYMN_^K|3BF02CwAjmae@eyLg39ooP#UYBBstFJY20(bb zHLI7G`8J$qnn2;>1zFhZpF~GFMBQ=k(_FT4JvRBqH$Y@oFAdskIjw@s zXM(^>tcp=~+rFs7!D}98fH^0IU<#vdQA*=R-KO7ea|&aW3=op+F^x5i|6OqmXv5Zi zftI2eXJfwJiY~siLllDU+Y=_^p0i!}Q_yG4!-*%@ZCZJYvuz8plYlvVCZJ`>Z~?wj zpsEcQpnI)J5{{iJIITje4Fyd3LXvxsPw2g+!M>}!#2CjwsOTfvy zfws{?FVOp$<_?YP2u-$TpT(=7UfCCXb6JTntoyuP@PmkOIeg#WWx+*Ed*p@_4rvpo z{>jRQ?qZDQ8>}3zl{pw*jy4~+FWBIxJ?dC+DwB^daqX1PT+KF9!N>(Wf^Z+!j#x}K zinqLtuWu`iksU%*JgNils((YM_GxDhW}>gj!3b7Pz=n931mWv>E+!t3fQr!I36?a7 zGY+4J>YT8iw-gQ!cmVqRTAKF@^k~tZOTY+QL=Lja!B=knp5y)W=Y>p6r7SFea?H$sz7;t$#Xs6&b%!X_GQuS(ew%U)AnG1YAIQb2Em z)y=iN=Mjc{Tjj>S`jRW$Bo!*k=eq>^Vlx-wG6C`If#cs~F`xHf5@fiowNSJWMdj)w zm3?e+SnCW>67Dc3%GlL9gA&aFp9Uwf*VK#mauZ3V_Pz`~^(yQsQpJALHLM&?ZWNtF zwu4CW-fXX_>Y~meSnwZl85%IJ%RI%uW#1kJAT2b+i*PSrfoK3sW?`LycO9&R;=>lS zgU$yGU<1Y|YHTwD9v<$)B0P^V=MGX9D6C?bBNV;|g zeP<;Rnt{HscRGnAUId>5jgWE>MeE`~Tbc@=vc`kj`NDOPe3oe`lece@rg?*?Od+26 z+B%X%QNPV;x#0@5`;KFccn+LsJxu&K&aIH+3&YE;@I6TIM=IZ<{3tKFV)qx@D~IzR z0q8?MOisyX^TJ;crC$(lWERjyNwUXhe!=s8SSu~?*^f({cx#X?#E=w5EM)+lA$1G5 zVv0~7LG7dG_TYUZ9wK`$4m}`a0J_uvhbz?1N4Qi8yq*J~Be%FM?l3da$dPr}me100 zv|jM&gFkq#^ee6lbD&ZFO(jt!$>Qz&OjwQm->#Az?>A_a!uMoJpeTcN{3BxD-v%K( zTrd*yB*^;?8m`;)ZN>4bC&@3`BQp{4iGgJ};D8qg!PKu%8BIQ+4HrP3nENHJ!5%52 z1`E(7D17W_O4Lq3lg9X&$|4}a`j|5CuLW()VFB@ly4ZS|A(#Xfn2US!1tx)qYw*rV zfT8k#wE8fa=wv<%ujR)AobSe39?!?0c*u}N>J6!rjS755qZBB+}+rB<=pxrFC zn4fF}_hF6yvXq0@4AWsE9D>lIB)AwtGfW546h@2|y)*S9i@B)tn=SkCm=Tn)!a^%A zi7tZ@+7hPlqla2NL=}g@CzE z#{NZnIh+UuCRIE3u6712*0g`;gL~ejOVf=pc7m6%*y16U!B|;bFo3BY8XB9Wg~^QBYYVHnOx;gv={*> z#0c*LD=Z-d)Svls_(MK`JcbX6ZyiuG*6>@(G&pCZ@| z6p9w_6xSdoKmfaO0*tt#M`PASY%TsIK-h3)_~9WrZ>K7rqGS_c3so36?Of{_gc2j1 z<99GqClj526}yYf$HjY)bZT7P0qHQB$hopfH^GwWN@d}gu_+X>^NWav$sy*Po| z9c$Nx)CK#^Abgw?OluJl0~kWH_~-a*hmG}Z@(0$7BCOXh;KF_mqO_(EJC zKzyN{9RwP9Z-Ig&8h4^&z|YuzO!c7MwA)bIRP+s^<2wb|tz}+Cb~?`|2Sp9K!vU7E zU%wqZ!H(P{U4`E6KS2)%Gcsfgpxw?g`)zj66UJI;>z8f{ z)-Ku_M1-01(zEws!lUvQeAMis=Xuu#l(H>vGv;seX+5K|M<&Gwcsu*j^fcS|m?%a#TfBS}(*5-T3;AtoR2Bs^7wbr-xR)4^%R9~Ly_HQmx;V)7q#4?_G zPLOL{;*!9J#UEprQ>I&+*+N$9i16Z^C*aNPzMkv==v0#yl(tm7u76YmKq8 z7Gv`v@r{wP9q0*Q$)nReLB^pZK1ir~6lRSp+gq3N<%Y^ZAJ}xYC_`;F>-bAkr;GRx z)N?)|j*s7936SLb_|zCR_zD5{t3eY&;5hN@9Z+uV$mb{>heEH+NE==gFS$BMc!a3l zXV-^|>%$86Z5s~3ZuUQhHeDM8&zCZ!BmCl|G*O8j-*EE$92+LGenSJ59D68|PmHPC zGQw!OJcW^|; zS@;a+K%c^hi^8r-Jm35H6xm<(Dx6)WY%d=;?>F5fSRMCgeYIgIQhn(s{`%YZuc8Rz zzMOvvmj6pZ!~sQn>)XGXu>$-aKnLZx3VnPsgm$MLa~B-z0M-!KK#MU{PRzY_k%N{z z3iE8R--JmK&OK+o7vL$Av~+QsMMge|RUaWdP9RRzF0O4~?T+mLIGzq*YK#-DC$OF3 ze%zb3kZo~4=(l#Dbd=1>sJI_Tq#dyB$Wh~$fRyoBv*`s~0b1 zYIDzg{y)^&zbygC`K_%M%`}~aDgUZ>Q^DfJIKO5!G@-CG>h#^GlU*@Yb#DHQbRA|} z0xejTW&y<^>kXsp7hj<_ABedFpIOYK+`=O7N;I_WeR3gUjt0-NiD`H%tmH>eoe#Y2 zpB8_kVr?6yd}f};atZ>qGE&nXpeHvG^OfTt)u#@ncS;MR#~yfZ5`(R@5A_`-62elf>V`%?7Bc`z)t{^nR%kP7?XOkux}d0=+8gH z6PNTD77x%a#E1wbw}l9vWnF`Hhl>`6-s0ka1AUWTdZ&vr+cMZW}N zFjS1LtkrWLLm=zLUQ!21wmOvov1vKgBL|nMAg40McMi+obx!+w^({@8&CCbc3_tj+Kq?vwKLVSq-p=KRGuoWbT&ZE}ETZMu1V zhS_j)LnWP)&HcS-?sw#6hg&^oyNI_h2$*a{z992yyGikG?V1g(z}HJmmf3b4I!)PJ zC{23lX!)625~6eT#qtNLHhGt_gIfFQT+5pN&@vm{mLw(xotoVoHm03Jh?Lmxi+za|( zq2*aY;}}-UK8$KZ=LW*0K+m`$Ys+4>N%Dan>e?g$=Ay)!-si2twR-mVpye>jbAoXE zYY+c2DkzkmRoD8=@*MB18CX!~*Xd3MEb8zWoejLl`FvO1I_Gc4@xr^F$3os0J6P7R zU*r9DWRt^owxSO=enjj#uIkW!ip^fxf#c^F=BqA{571?vJ@DCE+Wu1%;HIJ6+VKk+ z@Ef?OGWRQ>F@UU$X*d^k?)UTI$CUxv)ss}y+yCsB10J(%J1q<9&Y#P1HTt1{)6DuW zeJ`-ft##P+5=Cz&swOiXw-~E`2shi(&0Kl-;1*Yy0dEf6naiq&Hf*H{LIo@=;mt!D zDr;HlNIbPA@Kcy#<6PT;v4fMWbEMeU=@sx0HLG4zn<&`^dM#k{g1SnQmHefDM$zzj z`mR?tmKx)@4-;p$B%L7@3#0>7 z1Qw|f>YqINhY}iCpKYYCh5GSsaLwiJ_lJId;oi}r=U1-jCFhiSD^@!Esxm;XzB-d} zzQ*Cis`I;7dV@Wq1Aq2kJFW!(-2Q1O_npfWr3rF0Gy|CvsxPDXG~7F&>3!e*koxcL zcL!_kU(;jMvv12R-Fq}x}O#^|JWZm{Stc%@$jXo#aheO z{SjK>wv4&7d7>3~bDUl{vg+tIuMX%ePO|{3jQbZ$jQsf)4w(a(;kL%b+tl+~nv}3D zv?tcPAS`5K;B;OtGQcvH)4Q582m-@4m;@iwhx9s^AkU@{#%P!VZ8zNL(ZT!3kYmFz z>Yp$dLon;Y{sGb|bOdCC3S)doA1donoL&v9WL4mWvX)I_)&&h4W&ks-UOUH4&XsGw z3mPWK`Z7oASv<*+2=Hdz!+p4hS8-6DD zu6sU=DQHKe2)ZujsX!<-+pl_5wgAXeRW+sdaXaiHC1%S@Mp=jBZfyDlaC3fo{Eauy za`Ufgk9BDW!vCxZk{oU9vgq6i5kdV{D_Q2KDUuzl?w9=}>}4@?={=qX)8s$uj`wk! zXAaN_K6e+UEsL_I?^lg8_16l9lp@%uhW>2P&CSi69mBjZ6D5LKjoXgfKKH;OQdXvc zs;9`Xd1~gw*I4A#ji*IV-BI-MoK2UhdDn_b|CVs~Pp8@Ic`BRRlN!&g1_g#lgHwT( zEf1q-R789=RACt%@bG(r+fBB)d*Wo{_xP#87V1B9I}ekdYyUu}A*y$Cs$7 zi2hSqc+)}x!>7OD-sw)`?ByxMH~y8l@2@{!RxwrPhc?{CWQ=|e)Ku}&a_^oGqIrWk zAA=@PLf+5p$Hy*sc*e|JiD+oBGZIEOEQkAw;xcC*-^c<9h`nU*NNZ1~*1qcz7?fIn zjKNX)+e!&3QvsoRCEs@->3iz=Elv1(eU@88Smde5`-cn93AYqr36r0+!~hNVl?zSR z0Pn1hCis-JlR6Kznu!|S=r}DIWr0Avg+jgeTWfPWvnfi>Ws9YkIryUA0T0>QpLr3= z_r)VETB4+k&I_1h9@Ec26$|j!95;-1qJDn}ZPg|HV;kJ)$59S(`JaI&Ke?xdbYAK# zfrrlAPw_bskN5wlWbxl2*0ix@9pfYCNCWNQIs>SgZz{=@K5cqXZ}NA&v9yE)N}BQvqm){*B5IHM!OaN1^in$xDKiT zb{}NqjiMEE>o8MG+1z@w9_zX~MEk+LhBKwGK6R9`wKv;Vbx=tfHhB=G9C&zMw9te5 zZ>3;%(2>$$Sqgnu_5(+_zC(!m@-oa)FJ*RS-b)CS4fDRr8bWcqNXMx)2ksPYy+~i4 zSqH82W_FjKPO^keit1g{Zi50ry6QTh*8GW@ppZ*%^Rk^yq5KMTt&`|*{wxTNn3Nn)$07;H<$&s zb-bO47ARCi$F1hKZ*jsVm(rKm!1q?qXK(fe`s4w+>U`uH>dHW>*vbTccTX>xK&hfN z60|BMjX)n$q)3LMBA&`pkPk%Lgj>YYGw?qr3_7Zmq5^#asvYKHY>#z1?&TVr_mG`9 zzH>2xM?1HalmmT+J@*A##lx2)8)|p`fi|du`L^C*mf-O&n#EpE(QJSRUgudx)}oIA zP}%TQ?oW1jpid<7g^tYSGIwJ5c$VVQ#N7!bD!za>Du13lHyxWOi8cPg# zd~|cv`a}OE*N4jldzK*#tTh}t<&nx&){uD@C0uE&_YM@j6g5pWIS2muB9VQJIN@3; z(>>$#X+NXh`5m!&jTp1-$K|H-2vR+E@Wby#4>h`=XYZRd4G&dnE%bHIMz#?qV%DOI zOwbE??;q@g*d19+cCLCUTHerHOYH$3IV!A%%;^r_Ueds{{4-iw6$5Jeyc1FMB))Pq zrg;N1x5fo6m0xVv_25o6E_lxG93h)+v;`^`I__bEii8lNt8r;liw$`}^p`BJTH^gC z$5bE9U$S?8&57N;^^>z2|0lOIaob8U9Y8r~cm!By5B>JT=#yM7TTpg$`&wck`tfm9 zRy1VfmR->nl$5=unbEK|5#H5M0E&sN+-3|KS~qJWF&CpSEtv7Vzc8uc!A0_z?Z?!B z$GiWqUok8DiIEpE8-b?oFIeuT0RP>wBt&O)eOsMzjVr4)q~QL3N|~tN4mZ7j+75dF z23pwf-DUsRSh7d(zs@abo9kBH(^alVrxArGzr06w`3#j|8_R+QbM4>*s)bh;-JU+D zl@Ib_dk1_Tsay}C0^$#viM_(>T@!M@XYPf+)^g)mLL(dZh!M4(mi$P5DXRbW`F7h_ zF_6dkBko4>48W=2eDE=n`PK#bAP|08RJ1$R^R)ZDtC)~Ca5GP>iKss(&M!azW!z{} z6b!xoz@y#Ya!aA8!*P(zSF|`#>Kl%_h z=X5-O3v&16KNl*TzAt1+hF)9##yo&LbI9-;aX)(B{v%F}8sM!6W)w^-!!0H9IeIZV zQl&mlrLej0Abp0ef7|JjV&Q8ro+9`q9c%y6K++C zLxzJF&mP3M85tekEcSj)Qi_2BC6(&z&ln|FYD{&K&^9d7lItffp9zD3{P zZ+L0yHT&!Dv%jGiX^`*{8ucG1s~w5HzfZmkT+ZO6wQXx$-hgK;9FGFE9{Ns2#=sq{ z!S&>Rt+We_U!*s_iThNk8Uaxcp$9R=qS_?EbekoTgzyg1UewCc%rELH&o>xY({VL~ z3w$Pd_T`w2$xBSV9eJD&2v2dI=F4bYnL7pjFymG$BBV5r3TLR|CnqF3vJ&%pKhG4; zb00Ql4S`AyU?zlKJUYJ^I$bLbJm6B7GETmSJ)&>iO@0Q=WBHWtwPmyWFUf_EzQ8=j zI&+wiKX0C@9BKfCWSJE#J()XoR@nW*Ljdkk@z@?RI8U%QBu_kEqG1T7-x#!xUTUm@ zQ5?&RM6d(sdGn)lmC&bA%-!V0ck8L54Zjde6>x|FiE!Utz#=VLq1+U#CV9Z%Q}?UwwxLVmk!N?+eL89bt5Gdu5L$s^zEIpc4T zOU!I6ri}`y3;01WvtcUGg9xJ|bHqNDwy#Yk=JBuXBJ9M-vOT+<*w-Z=ZPW8Mbw{{* z>-F;K6!Ao^mp+sV{3*6F=%w(E=J92}^L3iH^U#%iw1f9pNo+>e%3v{^wn!;)e`dtCmbMNUn ze|mWZ)m!x;4L|woUPv>vU}@pzA_Qz`AkgKwQ%(NyLwliRvoH$_3{a928AimllyNQ% zUaJIX8>X20OJvZR=TSd^zw>U-N!nRMXF)E9ht1zL&u%qs{ZVJ7KG_#yDP=X!p3uF_ z7(MAY*JT#c6>bn2{O3WK&*^4X-94gAIVU6^emyQ|Y)QS}PqvdgRtPB#YJrWB?{0hL zzW>f6M#WWoK+oQ9hsWP@J67||a`G#}C!N%r0q|7*FW>#ybbegjJ)f17@c6&aJoZEy z*7~=#FSMeT8;-Ewoas6re{PtyHBt`-;iHg)$e_KJ?VG08|EA(KVc7vG<9TY>75gke%D9}2eDTzLjjyh{4sGLQQbX{n7G3pg7k@Zjn@`WSJl&#mgW zTz^XLNPjzjuY}Dlui_{a_VGt+XXL?WGb`ah0!0(!{f5z|1{KyWsnbg!2JWv9d}U`T z37aCyoNtIlYJG{$OpHHX4fCkR1;{*V>Y;W^ANrJNHhk&X?=EB3M$>|)O<-dPPQ1<4 zVj@+ri{pU#R{9ZQmChOpFPsMc8p*iS-z9ethQ6160Bw#P`P7u;Qwcyn>_ z^8pg+$Sz+5Z3)jzU2^dkd?ZimR*QNCR{5bR(UY~da|lQJo~)G-IeyTr{A2>I#L=w1 zqvgGV(U;|Zn#CdXhxfn(b4$GQ%g49Vqzji&(~JM#11-q?aPZS$+;-vr&c74{O&NiG z$m>&=VBfuawzgjen5{oLQ@B+4e(CU@)|5cM#KWk^Jmo+02UQ^VBY~CVaN5U6IL@Y5 zG^qo)wb%SkKuoEjsAV?r2-xGtYUEG=JvChrGCjciuCE~~y72I`IShAS#p9g%sn4|A zK{lr$Beh0x+QXc0fhnGO=}Tu#&ZL|aSg&Fnq78|GLaoj+|)Z{L8d9v|OSLAK_@$D?>?b&%P`^NW$+sD*{Kji5}(0WB08cmNi2E?i3q4r3P*>jSC zkziGP1g(eP53p2JXIu#XqDuDkZ033ttyvSSU&1$Bx>i0?mcD)g!7Mu4IL`@50`-Gm z#V+$ZY{c&;3(r4L`d^11ymF($kIrp)nx*VidkfD?3Kz~HOd99gzIQNS`r8k*=C-Y; zp960+AAhbhFR2rp|3J=i-E;c+n9}$W!1TPhie(Q6**oRY(9bif0X`(f7(D&v5);un zE02ZKyeT~*6I;;!}p z&pMqb9vhj>9t!FHR>HB3E)AeKL!UbhPD zM0_VtNH#M)%0;=6jNd03maWN2X)IVuZtXtx$w&b7ZQype!l((IRe7xB=buZK9R0`~ZBm zxjBDv?~mcngf8qa#-`9V@OJB-{J^UmFtx&O3?Y({rTWK6r_AP&7h+vKGE;jP^nqm& z7?4+Q%yr!|TpShu0eOTuVw*s6D~#RhOqoMG+z7}#{^fo3KvqAsc~qH zaL>f7_m?=-2T8Y;IhDt!BRW%kPO1j^{DX()!?^#Rq0vUN53nW6l=lp&p40Q6|2F_l zi7ttw{Mm!$yAyYApZKry=F*?z%5haqL}sI5=lQ8$=1JS+k6Kn4A*3RNgP#XOlW8`&KF z%J}UzqAmn+Jbso-EtMI?v8@r_Xhg`gOjz#qSM+5-?gplroBGrdSRlin&;Az zB+bUeRDK!(sj5VG73+_3dAB97OZv;lQW?jiDp{cy{7wa)yllzgzUuCgbk1Wv^qC^= ziPt+1tS2nb?O3F5TM;ZDq+&qQx+awv*%{qoMF3kRdpq^*a^1%%^1=iqCVTO?(e-tZ zs@&J*hasj3RT~haLkr>})zmjXcauM$m_Oq`zH54O?#-L8p$j?WO``Y5gE+H1yaA(N z;D>6tY_yE|KuF39&BwL-*K*_M*1YGl^3M5`nW|V|wG%YRdS1n|3 z#ZCX-y}^fGSyT5%y2!+PB&6qmD8DyYC6}vurAr%6G|_Lt{R)%LY5qME^>3L!&s(Ew zv%!Xnl+w-t*O0H-VArGIxIQBTqqQl@AYWOuvG%s>aBircUJcTEP#Md>Ncnc!cl*v5LG#`XRO4^NN&I!a}9Sy$n1 z;LafbMwDuZcQR$J8f_ZVV?FKO7i@p+uB5w1vhtOk4POmfKdkOIlKOsf)q|I625nlV zH5nB+ROS9%OIKSv!OJ9l`Oea#SRotmHtjDNC;E%2e2<|!->qk7_?FZ^I(MdU%3>hFi$2HG4_ zTnt?by*F=h-QUu-+}gH1O!oFeYK%L`n^=#bzbt|)G+v==;haQ-yjXcE`g^wqQZF~ zNo$a2>x|!2Ol6jDzfsT&xMX?T*Y{|r&3AvY@t7u$0i?ny$o3WfYc;GEx1PRVdM88a z`l|NY^2h=1_mxlg9VOWhta`Ts8RacGwgoL>y3~e$)4QmK{A1;PTrm_9j z&)O~ansV-~Rn1$~yuYCwRy}keu=eC;&5#uB6QIhE(0aiGb0|y}pOpqCDYoS0_io_k zQkS`4F=OnlH)#DX1(#<|yUsAzN_|jwNRHcZPL*y%5NHu{d{lY21f&~ocX6i_Shm^e z^~M`}9lvB;XAr+T^}XFS+Y%PC7R_*{ zuVT{CWz$*0sGTlX_shYP<-)gwA8rHI(yk$v%nv!*xIG1aHR`fpf4yI&Q}&&L3zezV zi>HU}Z?neTly3FCah+|@KLd_3SiN0_Cp+Gp@qdB~4QcR@21+#-|KZoKRF}A!*wlALYKgOV$=oDTqTTEk^oLT*9mzI~hu>QZws)A$DyV$Pgq|Ua zYdZ35E%20Ja|4wspau<7F?;8C+Gb{KX5=L{;8jC zwe>O5Rz}Ae@b$xY*ITL^8*ncgz~qI?EY`kd;(&gm^7HN%qvdIxlnR~nasR~Li7Xq` z@ujKSaGWm;F3Zkt|lr&nBwS`f6v ze-H=;fT6G^Zdl|TYD$eErt)*G32(nImarVK|obJoh zsL=EajJKb@jl3qs*ZmbIugddx4@8_ey4f9>CrVpJ%^skCHY9s$hMZ+NaMA!fs&Bf# z`iMTimMYe5nlB2EB+5gRtI`T{ptf&0z%IRd?oCCM=Gvli_u?C%P8#QE22-oC4I&?C z1Wp><3al5%Y}|IqZfU*1J!`0X{_X&XRoWP7YXQZS?I1(~#e($;eR1)aR$14Oi5q2< z&#QT_Hjn&RddU?f`NrgCRJ8agvTs$PPp>x~E~<)p2obehRlvSt{T9)Yp7KnsY&@)X zJJ=nlJU6#tYLfYiMP_^ubqT)^vU8&Sy7BR9u;_(j?^FB_UhS%XS%RlhyGko}wdM+; zNwZ_{;8^CCt4$WD>xSgj4o9X^VxFQ+$X;4(E2 zAhm#pI!i8j-)rP=E@{r0cX3abGz=f$ToX#A2p4`tb=U$m&07x$K7?$8C`~sD;QY7T z`P`4w4j%kxl>od-IxRBAJ^3J;GyC;Q zw8#vhu(SNl_mxh_168cl%3$OmTRs@DmKv`^(IM##xHXhQ;&pnJ+RJ*3E_gaWcT-F0 zAziIfilOeMzdVU=vVM8(o6Otxj<9GUcD7k$6TAm$8I+-9z1<3A#Dz!Xus8YhRn8Gz7iwV zfD?QXT&2cbw0IemnOk+lMFHVp+;OKU>fneOj(YV8E+v(`4w7TR->l3RpCkLS z{u7<5>dL^RDCwyqAF8OUa4Q?(YfAAtO#60m>(>ay{7PAgn?LPu2hXUL;zLtSep-LW ze2N{H>W4`tnk5>|^u7VK_~|1hUx0&FD==JDUb>?FV^y-m+|h zTd@UP_D;N4d>?VFUF)s?NgRSUJ0MT@I$`f~j z6?yA6x@DW9Z*?pvN%)>`V5CjT+N4ZofLC%SlR4I(C)cr?9Tt z8N)tJ$|43gu}g}D(a|bsp&RUwX7*}LOhfe!Jn9$cEG8NKD<1gZL4tDSzqMVDAl`LF zl-`$SRWt^vwAPat-S8D4_kwD~Fm7Fc`%j{^0$_KwA?NP_IKFe@4D1?qmSa!-OYaEY zqKrEXv%KYRHo2KGUCL7UXu#ZrixP-6^Q>NKN&ni!+B|H{EWObV#x zDy1A=_$w1dT~d0X11GEdX{v&1|@j*ON)*&#c%=jeE_%VhIVm)g1B%+ya1$fFo! zk4e!oN8P`SZF0Oq@>Yu>rXGz6F0=6M->h(}6#XDc`dxQYzTyeyjh8^-yo$%!BG0Pi z$f@-Tmt|sb%Our}wXY#nObL0MFx|dogQ|;cL?1_MZ*Na2H)vHK!w}0hzC`A%L$o$@ z3Rl{$>|Y>%yuRF0DDgJA?uF_pZLlSH)BOuHUDuH2T)2RKY?N(sk-mK&HnNpXf^SoHANRPPZ%@UVscabpz^~WXJ6eqP3_jm z0B=h~G=ycy=6n%VVIN#T$+R0i=ZDY2mp1ve6>?%|6W`glC+T6enh(U@@+&W_16!ig z1hr4f*8VLXK;|a{T4e8I&l}dTm%!u+Ps!;<&Vjs+q{`9B`CKt||99Wg2*d{M;g8@d zZImhJ_R^K6!n)ubw?er2@BTtgi;n^nItDXwUuB{b zn7;5M#w4jf-hBV{j-{K|`T(wD)MzVPeCX>zz}N?r3y!AhtvS2VCSB2PdJ&KM(GZ1mqz zRod~YKjo!oLDTQ&VPQE9Tj9ooIy>M*S@TIbHsS5}i}fkb*Q0+SGLZRv-R=BWp7fSC zpt;@g@95REU7!P>Md$rJ0Zy9pn4sW)KDP8R=hAFlwr{WXnJ zPX8yjNi1YMg89mCY018Ty|ZbrW{w4ld`dOe`ZBmzfTQuaPZ0g3olx%CoLb z$UiT926`U2bJrGcX{(q*ySh>A{HqD}p3`d8xrLowZoErv--*~Jmdf=0UM>6k=fZ!6 z>2B4_IT;sqNlIPmAN~(b?;X~}_rwc-t=Lfz5dl#UktRX}q((&qX%Ud#rHPc#Yl@19 zbm^T~C{jc3B+@&P-iZ);PXeSTm*4x|`^R}^_q1ov&g`=@XXbo{M!aUBmXr1i|I@81 zIn=*EQ1SL5lpgoQ7%uUa>led1Dq{`W@*7Arwy3tTR;$oA3QUxVn|nh!%Wv=X)+Wo| zva^vDMVYPd=FlY1eM@vzE#^!aye~f-+v-uRn@Lqt+BvcN7zR0!S#d>06blM0*IRQg zwKt^5o!Z^6Ff(Ibzidhg*@qrQYaSaEm?o<1%cK2>AT1%f`w|^dT}S(p9^`(oUhSy0W^m(Y$ZX zlz^kyjy1KScOVuc7`*@?{VaaNg_?-G#ZHYQ#Q+v3%=yH_0lcAvu2Bxj8 z-7sQ)x6b(Oa&p^+0KvA+((=m6zQNz$(u0od!<_He50s>xv6QUf;3nvR`|||FhX@9$ z@||Ce(;HJR6nCzSCtIqf_NS(37gHd1h2@ovS)~dT@nkK^_=rJ{XtZqJ%5jjNM5VVB zca(PXtpfA%LEx7_35iL~6sZ@}+foi%lD;B>#@*n%lJ0kC#OL?r4=zFVasKZ(BBCWYR0?rc((CzE3b#J$ zM&&PC`o%fMSJ)c#;YxPESr(z@BBpdJOPu@MfM=sSsjLn?UMdW^d5YB)(?2lxEv`=(Y$wuDoj#yaz6-nYj-%oVi}$F~%LS(>;ItCOEX@ zM7f`-E|_gg62b0>r$HCbrYNz;uWsf9P_`pX{&be{V*BeDwVwg%JBA%9gU-_qy#e<_ z2PhS(tx?<|5J$cpcw1dVK7Mjq(d}AO>M?ZIL8LcJjWrqn6;nIee;^7w;rvu{mSdn(2*pym@J1uvdo-z8%L67rCAqvQq!H6 z!Z%WfWhia%=e{*pcYBArK{P7;4GIC{489LbgBg0z0I0#_Z6o`2Tq?^3y7uc5u;z?Ty8P6`BFs>ojRPVRqn$uk-6^4`i%GSL z$gb(lhGcai^4O}0jAiw49oQUN{YzCuI+-~Ax?_?lt=A{dlw5YL`M}7u5z00=m4Li` zHR~0rN|qD8Fd#yKQMFUk$;-kW5}g12!^o3)P`mQ-)Xn158z8l+{S`>O%dq!o$Q2X_ zt2s0{`Lq5m>jt?Ze46Gizuetg@0!hXX&u6u^gx%LcxaZ zEx0Np^P}NQnE=)a2z>L%MGpSu;k`tl8gDKHhjp6R1mQ5|j8XDv5&Rb1{O}a;FVj!Y z6xI&3qj1s{`Vs#yX0R2k^Xf>!zVk!Ib>`RzXb~jYlFUvl*w!qeKk?I&dQOpMX#ggk ziNRm;>#cx>?Zn_;P~B~D6mUlAf1?!Qm`xT?Z7s7Gp?e|;c!yc&)cbL%*kXkH>>M!p zn!JJ{JEA}v9D#WPe+^k;y-!)>Bzv(;s`&5Z;ss(LZi6!LIPz-oq)0D|&Pz_h>XfMD zJDwy5Mjb!xU7O-d^X~?G!7pn-JYVxv|GYT1D=UE=>B6e~pN>QQW zi#*gHz%i@p8~o8is#KFG%4r#tWYIl&!qKCNq#v!{Xm z>UE%^)Y=*xUr3ZVYg^3*;*o$8>~7z^R1Ord>}410Q3_ z@F+OKE*}@r2_|vNZ`Q=75z-CUU93RS7#631jFXDWYluzu%wS01OuNO);!)eU zmKL-hg|8v0s4NWxLcrv}owv2ahIqe^Ye3apNaKFCIy4CwuxGbMs}ca3Q>seo1w`j5 zX74gcswErPjsFz}oW%c1KEC>q3#$SXf9`h!xnO zPsa&}!kIXMP9Xm1%!>RLeJiFMeupV11mE3Z>x-lBE!wQ&Fet`T3Q>wBirsu+mqG>N z2?)ZP4NMEwAPZof{y?bN&;p89>9oFuq``*dB5u$Vr4R{_*?Yb-bmDTqKyLy6*(W?h z3nwaw&U+tDvzGfs3e4b*JPk3X0d?jzR4b4&$6DM8W&ESN_BX!MXXhPOXNnG#@hSH^ z$E_~dK;Ian2iHW~<-Y(ZFt~GhP0yF@?psZ?(5CtM?u>b#+0ay*306p1JRTx7#14sD zBS{x_bXOaUHhjVok5&raPKNnhrJV8B2d^ce<8)BFgoov^Hub|e?4#^Md~A$B!y;!H zSLO6IcspnJ{jtkeNTH7eSW6TwVQv0)5vUM6B?)Htp22RzL9^B4u( zIooOB3;cGlClYJ1_b-CFO%J*tfI~bWULkX50rox#K&@4(6>nw{TxmZ7ef!W9cXQq< zVH4Gog(>#V*=-8N{Vt&(thm*uCnbbhaq`7)eEXPl*m# zn(5q(AOlnd^r-CDRqn%|NoCFLV>+FQ4dRlEpK1lIV|=jBM?hS>19|P$Zm5Ioo|sj^ z01(bEH?gMdsP?hrNw8DN4Dh=@hX}ujV?d5H%9JXpI*5(mxJmvcWAegBM%D07Go3hp z#p2_^Wb!G^U3Y)rYP5W|0C7)*Z@a=wclH>}WN{OGAJr(H`|IDYzrH)27Xz?054+|8V1Nb%%eX`f9B?|#Vt)Z|GPLj z9DHJ^WuC1sMo%%7P{Vme0jv&8G^BKSY^^N=m|w)&{PQnxKo;!wEA}^@ZS9VZSS{<& z<p&Om-)wF9Txs?M9LtxMjX`c|c5^oq*Fx{uoIrEIx@R-x7=z1f zDqvFSzFJ(s&RqOpFPSc9xVj3>0#}6aSR7p%*|(>uj`%l-81IBhGn~oZwYLvXzA_=F zLmI;G*Opi=s&413k#22yyqpw;bpc(Q*|Zu@4F1~-oZH%M^r{oA>9VlX4#Z@%k*J%a z?B3iC^N{n;X)Ar!tzVYP9wJmIO*)4$AJfi^WzO(l+tR*0^j*m=pa~uqqEa+@_O2Ch zvbJ%Q#B!)wu{nS3iwOUtD#s?*EJ);)yO~mok}W`SZ~0(gNvx@! z6B2$&x3WSKNGHskA9VmF?1*SR;D?KnyHfI*nH8t1-Plv)U@HC)Bc!yS(+fMC{9F0I zc|t1`vULZknT6^2Ax~li>UOSBo)>p$?$56+Q+lNsO`GP|PkTS)#l%K-M<2{Z4OCSkvG_Kk{p)R+l; z(xNn+`Vm-TQ#+2NC?6wgOXtPU{+QkLDU3jjvj}`Nay;v89MIegEHyuDWkZ+Ney`TY ztzBGPoHx!v@@eW&;gOQ!o=Ayu?ay0*pz1AcSp$UUnKqISOK(iEB$1_M<(l5E+S(Ml zxt&X4l2q9WPe6@n-~Mw8OLM#ERJO+NiMT{+Qnwpwk8vi zc_X*_g=nne|2exG8{2NW7Q2Qy8mA?nj8g1p2S==c!?@o1mA*0W<4QHN^X`|}X)}nG z=BcZ%Ou={xDtE%&mIuf65PjVKS&L!DyTMWVjf>XGQclqjhLC?^Z63Sv#N`@BEQ2qJ z9S~(wNE)1aV+oNG@4xu#p9npmtEH$IbY*H|Xa`bO?z^`95<-*oq=2BxcA-evfreb0 zI*NcBy0~Ke`wjSlO+#WG6!lf=$0F_Jd1lJUlt+xN{7-gMPm@M*?X_AuYBx>7hbO`!c7 zSxmJFt``ahkw}gU7E;P$a&gOQ9rU03OVk%%xV5B#E8$PKJnZ9Zp31ou2B+>SPv0^) z{R$Tn;x;I5121XX6xhVcyrpSD3ZB9A`|B?Mx5SJdWZ7?XTxKEYkzvYgz@6K@CG=`} z(@{!X5q%bUZLkm2bPgyE+_{mw#L0>$KB=h015`;W$2C6x0Qh!=EYoRn<3W{WSpQNu z;0ZpG2wHkJ*hLxzuBr0EJs7;Kcpvn#CQf{iHfmk|9~MCpR_jP*iZc`h1ocrslG?dG zk%D1>`c-@$>m__B+%yTuQoG$pIz}cIqzpbpi%#u->b!`_>R_gKS}$5pwsbYSYZBR@ z=$fg0f8=HJ(&=dz`gF)sCHT>89fBm28yCw5Sa>c>AyzY=*wDbyB1#~pEZl!y9ddv^ zXY#{&jYdQ*YZ07xgY6+ByKBJ_&Wpt!wzVP>#wZ}o@Ugf+WTGFtry_7RvnUyvi5Z&{ z!mh$St`c9#u-UL&BH6!RSN&~ct*4*>WZZHP1L_U_e%@C{M)n)qT!61GVY)E&XEM4F z734o_BNn3QRYWyil%C!%fCm}F5LBCAyun1G^E)*F9&p=Wr~_dJ{|qz~b|5(aKHUeR zA~WB@{F&RU@|=7&P{g4 zn(k;$G9nEGi8`m*lbj?Yp}}4DfdqZK8DP^j`D3yrSbj&y*O2Uv%2q_h7yRx#P;k_3+SB3nq)^Xso*=a|JE z9Ff7*mGPHtjB_xYFKzVBX2gSy_k*vcGCs?-k_x4gMSDdkO9;%R;3`L87={(}w*r{gm2%fq+deKjPRrhJH~J0*;5xzkwa$j|KD%@Hv2BDDXoY)>pf6N#xuoU&0PZ zLqrS3;F$ej;JtYzVKr({h9gWO3D|i#YZ(zp8yiB{U;NvLfYRO&4sXh{jxvwc=cCMI zWVCa>T>}j!tH7x2Eol=KTr|1m@dy&Wj^Y^Qi-%;@1TJ%*0vSR{bX!*N?ETRBYQ$2VwsuF*m*;`<9o|!d@ zJdH(wsmcE^3XDpkGXnOCd7UL?MiW>^3;PF@n8p3ad{%ZHMLue15=NaAFWdUsZ8H)U z1vwALLjsfr&*)bTAsN2SA%qj*Fcn{LIPl{;-%iIF{x}eChIw+$i~t(og6!;v ziR-_)%{tp0h#uQ$q#KUpSvs@q(M1m>V4_?-m#*-^U+ieGa~Q50qab~bbTbFomn?#rc-m;# z$^D?eKM$o3Z=i2wxOLrND*OJ!UgzIau6auNF^N`PAHbb_j-RwD3qG_(&id80gp?g< z$mFqUFGh(os$M)LcYN$B^AG>#^85zVGVBp#1-)2VQk@RHc?Us**Z+}GcD?=uqg_a6 z|9bKTpfJaT1Y!QZn<&*rEP(t(Ml=%r2c%xyK*$^CXyf1I0Aafqu>4V=u%(DQReyNr z6Zey~uK|TW71I0Zu)Rx1LbH}FH^w$$a76PW4l26EGc=1@{*RtA=_0dYF=e7$d}1>~ z?hsgB%2GJwa=L})erenv;v*h(Mb&VRkN&qfKqaBb(l+|8<0%aDb*Y;`Ll(pS1;L6v}_9}&0;F-LI*`D zrvf*UT2)#MXKPgK<>*Nfrs)2&PO5C$TR>TKjpRb`=}^z^YAdIH`uPX0d~Q@_VOF2R z3IK*Xp$1$FC|!PHvj8;#*ls|ylSDI4hg|O0{`XbNY5ONp8u>N!V^GWhHevQQhX#bp zv#C?|PyX_%sPEJY^d={OqJmth;B&i&sE`ls{60}UjUe!<*6GjE{K_UT(HwWE&DJ*i z6jfJQ*iDvpJG<-P0ZC~y>*L|1+YHtrpYY~tV0PDv9;@PF+aWhCb-y=l2!ujk{zWQ? zYqCR@-R&2;$%|-4K<6&YtRIn(OY>sz?&<1Sn*nL)U&1!2b&6qn7 zZ6y3H-P%O)KQ2oKKd*7%#1WYLqBrNCd?5a%%0`1A>dFM{ghVf9AC@S!$}Lr(`yJTYP;Xc{^`b*&$I|)KdV|RL^*8Pv zp5Xg_vxc_3XzXRD*iZOOMYH1!J!k$|`#gOAaWB8}=EKb^3qR1o@>3>E*UxN#YvaGX zXN@#ke`){dXV}wdlF;`VL6`1OhH1aPD$Is|eSk&K?mSs?ZehIw_TRW@}x=Uo}l}1H56r1JT}V%#;-T~O{|AX5Qa+=( zhG~1r`~ZQ6d|54^yr1Yp-{52U?;T*y8^Y+cac6g4o`|ZzJ`jYJ4(XY!ffz*)Bn6&6 z@9~l$ApVK4>;!;?ZMXeKANO?vcpxyn;FmBZ|CF(K0UE5rQd5VKBDE4#d>Vug)1V6} zn;}B0_T|aGmJsSQ(AQH8NyM`3m?&iUoW!I3Gez=Hx8PZR|BRsfO0SmrvC#sTD0h3S1Cqyk(Bg=>Gbp^tgyjq^626wy1Pe$&vA&j2ivrZ&k11m7Vo(Uml)W z#Jvkw(qNnaTc=aE`%Iq_%Fv!9pe|MbfyD$t7crJhxht%Rrd zr)j)y8|{B}7@z^=V|eb)<#oUN3#QV$%alKl{IyXSB62p5Sz@s%TyBtC?(17kF)XuPQtpk0FC%AAbRt!eC`H} zQ9JH+$g5P3@@NR29Fv4@tPxGFgm2Zkw!;S*`!BbbWFuy$)CTvkU*Lc){<-}+*y*P> zwxH|ajqWal>gJWwQRL75FcZ(o1JafhN0!2>y8mT{?3M{zZ$EW13l>bCZ!Tx0ssu3p zHbzmuOk_8CclOzSxEvRBm-0Gs*2I2+1u+kFhi-^56k?L`#ruN?oTRvRqqV<&;+YFQ z?)hlmI!wkUu}1@E{FL?OTtFWE$Mb`b$^aMnQ2{*(N**Nx{U&Jr{505P8`M`z4S$uUOmD371pUmW~EQ9Yp$L-|64B3{bTlRaPDK7T=4Y2WgW-|G=AMSbD zI=fd!O9_0V&vxb=Y-#?9ZXNHPG64nyKH?DgzV!?b?Gns@@rv&%qvNnHxrs^Y87#wY zcOCpFaW&FV==I8?E0s&nOdQ6MYesAvcuw)P&JNl~Pl*HT1sM5-GDQ=eqfiLdKuxb1#-I;U7Cwicnl?d>j75u&OJME~^f6mU3nY zz@aYuPy9(agXE)Mhim9wdi~a@NH??Z)daH1z9F5_MLoi#2)@M_txVo!a0@8LTJupZ>$T_fH|S0<;}+B7 zD~adyQgp;NyDS<8DY94GPunlrYZ$@f>n`e$?UH(!i9vyG?^)QuKsOJdsmA7{!Q%;^ zU^{!{P0DYbzpob+-F|Z1I?A+y$JlgEtnmk5asiqeZ9aSKbpk|KoHqw5D;z_HVF10-I zDEto8;ihFFm{*>01w2YA^(?vEJ?#lOoj5;pA$0tJ%IULZY;Lo0$zJYK590k7=RWVW zSm%WL2NunDXnO%U(I@@w=sGCXYc){^D-o-hJ%&=3Gx7Ozny!C-{v>zz?ic$MpYtS6 zjE#gGvEWeoDfwaMmY??lw0|9BS&FgPbbVZ$$Q~iji|C&;4Y#mr-8#HniE8Dtm$E$F z&FB)~@|a76*sOQRdOJ-U#m6R)46Fdu;AH`wvH1$Lq`H4EQy_rJ z3dr_;yoHrr{5I9O_2yXu?BLHk2{W{EW8tHr!>S*xdAeWzR{rqQeM>AqRMRY-!OeQ19O#soPs*Tm_CY+QX$M3mYk>Ruzy}tkGSzb!s{4#? zzdsknX;W6xZj=eFjD$SGcYUF__l@kxYpbu!xGy-Zm>4$~A|Li2*heL6bWht4+!o2- zbx-kViiDKQhcwrj;YT@wqJc9D)?x(rYv{wkhebW0S@>)$-mHKZ=tqkliu2tGbev9i z*~kdALbjA(vyILCm2_$dX~FLigMp(*q^iEk*{bo%#0pqupgZm1tdmBPi2I844mM$b zvCKCKTlNdzVA$Cm(Xuy1`@T_CZB%v}5%p#)N3shuJQ`(&!r=!65ni+X@AZYf7;-cS~kgvyROq!{eVOMH(snk zRhO=W!Z?-g=^bYnFH0AAi{=F3FZpS^CVyn{rn$vHY!|7J;&=Zb5qEc5z>s63YWCOB zhJijjgV7@V18Ey_Tg!qnkfOCb3CrPdLujfW4LJ3ULf=s_+ZOq-Mk}X^Jfp|3ql&4c z$%6pbPdn6i3Tnq0YwEzpvPigM>k%_IbRMQy3hJbZ6fEsDja53wN!f!6d*HK(p%;y2 zn7Q$5hv5eJqrc3wqfxw5%UinZ1dNM|#5y=FZ~W0@a>~fMJe6mtjI@mse{Xtj>n<{vdA1_J(j~ERhThAEp;Z%&7X2acLrx0Hx`Cg zI4*5NZAH<8<{fT|Lpf0~WxHsziHV;}KCyyBss(?O<&K=pGh+c;pTRXfPV}lZEB?vp zdqX)PN)dn^PKm`^J1$EyDP{Aq`L~Zy_Tc*nmsB0jkS=f)k6h#ESHM)Oj%dMkXYT~dW>YsW8C}3 z$hs)ze7DnV)mlyUdsSzV*=cJ`?eD+_MGUheop{G8zhG%avDN>a*J^Nb%fcg{g56WJ zw5)^9>W?ZgnRVr>ZU__o%naQ8sL^uO(VBzo(Gz=8CKNSlw{agTx24|1xV3f^d(&MX z-!Oip5TxVsY`la&8r~~cKH1*oj|=v)try}v{AGZL_V3CYzO=tQ!ddbMF~LRbv~GGg zoib%EnMuuh%(g{V=qlq(;&#i{8*{p!7MyOcDU&9fcttgcPnLO0vpaLkJZi?VYU{n* zd+ey#du{#!N>neBrb$|xEG-?^s*<0@oDimcsIaHL)ELm2dgop#Jc;RwRS8Iw{p11y z$Zh*;#@gFsOK^VBs%I}MWEbMJ)E(3OwLKIUqIp^OxvXbpR%VE1VqDWMa&c3Pw?`oR zg5*Gehb}ywu~%8pGx0N{&fc{R#lH>nN=n)gS=zgp)gV75#?OJ^bM5tVL^dSuls}ld zQ5=X)qwg5gVG)A|;3|K>jy>eKtlB}DFo{eT7M{MR>DI*@=*Y(nJb5E_E5Ki=`fWQI zFxZEjUEKC{D42#+$_ItoaUJ!B0Px;}Uabpo!(39;G-U@mQyr>sC2eq5%HAf<#ongy zcUjb%X2xK~e05w)ZTW2Xw#`cn-NSH@)|pg1`Edr7E;Rrn%}5%)k)ER4R?Rj59t3(R zs-n|u>oU{T5^#NF`=$J%Kvo7mjgOTd>n^syyuYv;>U1dUDo{0F&{d1BHPh?}h|ho1 zEHH1or9TXFo+wLy0SnnVYOtk!iiG53P9+>x?xgv7KJ-MDEnB|m&cxG)BsG2;l($Gu zxheH}jU;@PcXx_o-QcRJ+K5_a&e}~^OiJ|1R`Rfp6dTk!yFrQ-JW7h|IL(5{RcQd* zj74VTDhoHgUF~Gwb`aq0A(L4#EpanbOTBim-rZ22x9<1v>_NUHOCMqA@Uzt7?s-++ z5nnjwV(qEql8?R_X51NsBv|V}d2TwcLT`*BuC@CkQ!&~k0KlI6DKt<^prguL0)Sc% zvcFfslL^Rhb3%h}yj>A3R11tz;Z82V(Z;9bTuUMb&;L$PoMC+5nZ{`pq~m`RHyH*P zHuiX@STCpOTL|A7>)Z`5%KH|D*4jI&_Xn6xU6m>+2e6WzEttX^bzEDn3;%pAz^EBk zb?TR7;XC+a``*vXHy@+YaN)Hoy6P)2@@Er?r7EzUh7rxthxsg-?T)CEi$#I+elQ>C zpDYs|MCQ(Dew>aqF7Z{SCWwVXzRH*ufC#&Ou=up&#B~h&1Z%04_5;_Vq+RmoGbkfJ zGuWC`YS6&~!-tvant;QJjeOS8-NDPXsb^*`@|g^J=*Db?<2$q1Y_7Sjot^bb=4bS?*OPzLg3%N7{P0-6the8`8XZet&hvZjf_9R1GoJ$j{D|2g` z(Q`#{a1PBfc7}|)tfm3wd%j(+y%?(1m|kHonicTrpdhzvmwg6R*3<&tv|W|3!kW=* zX{~&QN)@AJU04zGu_@Fm4@H&Ca(E)A+eHT(X`j}>X9as0u)79L2Jkv9egZw8-Ua03 z6UJC=*wW>3qmvddk1$H1J27I`Xxi8mbXJcQS(D!Ew2<~2x=mTVBkcYiq3bCL<@Z%N zJgj+0$Uw<3x4v&JpUuw5xsjJy({I2vuTj-60G=x-@#UN`Y6cyGeROkctd`8#lWHHY zWHR+P+>4~9nmuWi2HLf+8Zi5c67an<-}C|awYf=UPY0yj}IYp3&fogkY&*IUXa;MW6wMwUfQ9|HWg z4eh(*oB(VArbmMcISs~nZ<^t{JUI9KXuMo@_kq6f)Gm9il$eW#6-jhinpkAU`@zukvf$KO~lBa;{c3Mrh=HCXP zR#b!F)WdUE8l}!HuYbe`Z}_2d><@1KRo!eDIY{lbkIhuX>T3<1*PS11)ZbdShhD_# zDrE@AL6wKm0_PPQZ@2;3YZ19ij_F>%ajS-_7mXel=o*votCy?Nl{wGghz|bIm|)Aa ziaf>>(^po0InZ8Wl5MT&H+-nQPkBQt*yvJiroHP>L~XRu0@9_9TRc7V_5~O=GeI_g zNIny?npTDpjunAf|C`#bUIwh)Z2YgKEVJbfm$kP0#rIRIxwlqsg)}ZW<&5HNfV_40 zrY3&(pu9{2ahU#!e=YkF@Vij?PYmXhrD%I-R z)lMS&0w@FcE+cBAU9lo<)p%u-(V@6DPPt#KCZ=C@Y75t@D>lP6Dms4CB$Dj1JW6a) zEkKn0JS1H2&neD@?PqVCjdKV)gT?_DyO5hUYrogc|2ep)84L&en|vB7?oS)YuW+T({&;Q~fG>0G>TFe)4VU z#6L)kAXNysZB$SB@tFmHm8iP2pH758>0x1@Ww{dqbLkHduqUxqX!Fr<*VO1{ifuX|62=)df}=MfvT82E~< z$$SPp9$$KF4+VUhknVm5ieLv$T)jE6SF`X}Y*Gz*zP8vGlGjpkb~<}-0IRruI6oYG zQ4EiI3VRA}-IM${$I&zRQKInOwvHS#k@m?<`!l!NsgQ=JtJOMrZ+1UE)tj`?%D(NP z&vMh-p~_vxjx;sswu4&YG7rlaCW==lWd`yO2QpsH4*SdjlDA2Veh0Q|X(s1kb(-)D z)sbK)z71(&xGn8l0`ZHP9cto^P4Pn^_t?o*Q&bc2HCym%;J@`jbJL^Kvu{;CdK&m^ zm$%&G*E9N&({STAmrS2!yIC%Y@*Ncn2c1F5RGgOKb;}npXlmGKlv@P~yL0U-Ek4y> z%qQv^I$g#$+|d@EtKQv>)vj`}0&u^hd6XNy@#XVPie@}^T*rO)2p4Re`Lc_>>pJWD z=?UlYDT3^G(J^%!%*T_X)$Oqy0)v93vg`G7^FfUqiqf9SoR|KJ?#Liq7`;PvA~OS6 zZJmh%ock)QYJ=3oQ|IYR(mgChx<3O2IDr4hK@XmGH+qNRH4L0r1f0Cit^ z#bcPb*`Uc?c*`KnAdYh$>dfGkcONa=;+!6`8$Fbn%pV#0Wb2x|mVaaDLhbj08)u;{ zKHHZq9@UwW_1=O%S-2K3OIGl7js?)b0E)V;}Sat84Uj3}+ z(AQ(nBi=1mNUY$%Y6Wkd?~|3$0X|zAZP=GHdax2Gbo@gZrgl5fn28nXl_IkUM6@nu zFubs$wS)_x$?j4XTKm$hs({#@5`#-7kT*mvGJ*^cKv#=It5d<1avHsJp35vkKJP0a z{Pr2rLfS#Rdi+Ct)M97Aort}P!>HhI7eNg?ub848b%KY|xO0wdFF&vaJDvXRzN!%z z^YuWq2O3`>XoGsOyyJOx+GSbB0nyXhGi2MLAUPa_yj^UVJXcJHdyTp~@1p58QwP$~ z`8oHVNYCW8f8zb+D=5n;WTTs=ET=Y?wE({%?ERS=-S*3Lf0U|noj!!8fhNG`2{ei^ z{WU!x?l7c+($d;j)kbBQY>~dab?u|hPnUCULmO^TN=azf@hMN@r%r>#i7BuY8CsPr zLfgXyjrOo#IIbW0I&`S8;EP4J`6#LG4|4ACrqI(Y+7gA98 zAXg2^mur27tmP&u1W>ecsMk8j7Qri~)N`gQEm|M@j035g(OP^Qz~AXwpQYBX=%0S~ z9p7KszasrVEdM?c^@{#vcGDTRscImwHS`95$F<(^Y}5Ao`b{lB#@7i`w`%9d<`!a8 zQ=yjEVi!N#=Lg3?Gos71?mrke_4PL1O%taxeP2B`SQ<6oRG2LzJ^N_-*mC4g>eox+h+!GdSNw?QBg!s>aAT+>Abt$Lj2U@o=J)zh?fZ`- z&orKFI^`bWzKix$A4C0^Dcx*%9cB+Wu+SDZkcfJ-?mQal8v$#~pwB@t6Od7#{?4LT zp5PP@-8e>e0+x$7TS0Jkx8honmMg_x+{T($clm{$N=}BycN8QB1(ztRTn2`E@0IsO zvL*x_r+ZD&e)|J^V~@obm?|y!*}5gGU#<@&2o?xpm+I||OFsb9FC66XLRw(ma{8*y z4}HV-hh~?=3-{gHb-XX9yb_k3?Gx~=umiTnT%7`G2hZdd+@g%yAL7H?bvsg8zGZ(^ z17!zNZ+d(-vl~$_GJ97t$WO#Q5@(k0liT)EbB{A-yM3yIr9MXqHur9uqK%g7WYGLX zC5gKJq}knqfxWWzx)o$3QVQz0Es#%qynXtI_HK2y%LaU8gq|6xXT;2j?9SZ3zZIa* z!kJ&AqoyMpr(;P!vB9O-f{ZU((IZ8DQu3`TJ?|yZLR8U2;M+uO`RC|zSAqs#|K7=s zFYroEGroT8)T@L;FI-mS2)A&cbR~zQQE=T2J)A)Yo}h5W>5|Xa+9x@P!uD{0&c_?w zgiOb8t_O^+;1SO`6#M*jZ}s$Vx7tbV>8E)^NVAkGu^)R~4K?^#FV3uWsqP1VI1Ut- zwBOgMby9b}YMQyEpC7puP&htS?WNYKqvnzLnApxw6e8pWnYX2y-ntv~)j%&#AD!=V ztcknCT%A0ycb~ZD&XfcueM>zbx=3SE! z<0&C@`L<-I{Du@8p`BcChx)~iqa^!Rt;%marrc5{%BSz?!kiLZ#I%l8N_6&WT;?k1 zosUjNp^a9|d9JNGCF_|q{Trh`nRzvFi8u3ViX6U<%$*-OCuy94_??!WKSp*znIWUy z(|YpbOa0B?f2!_y5|t+lE8vLW>W{eZ(p%wL@aiT&va^pj@qJ!QA-(n;@O_Hh0xWlQ zxqGUtrk^*_yaFb|$?Jl;#d%9kH-lGOTld=yq?)p>Ec=dq_ek}sOZtnMwYTC`(k@;$ zOD?CKb_nv{%=Ew+9NiJ z1pwRj`H(g^_%A%D*7?fR@x-i!M^)2RLjV7)++p`Iyt~Iea`tVm8*HRZ)E>p^tR-y# zoSd8obCkdcC@B*@79rw?2%6vu1-B3_;0uMUB*1(^_B`y}*3z^|ZrQu0x4T>>B_MPy z&Zlr@iNBEgX?W~i|GVyW`mmY+_}E65wTIUn!?kQiiW{{0hf!U`if@DR#&JsR&Ywb7 z>%@Swa)a)@XA27@E#3t8r*vB!6fGy&GzYD_iqUb&+J~-cx8X7LR>EfZo;AaB|JS$U z$a2O*kCaD6c}04!N3E>1uC9JLZ1}WK9{Pbib7VdcSrAI~09;cR3-12Z8N=G~e^r*| zRO4UcA>^Jx*jdXw78BKl44uhVy*frY6P#-!?eQ(VSYD4KBN?q^*WB%=8_3)P5+?)CqY;&G~H=R|KT4|LVm}IcTJ* z*!_>MKJC8}9skE8l|`W3z#Go+gX}nv)7#^wW42BGm0P4g;=m}&xH|N=TI{Njx6e2W zWT}8#!%n^L{rcXB-9I`a$(UWu_jFi@x59KuW~tSAwgc3>*vb zRaNSOP;#KBhDT)hn5MR1^gSdYT1WeHeA$bey~1r@Q_rzNU>%?_jRfxfmkDb`q27xS zp==4XJK{g{zP}fg?R9VQ3n0N$2$W$Q~GwL5SwsY&ve8iZ*Ar3Sl|0?J=-sC znteM5`XZna%@<7J!klAeir4jOETA0wuVI@)4%-7*5^hOC8uysq9>1h=R1%sQstL`! zK<{p)x~avl!bdUWB*>p1n^fdpaE1X>5{bK{p2hBP+Md+6 zYx}fo+jDA6+E=U@^qU{co{+Ez**kchLQ|(2uJk>_ZzWhWOEpOWg4t0)3iudrfhqzt zo)Q-+5g;UReWUanp$N-uM*pF?XGYMI2#Dw*xT-tZ+^eMW1qp!h@8b{i_5nf2y<|ac z49CWmKP}54wLOFt!4}o{SPeQyd@_t+qfVEdYIvR-bmeC`65@{ZY?^Z^+!^G&Yb7Y| z*&;a7V!F8@X%} zg&t+B(!Qd43OUV~VoPXe-WBAh?_j~JdS+;?-2 z?_TAHk~_uA#c=&TKWwK`a9lnNn@S!@RX0YdhfJ=UY?|SI0avY^nP$ths2+)t=&Bj1 zWfSHZ4jW*W*TH47@+&Fy^S<5|BL}?GvdqjGVAbq;H@CsUnu|tPvWC+2IOi-r;ovh4 zl-E?6Hx-wDAR;g<+MMLIe{C9^9Wsrmix`*}syuRCjVdHK7$3o6LDQYH*3+jV~c1ze*Axv_F-4^KULs13ndqQqA1tHic z+@v^SEd#eQ&att30`E)u6BumXX>+ouq2+vCxk6oUYTL!!Cge5iSM5px=Ropw@5K{@ zR1a>LsAW*;K3lJiAWLh6F?lhQw3G6H^>V}&c@+k<49?qUy9BHs4N6rf5bSU3SS?Utj*h zN=fY|?K#|py6wI8k51fGyxvHlNVNB+kFB7rqC{$Q5_cs_y6H$K0}_` zW_>w#FWN4@sp%df7;W$MNEZFQdNN_3$rj@8m(ynNX^k>w^!G!L3^CE)=bh?KYRgN) zV(0qaw_fRAbuX|w7`ZuEAArN#RyWPhm%Ya(4fnSZ#!jC2ZXl}3*?b#>e7KHL-SlAb zso>~cT8)=SkGcS{=)^>}PyEMz2L?C{x|E4*p60c-x8G7`(u{InMiXr^D$@71_rpI2 zTbnusx2CK{Id>xtZ+N^sAkO!+x~%;2&05UmLg{*FxY~|-N|r0DIo2e6zgt`rMy|#t z?t66`ED}$s7#1tOoj!uaMvmPxVMnO@`qNdXCxdn!Fp~vVM{j!m-8Cru>xLIf{Lw3#1hweVz2j-(YZxoh{Rvgh6$m`zFkJ^LrqlEh|g;lUHpbj#E{Qzvv=(> zyr^^U@-FqgPvH8LS~Bp?y=Qw0*W7Av`(Q(_C2@OvxV`)5d%tI*>vK`XTQ83Np5v>_ z^e)^pLk@3H4x%GGQbG3Hj&nQc_WFfxr<7+ZJ|J=a zx;E~!v)3^=r3x?sPLE?A^KfD!KJYyTMDm?0q|XLDaI1${smmXZ?wD8$LR= z#9SF>Upa8tsuQvN(6QH-&qi!uVlpyk`X|3ThR1xITn_fXp7j=YMN?_^9bA2E*~d>W zt3%>3!_RN^2w(S@^GbH68mymcYQ=uOp}Gc~UU{Rsf^i7?`0&IkmvyEq#*e?dnu+=< zef9;>!>B1t8n0ZEaV9wQXo6R!9wu`#Q1t3eVlbe8l}oB42aX+D9@135(e9Q0ibzzM z7i)`b<$pfM>n=>)J1aH5yr;8k*BADc9tQYWbWUq~T4tu|MippJiT2!2LtT?Su8eo< z4|HtZq!<1!?&H1IBdg{~mk!Q{xSxXUyo+JH3S~6x^}f@+zA-XXUGUuiJn-ZapxMvN zd;_|mubNvcBwdWC&)-3A(}jl7GSJDMEY%i_Z{V(;tn~TG49BpMonNtP_N`0@#;Zw} zOFazjSH;(y&zH>COh<1X*sq>*)OV*JJ~Pz)m|+-tMjW*~o^|iEQO$I~siQ-&z&ZAN zr;|S#ulEry@I)))oICH?jz3^7aliTTt0N<`by{Q}h{a>r^XQ8gqbJAvvfZ7|J=JdPKUelW zIoM{m_hTwoP=4;=L+`nP<_+49125LU`W#ZT@A2b1BDT(IMu_J5Sbm@P2LPZSHuCU= z8*%+Mxuna{1x`;z-zI7{eXpO-JLeqr`Q8@!#nA_y8=9*gtbJhjQ~!mcO~! zcD&xg_`w`5>9Q$yL(;L!h8d*$Z&fiR%mLOH*NZaY8qTh7wVa>z9mf)Cif;wDJ-%3R z_|d+hh{y)_s|eY|{@KTmAOF147~r?393{By!ze4w@$!A+!}Vpw?TNRO@h&$r zM0YF~d77T8tNV?+H1U00<40be=EIzW&u;e$Ti*YsC(wLyT564_-apz@#?7g|`7qG* zIrQ<7lQ*9*r^*S-Vy94d^NO_p`(5ATe7iE2zWz)&Kg8m9^w*&X$~Wl#7^dyILYKXb z=M;TY1&ub{_IERj{S3p8E#Ez5@woQp_XzTxjnSg8_{2Xq2O7c5}Oe_vd$9FvF$Ex&uuwU?Lgx%`gD zbM>zGX+>=+Cf3n(=(^PQCuZUN*sqQk2v2MMHnkI0x}!x~IG;^CUu5mlw(A{2w~Xrh z>co8pq*LSCfD`p6v;Ul^IvvGt5xf5y(-xii+*-P6V4$k^CqGRqK$k*5>c$qn-S{+P zL;M+0z=M`|=YAx~E#g)`@O5too!rt(IE~OW1l>^&wc-~ zoaeLYvODekmW`X7CU(%4gx)Q6r+RUEd%76L77GWeZ-goejTA3eK|eesecBcfI%Hd6 z!dTrIT}Y2UQR74i=vaU5*YF#k5)11)_NAl8e^d_cCZ5urugMwsc6r<6v0ujq<`Z>4 z^$oU&F^%=%Yl#t=othb19q21W(S1K~YrD{6YWn+bqltGLCVPX!H(^+-a&qsxpHZ*8 z8GWvfYSXnrnY?gA`kNWbLQiL#@pYAe~jGNAN$aKd&t`V;Eqw79=TQTy1J$1 z5KZ??-bCEUy8l+tK-)EYiJsz!m?vA@T+TkMs$XM@jZ4(ew{k6V@;e;yzNxF?@rPgI z&kmK2=KMNZs?|}vE3%QZv^``Kx<+8)c4n=ilgp_nT>i653vSu`5Sp5;xWrj%lx6B1 zW7tz`_V)4E=@U*KdiMm+-(@@G?%#ZA;?wrlsVf&HKl@p(7td@p;GaL(fc12|m7K87 z|Moh*^Zd2jX0KpxFi&D&(aswwZj<&ut$ok*Kf9BX8+h(w3)yeWA1Czr;~haG7}MYC zW6Mio^gkWBT9Xtiw}4|+is8LPR@7zk#D9uj?B0;~k6&+|=J9l5w`IqRzCHU|1#%Yg ze#q-z9BqomihNm54StDX@pGGQx!w1?>u}4h?@d(l(7F86y439-?zUG^Gge8#Z)flR zb|Y?j`8(S4z2`x@>M8h$ugyu{$vwF#2S%S=-`d9!K8?vGIiFBn{~1$M`o8*N{s~%4 zz;gXxG{5mb<8!|*F3x-R(J!U3c28q2sW^B(;gsXWgAF}}t&2EuFG839det&@G`gq} zX{O5gdud4C-boi=kzPqUP zV;f&X@16AXZ1F-iZ@Ydfx@;ivzSWABucaQND=$6!bhD;o`oim|TLb-@N>VnxKTU8Y zd!@Y2&(-IpaE?8HG3_&o+^>hxv#`4&f3AV+e1iL`Ljj|v9inocppWu`HBaQ;c? z!7nLD^O{osbMse15(mpIUM_~9z+ot+5$EKK_N5Q#f1)OTJdPe#l3$KwaLjwnI6rov z3hvF>4B!?MKSe!JJmJK%Us}@JuTP$o6#izvpkJWSul)q&qjaA?Z0`VX`uyQ;py4NF z*lV+Q2a8ut-EY>w^Uv3}Ot3_GCIou!Z?fa> zaJcI`lZUbukmK18HyvAk^ddFT>`rRaM%SE;&kkUC8&&bq{T<6kjJ|7m~ih3U{$*Kj@B53cgR4{xt*_W$JW?iX@7GJ?Dz zZ*_1t9r2`SlTa&XqE5_G->2rKX(ljB# ziNZ_v6|LjM;myCmmorlAFIOb_)7QwX-h5x5-il7EI&&yq-fI;V*XvZB!WXRszC&#N7To zKN180O!&7xAK1O)e+i`7|D(wMi}&+@fA9kS&C>yR75{cq{12ZVAY9kK!i{(OyZJ2; zOyzqRAe> z*vg@jNcD0>@>(e&CQsp`KHBY>7e`>tj8~)~`aO*>l~`k${iA&0`!7f>OeK1)%tyUh z7~l+_a5%5wU=lcOGC!7?9lh>)O48n4Jl^fxU~S_%o%Cx9Pt<48kH zWrER!la=yurAO|Z2H5>DtC7mA%i(L@ zWDCRX`qyllF86OlcZrS9-*i^5;tk)#REke@-?fqcw_Y+A$7Ai5RyM`I&Jl92UluJ3 z-e~Mug^{m8@^Ci`3gP1M-2 z1ktr#&1$!P;9r2D>|yr&aI z>+Yk@9VcH;(x1RACJ%2z!qQs&1nLc8tbHn@Zo8J9%_Cp=u@6Ej)q(x|EGOWFCAY_ zy@u77ce#J@N_IH}6Ao%gt_vX_hZ7D|*syJ8pc582i|!c~ZWvDhl+w?=uJCq{LzKalS+mD!>?0Wy4Jq(%w1)g3$Vd1OB>L8Kc(%J-v5gGgwXhMab;fE>S z=g$&Y%3^WSfW}0shTKP;Gal;&n@CxNT+^@+4SSplv$2@4%*XoheT&tnyS?9sKS-$r z3Ji1_@EoI0?UtNyXn4u$4nfC6!z-bFzpD|M@aLdngXp;=T}V!cL4JYy(K^W1>xh2k zGMNv5Nj-f}v3Sn_Xd?B7()5}C8O2Iv>>*XcYS_fZDh2-_u*`DIMu{g>JZX;kolEa? z^x@YPVYESDFHWIpyK+Fq3TX<*=}-V z2RdsOn-N+mKh*6lLq1YejF1V;psJHs?Y zHSBy}X-;Rpg*c!%UkH1wKpsN$%k{@pCTapL=v*u>FoLfk<3?8kmi~iJm|hKV*&&#m zlwiSAVi(2sWNeip{uyL0Lk5zSaO^{<DGjc=zZS2Q!ZPSo zu@gJk#eqQH`QAm#{m^yq?|t!A?LJty)ZR91rQA<(=X%RJQNfme<%?Q(pzZK5 zymc4im%|75;ZG{9o4(A7TvgbpcXH5ITD;(-W9rJGq~gq$6+8^632lRB(%(JGzx=+y zDKcgKCnp;}*)pEZ5dRmwZYCDSqnr;{G-Y2pn}}5GlF6x~@!*vzSD`b{;u?%$oPT(3 z4Rj(&h|dgFylj7-uaa7dx_e7N?VztJAO2$Dvi;zG&!tVB{h>F>K_~bdc%E8Pz(!a& zVaL}#IpQi?FPXKY8%exeiCzTks?8ei>hA5&VfXQuogP+%@51);ry;NLLTpycid6I5 zP%841%BJ(A54ZWrC+Q8f|D8El$y|xCbf}6V^wmXA2MF+&6Lha$6UR#u)&b4`5dk-m zXRWL_kuQ@6bW|*Kt30I@?IiDH zK9ww{(jQwgI8Mo77TDU!vV0_Tr8+I#N1QLgts~IM#iEa?xyrsND`bD;P0`VPjkQex zt?^c>5L&Z_{KZ5GGBVas3i}w|`t#V1_w-6t01!YFyWa2l>Ksoa(<$asB3i(>S zsk`aMrMFp<4ubFNOyTVVG3m+&6>)^=xbE#Thg#<}i^>LLcls_E+K$-*cJI_vk?1EC z)s*S;fHkZb_2)SZ@Pj+wGC%t3Ue%YlcakiuEif*-+^v)k+&ieJZAuiGR8=U_Adf!!_+0sRI8z@eV%x~3f>-rl_wg(BB; zP{bUIHC3C0jisL<{Pt`;9y!-KjN_Y}W1*XLxAMJc7mUua@XbbB`QfxdyZ+{iq~%-r z&Mb{mu}a2YGO>Q?kB|E6KBIGTYLk#NU}kd%b4;t`H|A4m#9Y{j+XWVOaBe#Qmu|;w z<|ZwTX%2e7uD>}U+4%ws@)BW7X>Mp-;KGVEVDzHPkT*S!owBH&#Y;*N)^7@y+?7A= zv~JdQr2aW+{amns=ovVAm5E1BFAL6e0I*%b92_EuE4>iW}jpgtL z42`G?I%O!THV$qMs7!*1De^sd7m74`CpaaHusv%|i|`Ra_{lbQO8$JoMjqbi3R*a=N~b`UsT={TkT1t{(@T)mG_+Wb{n#6s6vhOzsMd#2y_LXj=bgX#EE@rZuX* z*SUfyfA51Y*?2f|EN6VoPDgsYOKmvYQk()QRK)=(W~Z!O5Ia?j0+k;D#{hWnt(;p$ z&>UVi(ORY$wo;Z^;~R2bwmqut@Yp2q?B}c?o@R9-_ob2+2C=94IWMWDksq5MrmnOG zp=(c+??)~@5Lv#Ox=R$#_qL9&ux`z^9C;%5Orckp zr$Y?Xdn+FfH(}Sm*@+C|{7Tp*Qtdv4ORc7Yl?SD-e7-tO^LKt{U##_Zzo_(-3LYKA z!%SQi-h}^32(F{A~INPf+SlT`-%wEv!73*+79Sk%tl@qskqu-AGc?bQK7 z1EgdBM}HHRc2o1i_4z}_&4$&~>EX_j!jizlkxuIedwTZHuBTj~zM@bi6YplM4Mw7N zCz^!-LF2L;uBR3hHPeF!l)w635Z%v+=0I>IEkxIPwVW5Mg1eYtpGBEEQlzHeDv}v* ztec)DTw0b~>wf%{%M_b>nmQ+_u^|60iWwMN%={Lg-f5`_^d`jK>s;5YOS8xw#c{O~ zoq5PDVKqDa0WEb69v$DO82^NrcPw*^yORv1Ep04FeqPrJYC_#EVM=Nt47MAuky+;D zxr_jIXmxmvalFb78~86J;h~;8l!7i&n=*fRpPD&n8$vQCi+AzwN_0zVmb%tfbf!2> z)V{xw%nNX9wh&bt1-mVfqZsMd4!)fbhWs@kF{i3luqd#AE=cRl1s#Bqz$F}3=1d8{ z`SRUMpxBHYI&{KPZ_eV@+LvML;yNNF5C~EW8*AixUUK?dl-1bKs<=5$@thuE$eZmF zl0Fo4gXdZ(2_itMO`aj;IQ4mgsVKAG;+rO|HE@)2@*1~ky$M{t>W=ag)>-vtcqwa- zXP(K#pcc#<6A6UHmVnVfCI&h0s-cz$wi#YU?sT<3!KYe#bBuXqS<3tyhj|@u^AA{t zG@CW?7(ZTFH<+oGN)xRPThPjHz)T27;0a`)4(e8V6ed~AwFqXBb3^4kQzqV}9p`jC zq_g=~3T`$6HXX@&ia9b0Cdt+lLVL}QBt0t{FyJ;EQrGQD2E;25?M8y+D6Q(0fK&WN z>mJA<#LL$F(BBWtL()SNIZ}xxl+z6ns22*cwr>`_SRwNS6mk)RQ~j}WZs7}Ko<{~^ z?jgPBW#W&LS!p$W6=_jE<#!X3wX0Yhtw?c`s@J`dpZGHm1 zIR`)!PB3ZPQgj|7lvOMUb=F8t51w=%y&m^P=Ab!lAvlQR(a}Oll0e*{ed?4APqbff^-7Y@29UJ* zX=VBo*t}BO*Kzd`A^q#Q0A?mS@Fa|-7sSCuKOO!kMDoIR$c`z}U8t?i-~7h(B=OHs zrjBj;72c{IAN-_%vVA}v2Pi;@7181$g8l(ZV)|lVK2p~hTjJ_cf-a;%7v1CEoJ!OG z-E@+1Qhj~^;@IwKCgA=khLmuoBfFcjW$jv|N$mkM5oa(yYZ7H7imAk~FQQb(21>6S zG;(Y&x98QybUT?;-@CGOaBhceu8}gGQybK#(vfmLqeMyHI;xPM8HgkJOS#JdwHYqQ zmxQqcnJGw=)ns4^-)!yoSHIDCEmBIAV08$tg|T1V@PO_X)DoJwoJIw_ zbkhv}3ToPs^SQBC!r@f|YGoyr1;Qy^`c*JWYj6UUisIN%Le-fq z`M+R1>`l?hvg+w4YPOqG0S}|Eiv0*9>2ZhmN-HQ8?&s)qof7shPfDZl)R6}sq~sbw z+s~{r`Ggb6075R4%?(lAF0@XPrYtJw%68)Cz;mG;2bfYl5etV6f84_IlM67Ps>OZf zkp5KEMCmuI^E?+#*aB}TlL5t6WK<4H)x^xikaFhk{}G>sF;glw(US;bP0m`PnjqLs zD~ii60LonIPqrce=Sh1sSn;JCrQ%W$FjUXfeKnju`-eHw+^y6c!(^!>Hlm0*;IlJ+FW}@7JHB%a zxUXp(Cb#*mK~w{WPN0-Va+h-~Y0;QOvkR?J$CR5y?{N-9?lONWj21svHA2^{XJ}Dq z3<1=ULOa13WZ+()Os_gE4Lka{r92ypnmHkpn=#2*GK3Gt(GL025o(#JBM;Jf5ql6u z0-ia};W5`SL52;Z<3dK2a?1Ig6yp z>*zRFzEkys6xztp+hWKIE`gSWSvHNcNOTBEi$_+bB-(@kp306n=C<9`@$RH{CUfNd zHXugQ+y*iy7g;u2I8u_T%?@WzR8;J*fcB-vdV1P>x$jI$E_;$uS0QpRP?_Dz62h0ry7%Gj4SYb_2!}Ilt@={fhnE(8K|1 z>?5^GZw@o(!Fb#&ra7Ptr&DjLlAu%PBtsO}>XWw`_FKMW;mKHgHRx;wwhwt)X6A_T zVXEzwQX>G!Yl`=pVS)YG@aiII#RHFzZjUq6YdDmWr?JP5VsNvD*dwGq>yXUJTCrhw z>}d;7!rRv|&%UTaO6J&`i1LjpRA{wAM-(ZJ5(a2vNG}eNgua{=Jk^a^Qgu+~i&}N` zKBn#jiU=Hn3^LL@!AEC;fbeH|!ZyA!QEEX(acmiApp5u5h zwub^)Q&yAs6Ov@WVDE#<)>F(l0|p$wkf1AP3bEk>5X)=~022TC%25}GW|P3WJ;N~8 z@kA@exgNn8cu&tv6Ziue130|lAm-fwsa&@t0*mdpkSyR)Z)xJdjhvEN^gG*W_sID=m(uF`91-IiYHvH&^tG&5=K)cj?c zv$wQFCx~r4NWFrx4?t5-lkk(jK1LOQ84)FuzZ!jKU_dz0{RUzgxR-Eh8e_n*8FeKi z>ODYq5P3yQ8UF@lX_@T{1l#g89&J~oo0>HPgY?i<`;mZJPCUj2JXT7NdI8F<8N#gz z@lsP&Zz-p%3r52BZeYP?~N?V64m=W*(3c!J%OMr?L`tkLu@#0^kvmT&E^*1eop-(Zf^N7?*JfU`o3 znQYK|O|yj@D78?qk64gWgUh;(9dubk*~P?^pl-`;5zR(4vYC9)ex^Yus25Y*bQT7Y z3wARxu=z}1R4YWzhgMTqAfNCI6=)(B9=@tfzM&C90Kb6fi`PB!NOa((?o5nCDs_QC z=6x=IjHzC()C%GpD5BwmwFCRGC_~585K_Vdb%S0keiB9B3$*@3TNHaDOXT}#RZsI9 z`NDIY=}8~;O_V7Ob6XW`M{My8mC_Y1**&N`<{)E zz;p~#X+5Ru{xeH|(7p$=hXjry??cBAztrQW>4zJMNcn-;4k*!!dWPEo)R9U9{Cslc z{FVVTN6HYRNOc8Bg4#pPvU~*_h&2acOsV#~=_ghuWeaJcn6*s`(G7|emr^_jp}ncT zfKB2)W7-EA&Ot~ri~dHZql5l#JWPo!u404Ob3ii?Qlzp5d|vi{5FgkBPxe}((nvXV zC>)MnBE{}Ys-<__jB`1puGnwMQ-u6gmiUymvw)qq90&TEls|!-h0Uhb)RsZ+ONF+Y z!{gVA4{|mEPF`iH%w=*leU6YMp#JdPYK0Moq_XFvmwXM+2e=$UepNRdP=yP)SB2`e z%>;S%kB+B&hZ&HFy|%ePUM(f-=2NbaK46&r!??McCs>tL2>u0%1MXMvQMc|s>gm|5 zd-ZA|4KtKc2$5gNc!7e7uhgyKZ8Aa+cLSM?ch%%W@%|V@h4kVxZ9;pTsM3RE< ztKjZla4IHh%ONH{8pyPI4-OlPq6lDg-8rY}<3Vh5@w1_pr!Zcx(KH66)MT*xL;8pJ zpnD&w**sSLaMNm7b^8y;KUB<&H8BY?Hs$3O!pawZX8x=YWly3wEkdq_&^`nQdUqdt zAFzewm{wHRU=+TokzVfU131m}xxs`Q;0Cm{JoAheNM9JLeXt~a8x{paVDF&r$_0Pc zP{3l&q+k`Pem}eiBOTySc9H&OHUuWOwFQ((AS;(Zqc?XBxHib&P4%r1L0!(AeT zhGYQ_yqY>xQQ6wjH;kHk#vF0gsL20lNTt0NI)!ASk$%z+Am>+(tjXsZ%-ZY3W|u9& zH6e1aKr~DS?kp<_c!Eswf6(du=V}}7P*#iH*vzH(Q>f|91M+yvkFPV(YN{jM^)P)g zORt2!ls4oIG#z0iwq7aMdNwD^rM91M$=5P~wuOux2AiK;aiTjk@OPc^Cu%Vl$ln<(lv2vEYUNSu9*X zDiQo49nCQh$)2lC-p0hwq27VikwyZN%UMTnBti9KvDaknuI1=wZDyQ%U63fJ2iPRXPq-YEV*rNiCl#C_Ey$;Q zjMCvt!1K7Kr0P}JH50XvCXb*)SuPYil3qz9o*T0krBO{WA!$d!o}>o#h5vRfi~6eG zGBDy=PtTvJ3Sg>r$EZh03!{?!tF*2oeXp)U+?LRpSd8%b-Kv975(HOWAy*u-7GfP!2YqKOC-;RlZTulV`z?RZx%mWQs z2J*?;j`-kPz+D9a!j4=fe$wea#`1A9^Z={kHKZgmHcP~Atkw%j?`cJ;YU(@uC|lqO z&J!M>K+MJ|!>HH?slOXHBtGJluq%?l296Y#!&4+3w+1o(Uh}H-&SV>MoE-EOi^42X zDT+kNMJOlwts_8z;o%+l{t#(V$?&SdS0tw{eCX%+Gq=QjtTp|^4uiL{$24osn}w+E zqtdy3dtpzIKr8G(H$ErfEArx~8m`nVY0v}IV(YxFBE7C+RZFHKW#v0rSe^zO+oA9YGSD$T75LporlO!dvLj`EKznm z(nR!|JxuSzmvsoDELFX?^0R)6+OddDKU>JCu~Qtqkm+U9z=f&mrJO0$*kMk(CdVNQ zgI6$g(V#6FhOVF;JEPgLO@bqe%1h+&!Yk zu?OMkrDMYmMAsEc`7XQcV&$uZzWge}JS`1n0FQ zh+|&$SBk*UL~y@+>qPCGMSsA31j@oO#$LIzpJRcVZu-Wzou&TdxDk=TOr_P;j-8AC^RV(548Sb@i~BDe7OxIB&L=)2UIIwMmY_bS>p7&7zOUX z*t0OWzPm@sq%u#nF$8M)+jYqJLix}2itQw^wL)q$fs!5&RyY#5Cwm_OWQ{crTQ{4~ zW)A!|r)xCj>jDi6@`H*F6%vqcLVpE)B{nAo{;q_3ZElL9??g?-1Mz_pT<%;Al+?G4 zXo8SS7M5wzWt1z-QfuA}@e)wDm>_J2&~~bQHbBwiNVkiUb_xSYI^1e&Og7*-blg2U zh-GU4Cq()20;hb5(iNTg66PTex#K6TZGfsmz2r0_mUh$__4{)?_n|N9qldjG1XEr_ zo65zI47eV%e1~SutD;Akr0Qc+PR&3LDYYAirD1F1SB^P71}Yd{`web=-5gH8HckL? zq_!x(iC4;&I8sA<)~F*m)*)HW4q1~`x(PM5p$O)yZWL!-+^01@Zuv@0IxKf?BN#G#|o!G5(!rb;hj^#^g$f1es z#KFBhpG>U=0HGd(Xn7tNj0O{m|eQIRIEbzsmno7e9 z^0|F~`>buDPL(a}g(1>fz#%JF&vRU_!U8=y!T>JjHp+m?EeVEB&<|n*xkp$z+6lV@ zNO2^UfFiUsRXilKHw~UHN8|C4+^_WzVpC9J$9hRTOf`H1@i%`^*-=&!HRLF*6`v`e6N^o*Ceeo750E~^tAY^))5F&>QuzDs zTRzA`Km#`-pRB)nmLmkZd(#+qRTJe1yh#Tuan}IKTrO=Ht@#ks)f;FNRpcO1(;f;A z-{1}R5Kz{Is;2K>PDh!FB=?)5@!y=+vcInHx$2d&fgQ4*uHO zptp2i!mUtGO{Dq1?`erK8dkcFpYVGGTI!Zr*Q> zlOv8D2xE#PU+qXr|H_U;)f>uK8H$>0Wn0(PVlHyOD%uv3Q6z~{`ZYXMxY>#`4@KL7 zv{9*^JP0^uTk2~kyYJWenVDuY%AW*F64X3*ucd}}-mX;sHdT{tRNIB3(cA71kco?l zKeH~>AaGkT1*cvdRWYqQ?1O z$-MYF{}SR)#xmuj(Pg}7-*iyh_aB|%%R~#sX@}UG;mP1`efh70>@d_aq6VIR%UpIe z&Ug?+%cx`bCH0Ay5J8X(FRm|e%BdMnf)X_#nVC?Zm`{k7X9a-o#|CLFt*xUW|SS z>V%ON%JqJnhC^s+>v_)mLi1)dKG-ydC>{CcqD&tcQ7d6o6p2`SHxhQn*jyv3ZB6a` z^6my58PYLn0dX%C!R#(d8T5evp z@&~1r)@k15$7I|scW}M+lj|BD=PXKk(_#mSsE9h_+TVeoOZ2+dGr6V;twi(X>O0nk zwB0C6`L@i9k`5E5*wj;7daiAL(oURyXsB?630;8R*1qk_ zB%xxk^&8d)Oe?(Lse?XIasIavGYTv@FdFOFT0tQG(DGQ9bk>qLqnn5j%8$i;TsR)S ze`U>2lZg_5N2l-43yBNt+fA7EW-A3BUmh3AU&nqQ&>x0ad7{kCe;nUL zMGW*JfL%R%+hZY^ho3|HqFUpvWO4L9`9q*iT*@f^-z(-7?CBqRB?9}@+jymUXF&6y~l zX$^ckmA#pyDZil^wbycycY7|=o48P%@v5%C6236zQ|m8V60G-EA4GnG$_AtKJc@tf z72cJ2OvfG+@=jTtqhs>Z@4>E6lg z)yxlwaa*|F8R$wfdjm-d{cBj7n8MQ9d^f#mP*hv4QCGV@Anub9btYqC`>u_sg}}Cj z*fvI)jHWxY*O4Ck#f_in(qzL)C$`MWqbfmQz(?z%o?0-}T2f8>_Vg`q?Df$w)FR^N zvVi-FyzErKip|Z()0BXQvuiq?;CkR!yQFDF5t9eIzHjV=!2y@~72yApMJv{HG?U7< zLKzI!Tgozu*llA4WDQxyqX?19D9C&f-Yqg5W!zi6E!pe=1g__w_7(8M%Xi7JCFUUe zcHU7UAK=gyUgVB_Jc^P45Q3AJ7taCpIlJ;tn zfKY%xv@6-$4#q7=)j7ycMG3Wu`0$K%fL9_JiP9=E+WZRL+s+9V!xNo_>99-#xCVI0 zI%yG6ORO*+OL7=(=WkzbuHhX^O_FTyWH~lM%$vO8MrsJ*C?vepU2WEhUNk|?-yyp+ zuEuuqmlPJU*+r}KiwFonZBq5PoCK?a-AS2s>?9=wC!NKSS=~IP^MvN@2Ua5Sz?}5k%h_}CBkr> zi@G>3+9+Ro8@1w!u&-YiSj^lT~}BHN4w`Q7Z;7<&E}T?gX}P zz2N8KJ65iS;PtmdE+IypN<0=I4PToSdI6oP#a&)()XumiiVZuDM*=Wzjh>N2>NEiH z#yg0bDrj09>n&sRR&=?N^*P`!sw+ZUgsZ^yB^M*%Bn?sKFm9VYuXLLXu!Ux$*?4oD zl3isrV2Eya@)9L79XiO_9+GoDWeer)PMYo}Qc#py52MPPZ4QZBXf8J!ogYzb=|sYl zExOfvN1fKV>Ys7hGmQ(!^FI4PQqB9t4^!9;R&mH#O&Vflqfx5)3CNyl&EuJcev&Ib z9vO8)SX&_8{a;fEQMRyOxP=Z;y%ykl=hW&~2|7 zz}7;oh2i56@?xH0mn+iffs5U7fj%Jx1n45aJr($x8XmXe0%n1{Jz(cjb4~j<1rVgs zcke!^xpL8%u7Auea~$kCJF3HK;J|4_}p}V-DXRr>{VKXkW9z-6!s= zL+vmf$Z0NJ8%?AIeBcyjnx?3IDnb6QiU&2wM(u%JRJLR-5f8h*%}l6eKVaw03Ceio zr3%9<3=8XA^Y%_-yy9N^#%U?`XSw)VF6i*jP!3b1!@uOzKJn(_j-RXZ>umGWinzYC zw)|a!9bKM+Lq;t}<7^a%PdOHuC&IWjX$aR=<1u}*$=ztXQo(T}tRA3{H-uknVT!}H z<#-RtGo2PNAiQ0(m<@`7^Wd>VTfqm24WZB-QyK zJC6v<4X}clYq(HqcCR2V@J1AcXdun@pdfcJKw{F-7AYC>$poC;HNbZBmczBrg!@9$ZL<1q&9yI~AhW3saFN*vsL%mfBJ6krFN4 zwS}Oz1CEWlsXN}VHBdgc%+rPo06J)Cb?p1vNdgCBz^(7|PIg7wu;Fk+S_U;6P=dTl zfbljvR~@A7C6~X*^;3PUExTISwux|VRpo+Nc9pHR{}}17W)yFL2{rI-+a>Gw05NhS zau$MIb=$5HLR`RA-1~6jz7uop?Ot|=t;VzlXm130FbM@x5Et#Wivj|RugPq9wj#}$ zy;$*Z(I+4Ov_}A&tIwg95}#7U9H`yaWn)Dn=K%{UGJcls+4kUAmx(KR4cih$0!uaQ zHCL0^6Jf zD9l{DPPY?DGBq#DoD=*s9?+U?+bGbv^SL8Qa_Rb3zypjFE)L*fra?Lj3u;lbi-SQqAaQc)h`xKGKn(xe`Lu z^5!t?uCDCXG}jyPP&C(O&R|e7onjZ@YxsQ+HrLJ^VCwpjLU*>!(H-AL!CWRr&%(K&kv|G(?_*M*Jz@dFiB{ zd_yiVr%7|AHr-~aCzx7=@u?>lGPWTl*Y~hiHUbYAyKs_G634FXlIyxdxwG_{7C3~w zv0V-nI&~1AnDpU0i3&A=P`EYNin1{vh1fGAq33TUQ}EFQX+jU&!IwDnVW6P`?ej zEF2zS&87L{j#ewT)V-yHAu@Vc8#s4)`Ed}^{F!Zkk93T5Bu+0C{w851)}l`w14sr{F{*mo2Qr6ib74D^*-Ywc{*}(* zl|0Qn#Hz*w&u;Oau3WSImH{?cHq*JUW{C{42ON{t>a-1slGrhA^ps({fFy=Aauj&M z1FFcgRp-oVM6uGE{n!l!Kp3;AESWnrYdM;(3G>Oj_-VeP4IwyLsM`1DipQ+nbu=^6 zrqCg|0O3@KMQTi-ZMlm3l`VybT*<3(gU-H+$DJqkyX zLmK-DQfBL2ElER`aioTA?aUxE%Xcje6YnA6tpYC87&>W%~p0 zIEcJy=Hz{(qWjeUSUT&dsM=_ae~N$%A|Eh-0)nV?j0i|G($Wo51JWTaF~p!CB8_wp zox;%Fh?I19cMr|Xz&+o+_dnJw)|xZ#+3()J=Q;1$yG?9)S$G?OXQ^Y67y@U1mbz5om z;hqLkP;J|g3YF-?2nT;(?%2N#&h&J60-X?5n$!n`Zxw5}B>`v_#8(L@S$jnYk%a?P z+H=x#hy3X11W7!9eg{A_9>V|4GN+)g|N0XwL9WWT7NYG_#ZC!9JRn5< zMYsd8#u8Ac)v5P)ZwyK4?^z)NutpJkX2X!J?uYZlgII=rSNu|_p395w*8fs)b{o}y zT=vvy8{Erj6ucK<$SSl&$blc>Ujmh>^)$cs9=GkkjRp0V?bPa5uG&?r$)^aM&Pt7+ywfzG=Tfl@aUqEaLSmwo{$bp zi^j9meGV0Z8Ur2!&SQNGmU&o4jPeIno;k<&;fZ~|nD!BG z6BG+0gh}Y}<9T9lQG8sx*z&q>8KIy%bpNNU7ik;4$)3bC9%6nJxc1v9fS~P(p`1ea zk4av%9O>>@DB@1jQh z|DV%>Pa1#+X}djEq$aowFarQ(HyV(X1gQiDce3y%5auhUO&##L?nRgbsuBNj3o8KB zCocdWhwlH-MgT&r;*SRbDquD>fm}NeQ1$R1w-3>KKfSm|*v^bSlxcgmEC@Jx_X(H2 zApl%B4q4|EeDt^#AJ-=DL~h9Q2m?sVJ?&{iy8A&(-&+9Q0MU68-hB0L{|Z!-pmwe! zNvIPj^?^VOA+F82>^ym$%;_N=+}H&y`cUOd00Th7n6`ar^h^*d0}y!kRRY$Q)c`LI zkdv)t-EzYKCdmPE`hg&pXB3b0%gi3|HqfE17pK#%=GvHpaB^|&k&+uc}3D)@+= zpu2705#qS*KY-MDWpE@P;V%V51L(2KRXAREyA6OC%@Coi4%KI#|I*zf(`sW(|Kd(|2f+jx1w*nSpnWC2~unaI==?DdGGJq3s{~H?yA044* z0PgXWSpc~ToO&<6eKNnygKVGhKk%x2vT-lMKL9BKEjt(L%YLxc4t!BvIT%PS{|m?_ z(k{H%`R@QAKbfWp!1`wc`kbVuC5nzy4$>$@iB$sd3|*Ya_lY6`{zEwO`OzQ$-NN_~tdgwPf14l` zKfi5-ZI~3O4Sc5D!?bfR_aOVifftnh~F{5rv##pYMP=`R;)xH zr~sY`F`}CS_)&oSq?ftA?7&Lu#2|Rzl31PoKMyIDz^YBTQ3}d13T&58WM_DCZ8lDz zzu0KJ&`cl}=m1A{ZQ1GJ4Pflf7xf4crP2uKs3{iX>&(SN~y!L;cJtv`F{4TvlgPo{ z-}F7A3o%w&AqTx6J7M6xabEOlv29%YK3Sc{` zR#ePD%qeA8E9INp!=91bTRfLZ_tJyB{thML%8=J?mQ6obSOU*db}*Fh@0>yyWElPV zWNv;w8$FnvpJ{fN!i13=&WeY z+!8ck`0E=eiOh0@oL&p`G^Mw@7ghPs3rbu>Qz00s_z}_i(oy|RHCn)K@#22uoVp3P zdr=flt&Vj8`3=Q*EU3l^SY2G8Rc6&;pzfcdaD3f2ItrOs1v%J498?~7urt>$qBkRv zp$!?^sT=+2LEfdBIh?`*xgA>{NN$!Qx;T9P`aWC=j$X{W>IRDs#9S^!_RNhhFs;vY zSjN1L{P%*KXzcpYMCbG;n4K~5ThnGS9Xv=K`vjDxD}*-H#g#SjyIM-Y;MR=2DY75w z13{KKl*zb=wdBnein{*9f>xLMf>n!~WUj38vJgHej1q`qIZ_XSO08Ur!cn+H(IR;fGS7*K`<)c# z!r@bbX!q85iENEd0wWx$n+zjwEGV zP=Yle)v&xEV{Gi_-m>~{_Ir8X+-#a;8!~BAKa=KNL0Eq^wA*ZT&p$`?=PunH9gO8W zyBml^aun|$=7o4k28w0GA9Lq^DSxYiLzomPu_Un^-3x(AFs89MS`)%WHoFh^Yvdn6 z#NQK9hrl+}tAA6tjETOGu8u*NMp4&|{1ia0GJ?Dpw|flS*GT*O&ru>|LeftkvHhF$ zwMj5{>LJ`O*E6I857;wbn*JoXFCuGEHuiRoP#yOTk{Tf{%&E~#rfRR-w%#C2y}w?* zl^uU1*PD-bssu90Ohou{i+vn*Cpi-|yYrb%z%wR$i9AG(^;b*p$kBKT;zMh7_Ri(U z76j$Rm$Bl50_2}lemYhBF&2Kq!Q+^8#z?7Qscj*plOZ;rxcseeDI3>@a33Mn%7gVI#y4QtuFAGt@Y!R zkdC96{x;TRcEAY$SptansdLc6T-eksUxss0l zO|aCUT6*dwTY4@K^Qk|PoGi%{;J?(d-%^LUB2uMT5l;eNIy$dcEuu9yOw6B45T8EC zWz2`F4laQGj;U7WI)0w2_Vh-)K}NZ}b#vUerG7ekU)hc3^xHHz+>)O%m8#FIK5^9&BBx94F=UCId#tZmhjI z%B=04wz}Z}v+;y)B&xuALhB-@bm8zX-qq30_}sP}eViYIFNIM4Z#l)~=rQk0iJEWN z5MqI}r)LcmUL>t$u9#YnQs#+o`a0E1ri;%-l44KbZZP&RwWOE?e^J+W^np$KA*#8r zUE6+o{4*#ZIkPmR-Vy8>$zzecLB zQgcFz!MJYR)7*5Tyg`-;{RxMGi6>Q`VXwQjhvta?sD}%^Ycx`)dX4?I)oXVAHs2>+ z4f_s6xWqg}gp=h+7)a|z9T+yZm!`|ODJ;JN1^!J@`;h8&DOsB0)--IUM_dofsbAnE zhU02C7Va{yo(Fb2y6&&E8o@5FbTt;^e;#Z&SQ||(PL9m75vE7hiTxG*n*=GTq@0+y z2cMkiXY$0MUfbCfUvcwwfL&|5HPr^|iwgOf#^97lwW5Sr&EdZw6iiJ;BIPwKyOpN~ z>7G@Ngbhup@eHa*EEiJ>W#pUGN6bCL`N^Neu%)^*X5T#>Hm2=zki1mZDwNT){VAr~ z0L*zJ0Ea_1`2twiz57tScDiu7tTX?p%g0@K96;y_)e9c7MwXU_ z7Kd9EDj0@yT&&nnh|@XvEf&lL5pFEqew+@9(XOz=r`2GFTaRzX*L;ag5eYWvdoreM zA^PWu+?wZ8sDg8fI54}`vP9?Inpd`tqAs3rT7Hk3NpyOZyF3_wlnxuld1{r}}zxhj$=B@UD3k)^A&uA^KXjj~pVv2EbLdv;#DmSpGhg#?DPvx)*veE? zqCVk)h$VZw#%6Z!Rk*(V&L{EUieI|Xw~Z&re)A7hE-6PYHvunMTjD#uH`3KlEis`K zEpnUA@9QVbpoG$?wIa7ld9qj+ z5OJWtax&_rlnD>|YO;kpc1#|<0Ez;<~9vFkjD|-Gs@Y;Xh-RNb?PMGrgXd~|i1KR7*eRCvV9jgZd;HilX zZiG^;>5o0a9BB4X9PsuBFt{-FJ8JEB%AlRtYe@;`keAjMD<0@^>LTAnYd=KZTu@Nq z05khcl=u?M>@T+2Pq?8vn|1wPk^1fTrK%=_`KTSo9~C{SzhJlAvCLesByK*>l1a+0 znc<(C{S`Dc{F|R|+u9u@8@>>dP&XfAv1cQ*r+15+Y|Ot@lHv1?8Ok)b;~Tqb`4F&4 z^F4klDghjX^AWJmi(mR7pR@3zSTu`lE+j1X`zNO~8uYicx9f6XM|Db@HQjkr;}xpF z*7oaQpJ-vDlzf#puw|@5*ZDV7os+k=x#vC=v#7d3Egv4+?puTF#DzX?UCw->qn#y^ zi2#|$Kf7CEH5pKuS6pBM4HeuIY1|Y01-9Mq3witTbkoT1dZE`@`$Co9WIs@&hOykW zR}2N=O?o~MlKRPJmF8dhS6U$6L$~$8MqSuc>zZhz@4(GP%^}t~`xV+X*}m@Ec;o^T z_TRu9?NdrLCR1vIC!Xc#Q;4zj3IvWW{nC`_7s*X}knySsG9ae-tqCQ+h)^Ih3%&Yu zjeE6Dvb6WNvNhvs3fvO#i1EmKFIH4&Z%*b2Y|`=%CQYvPC}1<0U-2bw6O(#Intk;X zth0DIHtJ{>zBvl@>prV|4}~Mgh89&%y4ghCkY*_A=X>6#C?BCL*uwz5E<_jlNBS;E zm5ATTNOY!vir1XV`sdDrLl1N%N7rR$**-#U(eWr@ia*i?+3ehRQexK_nWjX6HWR1? zMyK@$a9A7eWDWQE@KH1mYASP0D_`?ltLT5M<=uTBOMYTQbsF8&8aIcWFob04of0(} zuefO-)?dSwwstU&yP)~U+UYH83{g{V*u<9Nx!N7tqCEb2FAyP*vChXxuOfbD>iK-4 zG&hG2__K%fLt4$#8R~tn>l^*YqJzqf?Tk2m1kVBtGpC5a(BKZoV}Z;B{=Noa>W0XC zwe!I2`GKNAqd`)gh`rvvTbE?Rd%xp*R?RoYA%2Qqq1)??8xnA%F}pXo5MB4b9tNLz zA1J4fH0bj!qpQ#c=WH_a9Qo`QE0O3j+R6&yxvaq~`lgWPx52IU6gN{i^{!`lD1JTLC+EYy-t@E8$v%1@drnRkqEOzn5|G+k9(?ZZq zFD5Kjve(P+B=Vs?QL7L&Pa%k3E@|&x&3O<6t9CmZX)rfwuWAoRx=`t^V!;#QpLsY6 zE6LoLEqeQ{)E4Y=cJ>}6(?zVYLvoK3{q>Mc@%TlG=WN^yTNgWV7lQwIJX6kQ+h ze$q9R<8&bvv3MzQWY`+zbsKaBt3;gUMV!-ifht9tQoR~=!8g+>dd~U|b`w63-8X;i z?k%2dz(p~;mVBlQp_;4+zCbrp5wDih zvZm4-;6*fVrrV%J9e%)_P@HESR{Lio zPor6FMb`zvvcX_!z^gg%CAIX^n8hvyBh zT~ur_dEggO)3f%%B4D=h=usQUoqQ$e)jYLA-xt$$s#?M z@M(5@aiZDXYzt;&MBB(bB={k{y7#SAU{?-a@~d@zvE4H{IrXNX4*5vo>sGWnd|~5A z0WO8Q1J?_Ebz?gh+Mw5#FZ5f#SYd=GcCnjs*I3`1xVvA}PLIgi9E<1RwJ}B2U3~~- zCiz3h^kPK&P~&}9K3M>`b)3}J%QAPbA*@zrY9kRLW^9?C!3s$IfeCCb_A72 z*Q%Hayi*XrKB+qu>&s~_s$y5y{jA=VK4FRpw0^^`RfiMiP#|wK5K%27BtGYa6RyJo zw9Sq7`78*QkT)|Yl$+B=15yg-<^9ca`Zv>^3M`4>TK1*}`iy&0W7@h*B=$kJW7mv) zQCg?^7WHp?#p&~|;4Fc4Sp!>gYPj9_n=`S)`PTa6RRN7Fx%9=$cSq|wHu*nG=H@tN zXX|SYuDHEr^%8XM3TN+vkA!n0mU7w0zu*21zxD~4?K+MTRG}|np{u_aa-{Hagd$=- zg5@|+HAnO``(Wd6rUB9Hds)x^C#KIMgnW&6e<+A)yrL+q&+B?6FM&a3O@rt%xoSD< z@K@ASA|dVA?~d>khd7-$ zq{7yL1=5*fU2_az?5_~^(W#~gS^NM@HTz13^JC~c=Fk4350IaCPsl?Uq(5HA!1pRx zHr%o&%$mAi311K2CvPAOw0oqJ=2E^aO*3xo#2fZ-p!oM$tMYtMQO+NFL1|-$AKJ8} zbOjKKn2mpwmG3K_Go>4fQd{n67VZ=mG3uN+^o3N%sFsXs?m@L6Ir6)Q*xFU7RlZ8J zSBk0-PG78xMa|krA-%HSZ~Vk;;``+G`cv9SyCeNd#M+4xr@1ZOKBH)N?{nO?W(009 z<4Ok14QEHeq$Vrx;&vduc5*_`YUpTk(9&`Fu^!iAA<-I#S?zCf%e!ru)H{cCJW*Nr zHlsTfdju2t&TdH+@0(`IC25xx0^aHwbsPxT+;9EqQc}em@qn#`BT&Xht~Fo`-7wNk zQD|(S>uu+Ok$|%ksAyV~wfvZ{1YeLBTAk?Wv*8J5m(cTjgLw za0H5=&kC;dn@YDx*zPt3+zYHq_GSg9OIk$>=Z`9m@_hUB>}NY=3y71~3y-yq^@r3q z)fXjU#ldP^0r?>j;J+>br`)KZrBzY3bYKT^4F=lvSJaE*H-M>l= zM32u-PPW*@;M88`H4XY@|Bj`lJP|VX(W;nD9ORxT@}-nz99Zn)dKpKfey@wY-WIG@ z$(kcGE8X?1Ad6XByyjaeYi??xmL?7BVf9+NLK;TF`o%W;<=CrZ)`ORWQw11aY>sMN z_wbmCP)Wv>Fo+iEj&|(^R&#w08jYNJ1AQt2t)0ErV-;7}$EN-gxqhk$FPyc370LC6 z`We8Aa7-^CN3Ja@M$Bgqk<913NN2RV@`(_56B;9c^tQzKXf+8bh{yN(h?;G!>E|0_ zwNCgi8eju5;(40lzv=SATq=FV`}W@y0=*pKRI4I$RrDU#w#wN+LMo;^C$~NqPA&7Q zGVXVS&+hsw(G68{5l2H*VYu|$l(!{f4X*KGxYeP$qZNga*1Xvui(hY7%<%ra z(l{*82p!7iKUmx}?`!+4AGXamGs=2MVds~e=Y9P^KRzt;t2wpDN)u62+temo26Ht> z2@Ouvgi8HHeZ{(djZgm zm|3HP^WDXH+@-8Gs(m;{HDN^WqNmP3HVyflHKUCeTGI2*D!Soc)^3}96HWXy`jxgh zEjMjlUM77?*7b*YfPaj`R~qV!|t;^4%hn6Gt9^}pSMtX zVl%)suY30Jg1c!4M&I%wAOC_d1UIN+Kic)i zl7B!u%)XUR_aq#WM>boKG5YJo@YnIeUsImHwv`0}XThO=C1F-khui{Ob09Es3B^Yp zs|hpos?Xfx4qTOaq3(OXWQ%)wHarCVU@IInkbU1T`sM<<6{hH+j|iEXX#9S!yG zMevz7i_2qRII8R2Pe<*(k+DrjCz<`?IV9|K`nHXGoSUB%$w?lI?*g6N z+;jivcZzid`aHHMlOE$oE`;TuAWz=(SA`bmUJQ3>>#|WA`WcLP$5}Q=Pe|KwkJCuX z#J*!=vfI5_Xkyx6^eyjaIy|iB)SD%ooSK~?=;7{oOOv({Qv8Vu^18?~LjlE^|HV6? zF}A+H&tr}FzE|4Y(qF$f7={*L&EMjW0axqHVtfiWIGnB<2dY#NQWB9-FN!PtV_7|0 z2D%)J(156a*w(NSaAkFTCVfHx3YUuT)dheN*6p)Ce_4YPFx9A4O`zN9R1KkKRLOa) zYHU{RA$Hhu%5hi$tdH$^-RL+Xi zq_n5$R9$v~(>>|)zDrsiQu7p7T_VjqvOcZOmY zo#i#gy-6O8IMo`BEmAs7Vrm-aGgiZnFaNP|Pvc7%HGx|Pb}4Jlzd|QjoY_Nj>w*^c z;zuRD$h(-6#;ui4k`+c!XQe#M9yYUl;nYN~b*y>RSE1N;hU?Ah5JcgdK97Ve{)J+O zWmGnZ-8~eMd71*&e+O%`G2dRhsSl|beQD|tQu1@tjI610?#|K5r!ioaRL%2hDWdrf z-`nrV_tpI6(p&M+`=pSZ8=LakhnPszw`5eQ^MK~N3Fwar-ZkD*hUiGdz2YY^e{-8Uh|QY$y2@LGw* z%k)lRbWOMvQ+u#hdG|v&j~@|=1#TuyFN1gy)eUo5k5g}o@2E?lgO3?UC-@%WSma=f zp6cYYp)T9x@nYex;(sc&9+Ib&F=yW9Kd;?l%7;P&R<|_kUaKBjM2XD0rXFBU=VMZ5 zpYNSIUcO?vEOp&v%J-X7_|LT^dMeU9RN0*BcCh;Rq4v{Iqr(J&j&+X|nER-G-jxd| zs0kZ08W%ZMWx_KAT2?|umnJ-96HQeCy^RuNFcB0!|A`_ntbJv8=WvMws0 zj>sYYaY37EGk>$39_L4PRZ(foq}-xslMDr#tC&YAYrC^bbEBxOO=H=|*^TCF^WTmv zDs1WW=X={JNaN&x_z6W`I!U1f57r)rcxY^Ub&a6zDB%kQ7`mDgE1goCg>n1V2YU3P zy7RYb%8XnusEBj4;x&rIC@nMdw3Eh9J+&^Mcweu2xOQ46RuP{&n-w}1Wj!k3OSk48 zFy>DF4B5iVQ34%xS{gfVUgM)Q26EKyin1O1i_r~Nkvk$H#!JM3$){{sMd^?aUzEJL zmy%j0YFc7EiX7b}$jq!<5dv%!-I&y1-8784hX&RaWW2G1=?`n-KCT`=1*TuAEh#S; zxd6>QyV7G|?4-K=or0KC>Wi% z8Zb=&@8niCbMsh-a1Qa;S>K$7-53?fj{FcF6C4$7KOR4n^`qXaYjfWdOuklA=ukRm zsvoyhDN7LJJ@;zuul)u4L~-|ipz7ahM{(~`EhqpCht*!fQ22KY5s z>P~V|=rb1#+LiM5S5_*@+RFM5Nr+cmRss#8d0tdQB(*!%pT?rn+27^I+kuI9ctusA z=M3G5b1+ij;~zgd%)t!dEW%OdqHpUyz*=4I;zIOCe*0=HmZ2bwp z%N3Ps#RnTJWL~#MAjitAlM=8j`pm7B8`WQ8 zrHTB6LiyhLod0oPSM`>sg@3d4`Chs8o))4#|K%bsE4d-EytA6ADNtaW|9fJNf#>Ep zxowS9)QH|M7@mk~j{YLFJLx*QewC_Tp)hulor8=v3=ZM`P zExKWv^{Co$tiQ#WQZ%{&V|2jXDxO<5rd60CBWCh+XPrzquF>=7CeVCj?wagxhihoM z0G*gh{#79OHZ{MS3o0Mk?Bey8>6xY4bJ`L1O+5qB7-70d*%}@(+xkEKO{TC^%Do25@K*?eO2hrWG;FObgJqf!?xUU(neYvigr zh@b4jpc|M&W0?!h8*l7&=7TqwsiOit6X$AT0yuFW>M<9c5jd6XDCBJsao;m_i=Iq$=hKITK`|G!E|E*4-mzNI>dR)8vQo;NN;rF>a%&!?5U z$*fH~(^bQ&fr46bYdf`D`3xrK_b#q#&bpeQ!DpBy_sORK$B}_ln+~S;xO!*~#H!Bi z-n!M+l!Q9O4=tMZQ5My482zQO{R5abWNU}#zzA-1#ENmBbo^w%LUJO4p~rPzY_$rd zB#zE3Zd@#c>z7PV2NsDcpNKl}xbprU>y)(r>D$>h)XWqps;1vlXrc6LHME4BrhTDt zkGIJ4r-8siL+zl*;$FV~$gl8E-d`VFvUxAMogL)@3(f60HF5{rW(X&0)I^1JL=t&HE?uy*mr=oxEWzA8+|(M`5YWADJns89sS|@;zR7L zlf=YT3Z&GkFS`lrrnFz=eIqqZjc9!y=?nKVR6dzwosY}!E*>_kLQ{Hu(qCHSp74A( z-?kVh$&`|~zAx*2q{>6-M5bp=&EBV=EYMe<_+`fecA_(~IJ*<_Cdo{Id?50cE3*AE z4RP^Lh=4&VLSR%SclZ#j&f^;9aN_n)eb9K4Xn|m5QBq<0+gDhnvcN>@0eX_Iy(@ zoGo7!AXRN_V(_n79pvBs7(e<#;sn?r1+(e4 zA&R({i5`(Y+tUku8WS01ulLq3Cpk+Q4#eNPdfR>8KvTTsBDr|e97ED;|iSa)jk?P6jw`U6Ft>-4ri}R@DKW>VI8(YVcouBq{W+O z-ny#+HI_av{TU|N?+{AGq}j(z=~-lZJ+0BNd@-r)i+JX1=BSAr%c%FgsnAG|rp*M|`f5Zn~0g;l#x^O;SbD)I-kv8 zgPR}Vw_krA(sE~XMGs5b{p)CUFt~E~10NdGt(87+#diB9 zP$_+WWn|ryzPa92b1(TKj<6<_#e?aqtv6E1?1!(OT8G_l#fyn12}6d!rsYY|RtE5r zU-2>1evd&Q`su{dlUKF=C6DmqNtmQ|frLeYq z>ljr%y&)P87+I{{vlT-~VF((X^7}hTDiP!YQdr~dow*R8Nv`Ob@9z4ka0sbd9k1%5 zVwAva%jYJ>;uO1}>C>7&~lE0(nuYY$xDW>*2no#U9L^KbjBY>1%l< zRd-FdOM!I|FzdG|e0C+7m(UaAEz-r1du*OQuOF-W0K;y^fXy(hr^IseC<+*ebcJ@U@2d{(nFUmapQB50vLWYEsx*}RFYdcVJyTj*9I z+v%Wgk*Qc|y^u9kN8(E!4mrJ&DmpQcxh~G?VF?*Q<))7erFm5au3BjTdZYGLmwYI+RQejUG2cl!C$Ly^t zf+xI5n&gryT5j zk(w3kJ+=w1$W4*uYW89D7%|rq(d_~GacumSrSs*^xuOJ@_KmSr2Z%SLa2eu~;ZBsw zX8|vw=s_5rlNrZ{JNjHUS=6z#OdVFZMLyv;^*a)=zYsbxW=$XZKzw6CFHR|6x)MX# z^3Y)xHKnv&LlDU)g;=J2!hafcUM8o&m~WLa^gaZ{zAR&rek)ZN4pszSV9M!P9jRAX z4XN%t%1Bvk;Cp!YOh-UyfopNHybSrrBej>v7xbGW|0pw!v{7qd{0&bPiAl(9r1F^E{z}+g_Lj=r3w)KsxCH=9g z45mWF>5{fY--KO=Y6_xH)351kq91h+l##g7> z3lh+TC4bv92TRT8Zw6|c>VNq3cV>dir#~&{nRV-PI-OitJ1Wh+g0xFl&H8$Fq?i~t zZ+#$LO8eM4{II;npeadoT0y^#@a?P+hbDRjZS8$-R}XJgkHzKXs|pEszt z9pf4t{LL9UV@6uq4q8?EOwY$ib~GY~1ypci{;Mghba&y|-3!|uL78&P*XrkjtO9o& zk%sI(aac{CoNp@l;68asfc-|}NSl$(lX;8b)YzePmP3;S?St;~7bj;cy6X4-Pm(kjg8PzyV3QIk_@r`o({U z%55}-bQPv+ZNGl-wcZ@yM#R+BzVf^8z~*>mkl!SDE+LG6Dk4We=Zrj$Ku>_keLgQ!Gh;>yNq@*(L)WsLNa!GH^tKFPr`9c#yyp5sJej=qyW{7Ng5FpbD`5%Sfs zTMlt5U_tmt2}s&FHr~mYy%P##@A`R3vA^S)TG7>HL(AuXX24qV&nPrvl||#q4R!<7 zZxzvZy)Rvzas8JMWWbN<(sv{isF!$FD`8Zp%E7_$@oA6pR_}mD>g4!-<(4f1>R$BD$?qtczaO>k>~LI_NZgdw^$q$JceIL5;GC$fgV{#OW16HYjC39Ipf~N>)We4oR2ln1{bD&=;_5;1kWdZLn}S0{WWS2d8EdErz0gM&?xPGt?}#x zJZUG}OiKM@Anbi*56##H8AXrSwP>>9aJNwiRmFxC=eYMMWNOGE%QLKlYG9<5;pWcT zkHevGQ+B)UqZTc*T7mhP^|KV0I9JSMa{n;a zaenDA7)>V^D7RsZ8xbu&$IcFZY4lC}sNULQg>2{$RA1DfEaQ5TeA|W(RNZ<_08YjShV-G4h`J?H*k>GOswF3h-68`%mTmt7R zbWxDw$s33>iV)*|Q(N2JLzq3C-RvFcqn*c{sZuAcO}>j4;ww0L>mwlv0BcM9=gRgx zrjTj=^dvK%>b#L&eq$aF0q`*q{aA_3*rSz~s#A|-l!o_|#&T^ae&b!}|MW&3@bnyT zWojSXJKxl}3AOtB?q1fnUi!U%fMel1Ad?x&oP1Cc&RVGFgK4 zym!Xjt$QZpv<2AfQF*hC`r^{t?Rx|H1Dj(;-+fia?)&&}Wee^BJiMWf1}Jv!|8uVRCNpr6JT zaa?1)dM*@YE1)4ku&Z{bY%%9;h)6yiS9`MM-iLYfH^3h{dJBxQ+JAZ&eaNcO*X=^M zc|A@*&OE1K*d1E!EK7zQD8BN7d1rkXA9uk$=&#^2T50l+Uoqu)V3B6(!mIq{(>{M8 zpa-aR7mc+Vdur0C8~?42a{QH-(5RJg=rYr8@7J&mskDAK6WY3MdPTId3q}a%8Ixb7%Hmbch!6jJ8#lILGrT{=u5eJRz3q6qlbWxVz9Ej;E*ghs9I12k`YK;4@z}n?xDbV( z*kIw576HUY_?7{YULqk3#U8d6?;)4DG=oO2fs&@AJD#vz&9u55nl-YUC-mMA$D~op zrf0Gv-bH!cTVx9>pN#nITDYK}16SVUdu}I#N)dhMC5D<+Z&pl{(l?k&lXf5ZM%T@b z{`RgLC-USHp`4H#`1LMjhlZm@qkn!(;D$25yQ=(^LpqlLQ1xAIJm$z*g@Lg($E-XKNin4Dn*~!?X8?$w> zuu5WIV*hLue{^s40**%vw0YGdOG(%}$S-AfRGX()r#2i{RDL7cptDYK#5$!}*(%$+ zz?E@pF8l{4DTm?$Ljxq6hDY{Hx8uA~na+ez8M}trx!OW)^3>OwL=7Ka|1MQm@RXrc zp0zFL9U2dDamkJnG2H&k(wbeDvY8YpE_Zm?an-2EKOt=?6dSfA?VU* zZ``*oONDD^q#3gK|2;(?0ddHby~>js56e1V3~k7I8du5WJ|+`0o0F;pdY%~aKm{nE#8>QiOq^MHtJ8Is?K|r zV@>;T7iXCJQa+2h6*Ik(RP0lm)^SzeQ`$)Lxh-CV|Do)Tok{!pI`d(=F`N=r5xZIM z4aeO&Q{@+GiH1GRZ<)>>)4Sn1 z8$6?$RGTOfmcFaM3QaSupE`&Wskm6pXUEbG-W9Uyvi0?bTq{n|WABv)2D-9bQzS;Z zn+aVAeOoO7&vJE(TbVq2J&UoP+dn-WtnnenKO&cL3+k{Odxr*16zeCGMv*L}b4_aCo?JE`OIlvS-m{!sX-=C^Q!ipzOB)jZ&XiW7dw^K@k zsSmax>Hkm<&U3&Cam{L%yY3Fyj=8KK{Pj&{MuDqbT!_X}qfAyOzix8k+(kT@2plr& z%8#unE}^wN@n|bOWnVDDvESHX%rXRRI%M1u6(sytq@<$cqGioiTy{<-%<_BUm%XY# z=d%kfg=3sCp}G|Ft20+hJUyCw;+kaXEVl(}G@K0&y}%;4p&a#auG_^FcNj+N^gsCe{BlKXA8)-lb=e96w85Qe;swb<^?duZM<$#K#=TIoXR z;n%Vt-=H!g_Kt@IKUj$vAAsL0`7i5aXRT@|8;vwb7gJI4iwo=~TNPIO*5ow~&C+0g zX(LrN_bMlga7fpqwE0Nu7e`PhOO-b3E&%41>B$Qz`blJB~em5oZvj zp+Kg%z;p|FpV-H4m1nXQUV<0O3CisjI`>I*`z4k6VH?!NBj{10CB#FtLDb;;CvbcH z#dry9gF5}WAiJflLQ-sXR7b*=RN|`p<&uHp6uN;T&!<)T_VT^oSudtvAmON>A#E;a z?rRH`P;NYzs)?9Bm}Q;yS#pzZfAJvC#hU4Qq?|Bgch6jGw)m8&wa>z&Hc1Hy*KRCp z^J6B0pJf>bsU?||i-!6eM38T8jV~ygqswP$&YO+IuNQjmz&l&w*N(Q=jf6*X-Gyb( zt1pKqz5JDTRz4AS8KrVS*uASVqvA|H@r_GpZ$3%Yh74~E@w@N7S=W7;7HbEzw$=45 zmFf=qaA6$OpCCag;JBb(YriMtqR6c0O>%I$WL0h>_IU24eQ2LeOnbYG_M`7>J$*3) zsx7SX8uej_akzPYFjodAi8_3s zA*#kCs2%q_g5)!S$^C@Pfp}KzHQbV(J{)VFvjfjd?cO;*HMyX;{$k40%c+{P+waNV zllPIhwR0y2X<869rupGFV?3q#r<~yx4!y?sR#iV}FZ2s`?LDC{nsn!KEnqr`{Z@%U z;`~I=N$Qh6Z{vOPfvP)+1Xu;eIEs{g^T^ zU7lpF)6spViaTN9zC78t3|bZ_^kF~9$;9P1+U4H7VFE%x)?Df@E##;>n`lFWF5Gz< zOXSV|cJqaya&ZCi;7KM$_SK~YxSIBt@E#vF;>$jjJcr@}GGB#^STCz!nqA>}FjnK^ zfXAN^oBX=)u~$%P#N%lT=2LP6L4L|Xq1or_(}63RuUJry_H`Z>wNX4|vHF8Ah!g@X z4UI&fAAa=Jxd@^nVl;N#=E$<9tR~n zY?s-VI2P;DEr^cHf;FXkxocGxlv)X#o%5~Oytw69qnyBZxv-pQMY(HjM`NN@JkH@7 zfbVf=f)~ME1Ml*{<(!vCTEizg<+8Y}{dnE~3ru}2N4^$mQ-OMq>T9rlcI+gZ`Vag> z{3i0_Sc8;@Bw|=29l$=ehEuqRY#J)rGM-hIOq<|};xIW86r!S%&IAQ6>sY1RrNGPw z?;!toq<K)j`ZaF^t6o4=nb$P#mcYO4oNTh zD8vG&VDP8K*h_=bN3mFt8pC%;^&~1NLs}(V$6+GhB+d-b1l_zw;b<>3$va5k$~uwF=d4{!vS4V&TQKoadT%gV*|snmqr zp?o#Gf>t9_VLYnf<@WXD|1?s5J?lA9$xRg*Jva&ZMMz7F48D_#4%dSN{oPOvZE9?i z{-Md{Sxvlo1=2{QB!Z-9Yf04GHbihe6cJUiB-yejz?6Q!x2}`a_wO$<_4E|-KScVm z56AEH`-A1fXsmD8QMXaXBTYzW^L#d|le2xeE-OU~w1Rf|gJ`&n#Pvc2pTN><_4gH< z{xl8w8l=U=M((;|^|`^;>8%ZIOBbaZT2Q=frT8A|={amx7iaed=!$|z!EOZYIm987 zl|xg~)%cw!tMBbBHue7)^3Ni5`{e&z%YSAt`$o#&QrD_Xs)ceUnw4f339_n2$k;_d zmX+R-N^80KB}VQ7v(AAU$nBx?Tk~p4DZu_uM48jEfSayl}MG%60O_*;)7U2oBva+7_{(xQ7dGZa5we z%1@?T;aPSxkrI$oEuxD{*Ud*2`z$U@E8yL9hiRf zHR$o5GVM4M`GrVJQa(E{^$p{1OViG6o7!5oHa0f2NHv&9&63UlvufE@p#&_X6ZvWV z{ihQjOt zl$7gH_7y7<6nQX%@|Tc-9SU>lvDT~Gxlz4Vmm7V!3i(>3P2~pHMdj*qgU1;@99MnQ z_U263u<9#l?_-9%#yhJWSP$ZxZkItwgxp;4crZ{TAQH^+3c|dAPLF?t^0#RHTW;#> z4dnlX^yl&;8RrA=(6J(;{nS};_Higg**oabtmRY>Q?Ddv4)RNomJKuIU!~t4%r0NL zNOpld>;idgRt(RY40PS&@uawF7BaCpJo z82u(W6Ra%M5ubDTb^o|wXK4LbVd`lI@@+`FD-8atD~7HonYgN@Y3Ghj%63TK%;lW< zc_fJl=!#1SCR-pA?}h1R*KQ@gOUr+?!t{r?kpBqj6QBHGrTW~xd4sbM3G_+|JF;MKuC0+M{+<#`4R<+KQnSPF~WMpqpp7xD&^2 z35uvo7jp8e;x;a2?JOYl@wg@8#rbj(7=tWP2IWA?D}k@&(bDXon6@}5@F#2s%gv{| zQ|@S-uSdWr+99<)Tnl(~nCt{x2bV^a7-te>*~8_+xllw2iCAFAXfK-0BCR7kVLi@GBnr^2-&@?_0&{>8~L z0_|JR`Z48E+XZg`ni2a0Vj0YbDe$Hh{1*?O8hQqzf8kKd7e?NM= zDm%_q_1|7;`pNCc??*aN>09UO_XoG@7OL?}{awu{(yg-gcVw_CTN0@$7h5R(6StERQ<_Pt<%)Qis=L8u%W^(K1d(^?` zuRWZp!|bg@Qch(-F&wI*`SH14>RxW$#D~lKaZxb>^+6l1E-Y+K4=QnWJP}G~(0wSH z+VaEH(`<@@b_c~8Bd+`&Ztch3PpxBRD_GkC`GDZv${F^X>Jl%ub!A~djZdhQx=z#p;4n@ z-5Srqk*43gg8ZvUulw-4KXPdO(pY~K!y_K85zA~BT*j6A;E|e=_ zK}LRhkNVyjRi>XTL;eJ$ldFvUSF6}W%fNiF zWX(38O$Q-Lz1&NimS}o+1lW7|$#`6x3>)kuOqQ|2XiEyoadF zT%vueaj-E4$1vo_AdMemaLgH_>u-SlM0w)IYcLyH8XD=2QA@h1Y1<++pmxaH?}=1_ z8d7QYasdUyvp7|Z48zjzmt3RZu)SkU``n8By-4@_aJ)Tc=ic`fnRCzoLjE5} zU-)p8j8~sqGl+lF=Iw1ORxfBhZnbKlJ+gt8)6*^$#d=mBE}V+yfGgJ8CFFDmRot;D zcU2Aq0=8R2;g{RsbKOAk>lL$QylJ0vkl%x}cf7&%`1o&XpVs=i9qQIw^RFmePA;2+ zy}J}U4PBN8G8sMF30R^UHDVk)Q5pFlSdlPY(zCLhsZquji`#%p2f&USG{6aFUe888 zg*1GE!F9X#OSoRgiTkxZ@cwtp87)ms^45PBbn=IRcR{y<*n+HOgvg?}$Jmh<@Wiz| z3htF${S;l71u0RED|^oixluc4TO|>Qx{z>Avd{pUjpmH7u|zmCEP`Ml)@(Hti*xDf zAq2S|NS#c(Yb<$Qyf5ttU88adZ~mcthuWCN*65qw~M=YgNzkeDxa@Y;RCNx zFPEv8LirqFbNU3^52T%vsF6|vi{lmI_#fw;gcG`zQz&eRdZTfIFQOb;o&}>XHNg1G#L@|Y#)#j>)qgF$eERzZ?36dtmH@~fO=^=J>k=DSt-`X-uv zt>7fiN|4GYnR>W*lKR|Ry1$19^mnR<%`J7?8+K(3{IX6cmfrAt0`ldX58D-T3+pB zBkuy_uR`jWZ0h@fmfbg~+@q=AZQJITP2((;kH*EBNTqBJt{N_K%fWN4xSLlZCk#3* zvMAfx1eAW4xnLMSpyYiz*^Gze6x4Z0RZ|SExl`2VGJa?;eMKLyYM?up1FNL49sZul zbTg+5*dcdV_(~3yyeJ%^Y^AYK2-VY%xHz86FRXb`%b8;O<-N#1iu9xp&#yF|!Q#Mt z9UlBk(aC=)q>~QzO0>B@as}GSCD>ej94b&FK2Ckh1&fY@M~J8T?dHyh^?Wqd;F^K_ z5~QQ28eDZ#566|?I}lfzGAONXJ7Z&=TABCqci|1rdvP9`(-~mb2Wb=X47ne%%_$34 z0Io#?`E(?4J%@)lUn;+^<`E^QYpUr_KSlo6NU!?vyszyAi$Yeo5E18toeJStC&c+4IaLti+zFNwv#lbJPF-K*u#zVr69=>RaXtQhxV;&i zC6S6|7~E5598tZlAh6Z-Xey6J@^Hv=_Q#N{T3l~OJ-Vi5iTtc+o>k^i1@2NXSjQ9U z``c%j^YiPF??k%WhoeX1Sg&ym%nwQP(MBB#4RueGR6UaB?sP_u)qZnxo$aXZJcCoL{agBN?!g<-#tj=XCW<|X>hgARG+KT=RU8# z`Bhx~0bR;E0zXy3fNlgf=Vc2my-Do#@W>oQ=G9Wz9Gw0}xFKPS72zomuR?Pc+)A$~ zSQT|E#UiMgYUMbg$bWKpjpyV#MetMQ! ze{4ej5~Ry#8Tmie@`WA;QwHj%mWH$Y>kS+9Ss`1rQ_U&+)JuzeK35vqpG8KAY#HEa z5;pKja3!}V+Y>~Un2Sr4QdkTH)mWF4$2b!UoU!Bace(CFs6@j<@RK9X%p~n@J>s(F zZiOp8+vop+{9L33vkm?;XRFV>Gf4bn92YycH=C>6?fly^6Htes=N5WO;)Lz6x1+_7 z3OfM@ZTt$jfNpBzNcjsnEZoU)m{*93U{Ta6azc$DuWVn)#d$mp?*=%kFjjp?;pm=i z`sweH|1;9NKD__Xcr)W>|7!#B(h8hr_PZ>G|sgT`)e6%!e*?H)-A2HXQ?w&rmS>fP$XK|X z%iI-x8po@1jUIRx`45r)=EG5}{c;C87u?v`n%TFkeHYj~RHy5cP=b1sl2=V86kr9w zjYHgxXF+}hCKp&SayHDN@L2zznJ1fnqU3CuXYibZ{MAU;&NFxpX*>tCKHWdSA6uen z+M!j`RZ2Czsa{62d0hc^BV9tE1+~mc;>qpdnRIO}X5}rhqu6}`=Kv4QJ}WOAbc%4) zoGku>!x(-Hws7h{^!T4|a1KX)98&dsgL9ttgYDO!1MX)uHu;byYG%mY-g&j`x6<)3 zUxql!q3GRJ^3Pbimb=#{_j|}cj`Rbc+&|18y1lm3*6fBQJ6dDw5m-V=*F?R4=w|)HR^MRzErsOeDQVoGJD~}x~%abWLzYBQ0&ol!BIlG zw&5~48&`xBswxI4?>Zie=FlypkQfE);5a*1P{8fckQPT5g{BRIjmt;pWZR|gcoBom zuznW#%jL{>c(LsaqYHEuE}b7)!U|Oim>IV2#l^F*F6T~>l}B!|ZWMb=r9}y(OPmlL z_yu8vu%^@JY^wkbg>%G3w*6gz)2!d{z@;45piskW_|H}Odw!!{*Df%6xfS^fkuF(a z>gx{ePdwOqb5p~no%L<9z81AKY*Nk(HA!s7C#X#eaYO>U-bzv$Dt9Ed;v~q05Jm0f z4z=KNPzGwxZ*{*}VEWgW#4qG5ywKp8vT*4BwFzf6a!g;owN)9Y(rfu-sTiJ;A*)x) zoIv?#$yDHC-^r<<|)Eene|U2Nu=4gUClYB`Gxo{Nyb2I;y*zWvW5#?#hv z_R}A`Q5sy03RHR?F0ytbWwDxG8TR)uPzi9o!(h>}V7jP+G*8jpk?z-&ynTyJ ze|;4BXOaHhhwF{SL-$vMYtz=&=B8G4i|UPx2=^-_#jHf(SlV+cig9PLW zi{dIwpukJ7>v~w?TmK^e7}AqV%=j4G&nP30mXs6#s+!eQvnv9w%DqvozyDL;_a~0x ztPrW>s3ZA)+5p5sIBNX1rbgBFqFPLFX(YZJ5F#u;&T6!r+M|q|bCJIY>5~7m95ojE z<$Pe|q_v!$qf9$}g#70uW2tGU*wSxmr+#_$WDV}XnOs+3vbGy!bmN*nU{{G^Tz_`} z9SKG9>8i?IQnhveL4E()r3S|?*ag0k(VwMdPK`Wc0OKp;W z*RJLE`sDr<`OlEP@X3uF{f%-r@07Pl6RG7gIBHEZ>(f$)NvRG=&Fqi$X}N2U_Rasu zwE!H}IPvGo?I%jj9fg?i64HfY zNyeR;rT(Pb{}_YgY~;U#bb}Aa-@gHe4@7es7pF^+WY&y50ere2aI$gPrMAMOuoOxz zW|vEcq5`xh3rACsPSX0h5S~ug`ZMnxUJCtN+lrFEi8a?+h@W3%RY?DV;V_90hq3%+ z0kinEneo>Cw!)u2)|9gj`7@B3jy2`H@>pFTgUs_=>UL~u+Pql~w^z7~SYLyd-e-0a z=cz0-t^~}+c`FwRv8*_K(p~d1Xn=aIuIRS^Me9Kyj=v!P9@76DdnEdHdn;P%G)>7l zGsPCB*cB#jW2gT9>g8si6_%R1o4mUJ4w57@#E zmpz6{4(bM^%N!`d^%>nqSOIbAWD~^-KfxXbOYJEzR?LAyxobojn6BV-uP)&5TzSai zx>iwPz#3sq&8Lk-afPr)1WtnCyqvFN>e2V#3TN|iraXI)zZU7n<4k$@3iY}366)M7 zl^Af|EaN90t>eu11bz~JCBS{aS~O*g0#f6FP%v!COZ=sw@~la*31N!*eU7+*|AdQgk-VNyb$?%J>hBfg-$VMq zhj&E!Na|1HRamzZ$m30Pu$A<523y!E*o#)VO~D+jKs-7ZEYHEptfLb~D=QvHg&K~_ zOZh<;Vz_(`MxwEBDC*!~*bGmpD=B@S>HeQK^?Vuf*CO4RHn?qluWrjA_h%Jubwy3$ zPXC%RRKLa9!XAh1vsKE60#V`S#!K83R;ngZi}p#}o-MCJsGQ+p8M+>S&U0|27m6&H zPR@h*x!8e&l_4<{k_MVeVfma7pu@NU1e~L*7pVnJ6HALSgqY3k~PnBxt+8SC#F9+RO93s zRe<_4tZTQxm35d1(_YsCxQN5t3@)Z-%-yRDuA7j51nF@fuH#ng`BdNcd-ZRF<3bIv zys2JA4NP|O-#cLO$BNqpk|yAsJ|pl7*VV>) zZB=hwt4+QA6!~8v{dTpfw?FE78#-@?theQq0)fm*xsOoF7B;i{g9%th7rEwTZr-OI zB{#Lk^yi7lPeGc##?1GF-S^+v(AsvCoUEEjz`qQ}oBF>DF>O)|m3$ zjr>8RXV#eVeW_(;;?xYhzpBcY32M>F9|76^R|MqCSnRVl`*koWPgHSu+Z4tpOVBOA ze4O#m2QNGV&H!rWJQ#<~nvZK7M@+%ri~!GyIIb0*7{Z|jmjSsGX9XsT34z&&-&6S0 zCm8&jkl&8fe1gG$-U)jC%lK9N@$2yG5D6u$1Yrr*DY{GXBD_2Dbf z_j%va=SgGV9)M4FFRU!IsVM`Ztg~yWzHY=NLU(|@6Dfugw}N8eNDGq8e@jN-P|qsd zf@8Iia~hchk8(H%=0hT|faIi$6wWOt8=RLS{~e?oPBu7y^nb*;Ff&N~Sih85%dj*5 ze_^Eu&Q9_*f1PRfvB=Lss#$07Ub9Z&b^obw=6rfM-nvb==xV6f;rN?Br&anRbgFy> zS!yk!)2JNsHn0NA^@RMx|p4ZT4tWW@h8h5=hdPF{f@FqyOnk@Y2`x_ z=T|FSP|OkNt6WTiXE|)(Nim1t&#iH)JhdrRo_BoZ`4{rhQ#i{$#gu3DDXKh~^Q+-} zKwJ;$UFIuN?c)^xY#(_}or4|OVzB(J1iTd^iz*@5vY=!$M)MVvJDm8Kh7F1vxRQ_V1}Cj?lM}zYFPJAD-W8Ji~Q=T>RzXcqk5_ zuQ&Ga*SS=x?I2&C#y0J;*dOD?h{qGtK~+&iR#Bzxi7|)&#w~y~w7s=nT*~=mu?#Nd z)?|0AGsBxE#j={w3U~EsW*jX-{y3!LPcyh%PgA%%2g?uHuxnv|1*R{h9j=9JFy$tc`z6HX=i9YB?0fzFXCCrPk&fA5?zMo+FmKae&;b;Opepj@A0V z*7$LaLH;PDV``1u?ph`HeZ3#DY`{HGtkwR3Qq~9ei4TGI!5I1cctF1V2-xC2kKGPs zXsykr_`M#;@T3tywH~GoL2{1r#3+~oJsjeJXxM`soQr?R# z{!z$}Lz-A;%D=QumH+xd`gy~dGWiOVA^R62?Fp2E1-9J9wF6<#cAOwK>{d{b-_w({ z{inZ|jeewNCE>n}!@VYfX!z)2|wCSJFVMa2qB{{>a ziY&6R9#Y?5Jz3j-8x5XG$j?Tax6$BPuHTOjwysF`<4MFv#dtiy7N^;Zfdt+3BBJ}H zr6$f>yOz6eqv`h#A^$Ye^FFz6Xt|kl=|gXQo!sLx$;O8DS?{QzQ-0f`V*PYdhT^1JFyy&OXRRixK_^23{y{LDGZ zK>sr7E8B3EipDdn$2#W~i}zSp1?0<(*j2kN_L3Ne<0_0s*<$P=w8=EuZo$>@HXNy= zXzSRCSx(?I3MLY9g4sA2;FBA^4{My=y8R9gh%?{T zQde)X*Y)uKRrA`fP-md6wLh4|nKme+Ae`%tj_1G>Q6aartpeIkO+cjxdRD>9Tv!2@ zQq2!T4RbG`HF>g_z%Ss-n10mGR(Rb8Q?EtHS0RmU@b&YC!~0w9TVI2Bvuf642mhst zhn(^e@Zxk?Xc`1L*cEn;B`i@CaAl4LdUPz(`mfQ{_kQFb zLps=K>iea}Z?5n0s8wM~_qvwn*YWOk1#DS2XZPb=N(qA}qJ`>`^?m}JL4TKCtmMYG z7`eldABQw?i;;WmmZ9a!V7{$wbux)jLZ)w7#FpXw_nN>p53Zt}Yzx(z6AD0aJembO zNLOi7tVhf5@X5aq`F}%t!YBWiTZZoMn<=UR>J1emTY{(_h26fME$ig$(+r3lE7A`F z5((h)MsFOVe3<+?*1SZ|e_PEuW)|{`k(O;Wc+T0X@C=rRym@C!V}r!9DN`#V{tvpH zJ&7&DiD;h{!~uw1R7Y!eC7&<1h(q$#h1F1qi(XnNrh+&f)QIPRXC}1caoGFVXP1`7x_AuDY*wvH|_EY@~xeo zYyTJAp2H{0uVtxY6s~R`u2+$N7wLa|xJtGuT!ZFMSGaceU!qCYF2EIb0n#R2#h8)Lf2BSqP#cY)1vT|4{6=JUbQ$3MjWifU9scBX8kiv&MO>!ntLe&;JAY ztB^Xj8JsU`oSA#Z;oPFH!zqoH^3qqzc~AMz0`et`E$}5 zhO-jUKTy8N21d#>96S2YqJGaCc<2w7kLm z&Pkq%c`Jv}jQN7Cs6lgHJDsDEHcHS+qf^WKbi2{B?hekfkaBkT`pu4^^?XySj=Pyj z^0%UzElyC3%^+520y1%vd$hbQJ52e`M*b?K4xha5?HGEzHa4{FsBhlM%B|iDL zHVs|hjZF|05&JUW&cMdz=!MInOe)*sylVd~MV<-gNp#@|1Y zcbhp2HyimQo7G=r_P=(&IZ#jRYHG!`WxZ;Fzp7)kB*F-=yLb}HJQruI^=M88DSudj zu!=B( zhFgf8Ur;#1>Cm4qp;^n_a;9njUC3XEbcs*yJ^KAY*Y%k&x9Oi!zZ=h1&<>~!EM0Dw zV4ts~L}OkVt{VlXj6h)vYk!Wom2=w0VC}1Q`F%Ke3uhiuq{ZMUYZ554M|JT^+=i*AhqVgL1q-%|m+uLIHSwBMlpGaT&I5Y(-D=9Y5&83w+FOmh2erIG{Vh-)#q3;p4rdiP3x$q?vwnpRDlB*lF+`i~K626LuPWbvqBoH!yE`KR!8^%v%{HHFCR6?lY7{ z5fd>0lIr8^13QTeza$-b zLrAzXX$We|T*{LsuHbYwLyy{16ps8|roP7^KMiT-E`wvyuA%E&;mAacNu)|-_HV4~ zy-tF(740#O#A%{a%iFul^rwBu--&dOPu`=uhVD;|nQ|v;>#>Um*@|{FuuvA2xeT%$ zTxTy3^I2-W9{;}bMRs$Rhg7)R$eXlV$?MNUHSnIej2GKqzVu2|jpJ}q;_P-OA5s+B zC5+Q?Q2Jd6pleYli|MGBwfxI<&mrbB$j48}eU}tn-Y#JRSEn z6USojfO&LN!{&w-ZTE{#{w%6g6xhRAi-2LGAWj!15@LFGFmBli%C>tp+Tf_bYipJK z+Vf0#cO$_-3(WCG@=>lNPk`37$a`B6yY&Nq1H z>-RHu`a1*aOYXZ)mc3v;>ZEZjje7VApk!>Mi)9E%in(4dlw#`9a`&EZ+UXYL_ahzf z$u0eslDi(%zDOS*xIeN>RuhwP=)Uk|9J;>&OLs)sOY)Xb5{3iqvTwlJxt>D_jE4}M z%FH*O_z zog9!60N&=}e}KnP#u-px4HL0IDclmU4{%Y!bApcp>pfkSyZu{c9=HzqJCW}BmMM4q z0#)wLfR0Bd4lg$yx%dkHm@5nZIu^Vu#I6kxa7z#+vGBvOD94H{Xuy_`MI`SL*G&wM z=L-mwBUz3rj+2)Q^I-y%iQ!mb^Mq@WAJSvoQK^&Y5=6AX8D@>lb#T=e!yz{b{#!s1 zUmz~#;!Q3_1hzm^SpWH8yx3OCW+kNw1`w`0ByyI}8?;S2Qex{!P+D*G|NB&ZzD}3^v z(DLs7yOPuS>DTC;mWH;SEhJBL@L}>mtx`V!gUgpur~z;#B!qMpQI0@Cu%g4Enyy&T z^$P60^T;(Qk`xw&cdizVkQOI8NxN8zW9=9@{J{+fC zr2e2?>wzhO0dd=#G94q?$6t4(tL*z0OZP_PHT@t?6BW4DLW;(KLJ^kY=+M6rxtgnh z3F^ON1qtX52~?=Zl;|j^;RvJ z3q1}*DHku@3P^}NrXQ(um7M(-oALV$@;^j+@nTc1pIU$l4t)gtk*1$6g1U`DtSM0t^OnX0s{BuYz`0zM-Yjd#uLet*r znpDm2$XBt8o>23y>J)5MQeJSZf~ZF+n4)AN&=o1jvn|x;K>;FYM`dQHERSBpZdh2k zRyHikgDM=X<)p!;i9MX31S|QeP%iT$jmm2&BHU7c&+jaj@;5+y$ zLTdc`s7`J65Skz{_!~!{L0E`|pzQC}sAC)m+Hq0tQ4R_REQ%c+gpv99ezmZ&Dk9j| z*1;2$(jvr^a^wjNKNAgz`XRFXq{*nh>9N1ow zy@0Y*guS5Wc$850ELex_t#RzV%=jJLhWvh{13nyYX&l9`4>JGMwQO!`X~hY%SGfoyFe-hFudkxO<`s6`;uJAqf+1KIR)Wl?Tw*w#}xjm(Vygg^LHQf=mpBIYh z*uG~$rR&Nwol+jLU3)U*dBZ89EVk`YbD16qoeR(3cU9TOgd%^Y${!W8j+9=u1c_Rn*8 z8~Ev>F7OKu^Y{jFuCqkdZ~WU@|6Ojz{r8YRfYf!lZ@qN+(Bod(A^Ipck=lfvz-1@m zh+jyqe>C2+fC9l=sQ=k1qLOuJx$YH4ZVB=ukVai$={D&=zlJFyqo>0@OW${-Yb-=md}TXp8A;FU*EAFayeb|kh!E;}*JF6CrVS%F+SAyqdbJGH#MK6y7Ie;3j{K6wuxiM$=# z4wrZJSLO9-d7oZs#&PH>&T^2FR~dODuTt^`+kcbtHa0aWiQ`e?cy?klyB#GuP~lpE z3IU-Yoxze4H@AJbolQ5BFO6ChWzsd35~Rf(1CWC$yJzkt1ZV|B$TQmh$H=f zIh?{WkDK(wc8$T6hkO|lE;ajcjn#QChF6f+^mEgFn1McTCu*H+=1qWkSfZZLSj&UW& zsu*TpEnk8-89mGGLVi0vm9yS`TK{(#JzR|Z2&B;+2G7in!}ajj&O4d?>SX$EI;6&~ zf%ea10or=GgyW#I9IS__;(T7px^C9`zr)nS^>liGbeB)=!&>fO_u{17hRtZd_Iw_>u}gC8Tm3C3dh}edkN*gkxwJ7zRut{<+`D9 zENyBfpHP-rjIT?vm%+Cf@6mEPuQT`lx{!Yg={cXA544<3?|uFFp#30~XRD?Mu$yjS z>v{t0Re2~FrWkx!+$tCgBcy3KkB)&uxiWj2I2LaxK6u+BSm`(JPT zD^5gy1JcIp4ZdyHD|{V;?YBsL#&E1%vVqq+Y+Wt;5_`b{MB-3{=KlNcOh-67c)igZ zKSBPNNWbyPeN)TL#98{vd1+I|6*EyYUOH5*L;Ea{kf-k!oes+_QTN+mH+|)!0+v$YA+cI6oo1Crdb=ma+C!4mX z^UyqBgs-#>w7{|4DALWGn!~05CH1(h9RrK$(i4=5c@Pge%9h3TIBIlUvz;nF=CBc} zcp?8c@YaS(VZ6N&wAU#1-+Q(G^OYxhBWJ}(sT)msE?4d%{rm1O!NB{l(vQGbp359r z9vmj?+Jme&Kyk?m#6Sv4ZA2waVsXZTDo&o>h_~cMe6ie!mj%noMcbwT3dK^iZQKBD z!r#m(bGM9G`oxw& z?48X!cht)S1t}V$hiC&(KGOPoYi=_2xC;4GkWRbF)Z><$l#D^+EZ1$?uKj&7o9d_m zUlw0E&(rd{eDZ#X{L4tM_~iZP5z3o%xWHcz6xgHXrS=&;Hv{>(NHzP6yk+|R%zAWS z{&SSq(y)13Lw#GOl+CBIb2=eJYYrgi~J}YH%Kl(tQ`~Np!nhh4kVU-GfZQe*uhReGlsL z-)zc18Tt80i*7b}cHew>`M=^PL0UfJyVuTNk_(kMTi*w4Rnm@no;_TyLFiw0h7*+N z?^tqG5do2hkRvu_9)qQ*mKNb^^>fZ@A6EFfZ#MPy8|2?W`Y#{8zui1^eNkLra#LyB zse))-9YDj)W9zZL_H)`He2&w98JBdtxES~a^3PfP5#9f9G4*o-@*9xqZ!z-Eyk+Ql zPzJZ$Uf;A+rH8M+knSiYQ9c@uJc$*thI~mwNya7uiSE{N58h(R{WIkM6X_2=xv}pa zJ`M)1Cs5?}?M*vO%luxp%v@RWLljBZj=)-bIM6{w9H&M!LEC!s_PhoQg*%as>6HnPm)35BE2hlAb5nTHg;&EQyg zo5GQaLq9Oi8ySx3I$iBv0GdE$zX|}6#-SWwpHsAXlnRgwvvCzX4x4GDpd4HivCEVs z^NLB?1OsJK-8eCa0v}b21Dvi2j^Py|D=G4E<>k#2X%>diQ^hOzaXa!KY!ga;`RrGRHN`G&$V&%r7?8cvem({WJizuQee zo{IcDqy@Jd97}IkI0oAvr+#eoi;x$>vf26?))x>khnB|5fwo7>>+s2Y5cz{h&-mnh z{0;Kz>smLrG;QCoR3~iHdad@46gBrVz}B+ZK2Zja9gfra@_r+f;JsAkFT=x8|%~8eC_<{0IA7p+3WXOE>uTLy@MP|yy=i@ z=Qst$L8`??G-Y{o#POMe!8)E-OmnBfa~bmALAt?*=le&1r@pEA?2PB3sF67i@?^j6 zwS-8@www-;pyg)K38PvdRd?(0-)YAGzmWIt#PNTpk-zcI!{?2G@~NeydujFafaB>W z*rPfv_N7%E4@ToqlpplQLfoDN9?!uw_Gqk(=*)NvE-B^*CtF7a!(+WFy6K1iLZYel2iSw=X+r4A`P zGww3&xB~f;kWRVF;MsoH(Cvu5zIn}-hLf~*N~BIgOqFs{dC#F_x#K}+61Jig)_6Np zk1j3$;9W*PzJmO#NWb^VfA_AT^`oo}KY;jx7>|e8`daoW%BNh*C8!nU?fZrF_dil{ ztG{RDu0Vbr(rMo_a-Y)gXZCRh#;^33`=qUHTUIx0uTuud-{nsB@i^Em_KZtAIyur< z4MR%0FGX>RPeB0f!mzy5IF7Pf*;#B!_zc@|hj zmK_c_6?6h4e$Jsa@H<(cz8~uWdbcT87V!kQl!O}u##_85yD3R02*8u@e?DlSys zT(XHMv!sWWl}p$Dqzj6`Ph>*{n$_ir(C8XmS3B_n{M$;}3M+z=Fs>?-fYmi7!q{wa z1BbI<4zJ`dDHrk1pX&a9k15wO;U1sed(Y7QZ+j-uu!y%{#|uhB=0#6XT2R|X z%r3?DbSZwVJdMW@C6h*{{zLbFpZuR7|0|^5`Q%6Rh1o&x6G{2y694X5Zf6?kr3WXsc4&(4O39V0u~LqtKks-GiZs>~O2lsLrscyf&Ccv<0Fd#}+~ zrz5``>AZUlzE3p1P5)B34zU4#eN8P(>gu_=rP_&lk0U0=o^4=O2UPxJAyQ%>99OoiBUs_f7jWBY!^9h2Qtt z|KA_FeeiX4-R6cgoh%$BcYbSD<2-k|%>A;y4-M!@5^~(x*fO*liPB|p+Pq7IgE+)b z5+k`ZzghDy6`ps#Z|sy$kq_+W%-L`7EKun#`tL6fw0mVJ4&_Pm1}#W_fKAaQ*ozSr za5qn0Uavx>6|t+ua8W2#7LF-9mdK_U9D%|>m1{XUp+dQ(Sisov;wZQ|<9^FJf30wK z>^J@94&?7cdeDdSR~l!=@93-dnHx3{Op(46a3!0I(=)IaqXM$+DG-iEvr~{8%>r6K z5$32`a#uLzSZhmQCDd~jLAU!i3Qy`j(~gsoUx2jaK7;4m`u%*}jt4#;h-X*B?zWaX z?Z@(1K$>)SQ%4r;u2>SsSr&CWc~^?!pSyMicG(J`TqI>M!3)|6tluDAXh^6{S*$^; zFcXB0I~CY1tFSQFb9jN{v{@RUBa`Y^75-iy{tuD=6zOvx{_OjQ?uVONnwq6kd-Ylw zJcQKLzIZ}d9yt%@2wH?%j>wAB5pxkt$;1um((-HXH+DiR^5-G7-*4pKuH_Hrk0-;` zPzB01y#SlESekk-#sx0JZBk7*L?iS+XB@;RhcspOih({)N&lzr|M#1I^#$_c0qp+| z`1T7PP@f;neo{Ns{YX-!Wl^@intc)%P)N6{3v?W(b}eu11E$=Ykv|*he4o5KwY(XB zRdV)y{FQzqyG$3q7-YKa0{L7djkZg(DEv(kDAx*dvJ3$w2rZP_z$$VAIdtz}JRAc} zP-xMSP0wozSKkAsKl}^%-~rAe2Mn%72ZrtsWWOjia7{o4fnMJeU=L-{tdS#gewNA< zaV2gXdu<#I;39}&U#4JQu`DYe=M2?v9 zu?izdIFgaiqLVNl42tP8G|$Z(=jze$2$HuH}-6>`;2b_k1zpKzzD zS0Q&?i>ydaB^`@9EVY=Ii7uJ==P_W3)1VRdNQ_s z9#S@2-^`v#B*X+d=tP?yN9*MNc;ua0uKTc&TY~&Zq%jX0xhFsT&ErC92s!&CtA9f_ z)grl@*pr~qG0V;(uU8QkG$v%4G>$X@HRhU z@Lr1iGf3T!7`!*?yw`KW${xPe8(T5;t;iX$gPwE0~NM68cj+XwqvAD%FU^OT%1r!2FVn?mW-O~xpx|7@I$rb)w;zA5+@ZhguZ;$Ks$9Xbi5zvzD# z`elfyZQTdf{QxUn%E?j@f0A2Ia5w2p&7}i+yBK2jG|J85A-;l0b}kGP5Ob2&$!;t` zd#Yb>7{Ql`%Xy%k+iTziX9F(`mj&PF;oQ(OJh}m8eJd-)v*Cw8d6H`T^!R_&^y@O@ zMOsd0J2wn8N(i0e2}!54|WJg}3#zwaYG{vR{-v=I5_Na@E6 zzK0$=eEbhwN67QAovQEF-fnH+wWp&!XR|-%(}1HL4_bDXy8S)V2K+e{&zA93JUish z=%d5?Qp$^-#P_0hu)*4aD*j};mr^Q!XBD~S9u?+q9Mpd6IiD zu74hgf1>CA$IUuv1o9J*COvM-H%I4BAMCu?cr$E}#}x4-uI_Vb!~3d2@(1(C>d0(* z<0Gx*?tR>}`#$9FLb}%{x99Pp^*qVdp8lWG`Ya`zdtV{dY8b}jqGG1VL)|_`<~tH{ zw3R}FT>T52TwIQ=6Q6Ki%h;z1PyQ1I&p70#Bh7xoHy=JRv^~+N{9BIR-Yi2|q;4XA z^m1vvzFbJ5NJDb=D}|ZZoU4@^l9SBx^fn_)|3lAzJ{*rC{|wUeJ{&(gG90pM67dSP z)l$RWFHFb_V-&9_NEx)snR;|+x%p4}%8&dsq?u0|xl5n?Cb`WjoBu$`pMAaL9xb=y zNi)9gME-uH2Yqs%esX9%)Y#Opd#l{nNyIBrrb9BXC`!0tX{%W=N6Cz5Hs%kSa%Lf4 zgj9CW$UFAn(EU!yt7iQxf&w(R1FW-1&7Zd1k)z9aHpqyRVkS-iC&{Rj1vIaZE1w6w0HcQL{|7Q-Yp{$z@9d#sbZWQ^RrE63Y!cPAHO_u!FWk z8-zcw$YqQ5e5r7!e_-l!GxFP!ntxz$@7A~nJLepTx_aRRkF8I$he`y6k*5Of0?GD@*X$M8>-P{Wl&N||CDC~D*| z(EhqT8ppDy42}lmn~++cGB|F~?+<1_ABLl`epj8&c>JEqK|;GYFO|>|E{-6U_iyJF z;5tKsN`xtz@@(;-j(60@)Y7u|DbpVRB>rj6!cQAq$2_fZ={Psjk@TdKav(M959ksEpbeMM(LmX{SmhSDsD1DsG=5u!gh(y7(Nq zH*>$*sJV^Hm!NzOW6u@rqcSX{E%!jsXxS|$Vlj&$>?XXZNC>Y)(4HQ5t3vV<5i)r4 z=`x#VdnaKBxs!{#In3s5Vk~QSRXGkmYs&FEw_sZZxUzNV&?NaM?fL&j;G}gqG_^ zO0JmyIzWGslgjJZSFWUBwmI3CkF$#O8F0J)Y_F6j#KYh}gyddsevUF$-V86!Eq|aa z6;wKdpM^LTJ}Kw1C-nScJqbKe%9C2o;wO90FKzMp{wlW!H^1UKj4YKV_L%k;gc$~T zPhxo-ua&{#k$Y{Pkc<@-foWtF^eex_-}$7*|2FW~0$uOIzfn4KCjC_=0u=ShsNF8q56$F@441E zF3tqviU&ts^w*9sgHvD)?;%GDq_c^~Jh9JM_=v^Ay&p`k2hJu>gh7tS*)UEsSRFqm zipNVUoE3?%^o2a+OoSny%+pyCcr1A^I=)AH4mTy+EW^(5+x{$bZW4wKYhcsaON{Mj z8014B(fw;J7uAn28%-Hp~l_nP=jalnCpR z8(?iADR=9yUH6}XzZd9%Uu(HPS8~VVkjMKyn>NPsu-}R&`JhtPb#QWc2;M@@0r~Qk zd;$0=#g`b&OtqOW(}wkU0D5ak^jjz3P2>rSAd>$P|hcR_r ziFBn(xfea9$NibWR{?E$O3VG7r=;Bd`jHz&q-0U!KSK+&TFm)vL&JSlDy$WHD%B^> ztp0^E84Dn++W#p%e|7`^Z=nCVrWQ{y;V_F-f=iSs9)R343~$k< zuv9KCD$q0rjX0X)UQdg{U;DJiZvuV~(8W({{BJ)!@cg}@vRaDJ(9|3gA$DFDJoYsab?E63_F$92SxH5xP|QCBM<-F9d!G(DL8t z@>l-m1m(})364p9<(9b()ip7cV=)wXr7Qo(g>yIX2Y~K#;XHUEoP~2^rGMorokUdm z$9|*jpy#)gbs>Nrw3>N9uFvx7uzT2L1z}k6rp0&q#gx zd(MWtSF6iKCo6D) z{WBWB`gan)`hODlo#XDaHB>d$V2~#wuCrYm6!+M^F~LhrBYQ^0s{!nvR zdXjBm3eg<#zXDKJ1ZIs?LTcIj2D^o^`#sh&y3O8bji-smbY5)?WfN!?OQB;}4xKIP zF)~7p|KDjl{1)&Z0)6^B-46C4*$(~fTc~>~;t@*ZRO|(!2V6Ni1j}TPaLr8=4zFn7 zAy(`I_-a@9<%cwW74Y>yjfXV;&4&h_2V(fb!6?53pAh_viHD5$jLwD`s>DhT;zLAR zMEK(gcvL39e+1T_n;{?!TksO)^6)dfT1H8^j=JRf3i)SY9r&!4Yr?bgFJkw1Qu@B{ zBA$=6(U;}Lf=3K-`tOC&VIi51jd%PaePM#=1KtogCm>Tou9WKl4O~U-;n06p09{5s zL!sS@rF{FIb)9e(R$Y{X_9+ppZ>45(~s3A4hKJo-Ma&_!y|%WUpx^ zGQ2M2p*$%kH;nV)(lGoU|N2{$U+kEJmWqS5bSciPvARr0h0>R~RF#rRL3) zEunaoqIH6-hv0L%9wNXG2O9O9u7^j|_x(NxjBTN0wy?{=D{u3Xw&F~l=p=FVcZ-x^rb7hdtO9@(LI0F9_bKBxEE`%}Hi(DVyF<5}MTQFWr)uZ?4wcQQ^ zpA8gwUhBK#d8uztT>iK`UyU`*m79gz)1zIaUXP#GfbRl&$EC;D&ksC))NZZZrs$$#>HB#JW(x^|4vE$o%=QJ7 zE!zPxe1yC}@z4jn%4ewg?++S(9q{J^ZTo}9XD>+ndFq_oJKx0h8{DN9$$D`9>tc6V zZ!p@$Zt;qbPhlGDOe3A+^2C;;ZKbm7p(WY7)a%D-(D0XfK~Tp^7So}ef^3d^2!8c` zwV9VW3=d@#iZC$3K5_Zp!NTd;_&CnVu`4l%{R}8te)R@M?<-_z_%ZX-@G)k2$yy3QmvR*1)(DhOe{P{r5FX(!?^o4=vqpflo zR*rk1dnce7lUH#lZl2F(iA24+6<+5H`uWYfz<&nxFBjejl~TLEd+eLGG;9F={Mafg z8z!K?;VhI3jtC$R;e?ALWzKnUqkBcf0UeCnY|hK&Qsf?UeZa?HdVvSvjGy#j`N#?z$*>Yhp-rJFq$2>kARGm=Bk@ zWlJP(ZKrORUBF)j^j#P3;|jOG=W5s{O6`iB>uJTcxb3nOXgt_hgS1V`_S(=E(i($e zMcpHAakBc7uSrI=E$9sXkG>eBoxwYp_^20~o$pN=$CAMAWAf$E++vHVWld&5UYKIB z71Z*ku=CNv8@V2EGflsd7y_fcm3J8Ql9)f!xVYXT3G4c$C2MVV6F;e9O_BVCz zsAZLE|ChAfS-_708uyZx`^=Ymw|`&t2@7YH8yG`yV;Y^yv6s#eclVx|k_{3sz({MH zu`yy7H3EKF1|P)|smJ!)w#Sd>_D*LPvHN4qO~@K4-+`BOdv^f;63|~=@_q4A@Af_x zcMr9;a(hk9&S*^|{2;Gdw$dkL7|qkfdkRe3VBe-dA!PLpz#zO3!Z3gA})t$A6>f^x;rw@th1tBRFS>v7RnF5+60;9<&Vrk0SX zDz{aYf#n_m{yv}wT;;~E`;RO4wECzhS!@CPX=)aeH@8|<`Q0zO_J99Oi5DpFXI*~$ zI=NT*Rh9LtW$7(cYzXb0RssXr;+DxV-V6TS>1zJ_v({r9@OywR{QmjI z;AHH4P-y=&SL}Rzl_3`dfo}(T?MtAD0;Wg>2k?}G{FEGcK%U-h^=9r!As zO@GyLZvLy3GnTI)`~6t^if0@>O&rVa(?$Qz#GZOFsc1JyEfAT?He+V-Q;cG;uj`ck zci}z@{9k~MxNu+Z2e+ZA2ePtpQ(utv@sRR$uEZ@ltjEnv;1>cdIjnKdJ}hw$z1nxX zD9})3bRLaF$c75CAq4g&Rh)3g+g>X7a)rWcJFLe~JMfPK{n~|h*osudKhfZUcGt#zR;zwT5_>+L21GL~3jbHo9 ziSV&y*Kez@+bM-;lb1Rdkqs~@Tt~wWW20c&V$NycHg2cMZfQbz zfP8{0u=3zNj}^iD6cIHhgHI5#JTTWeGsVj`JsBK66HL4oRLTxmM7~<8mH&H0%YQNO zR|B;k(emfND!=dV{FvBhK*8JT4PNnxwTf(L^^xmX*zY*_5Xr-nlP%`0m@k4yjutUT zGAzw`z3?b5Ix$+=*i=(p zvtiq&?ZCm`dNXi?z*)q+)@tt(Hl#4IbP`^RgJrB^ zB!XKvpTX+U&T-7by_B8JN{vurz_$!%d+d0punp{7_G8LM858L~>MiyhrcRx$;_tTB ztNH&mJ>M(_emT&}*YrHPub*`czE#(4$2o?Q4M5kyDvH6{HWO??*!1|-3KrK_+zfNd zu};C>HYoe|nznz>0e=|iwbyh#ex_vDsqz*@WBXMy7)f#Su4v7cy86xHT5~sjMxKq` z2ByIvpTP3&45+`$DGbNaMhJ%EnHYv>1Y5}7p?s9^dCyn+|IKv|7WkDwYyPJ7?>Ejg z#`23cHx>iI{|u7qAh{eqf~wqBSGhk1{(hhbUFCN7Q*P17Sji)BPd`@lK9$a%L{$05 z{-)b4>2*pnfpT8g^*8kOf&BzGPF1Ba>1AVQVeGZ)a&jdMkrImG)>%ZtlBmM1eO>Ey z5%Avvy7cuE*H^TU`nnN5T2#3mu5w=i{xzUCULQ<-Mf<9+{jvILRpm$C(B)4Cek#z6 zH%=_~);{EJgO4^zr=F8DB)eYokw;J z+|D&Sn``Q;W$HsTyXB9`&5-JD@Hd=%uqO-#sVUAntc2l<*KE1zN$_Nv9^0@(AkI>D zHzjS2s{OmPzI%bc3}|1M*0;a=;zc8C!I`TEWg8lsH`nYE3U3UOgC41HyDGoaRsN@_ z>zlAXc~k4VN(J1HVxp{t-n|KE0Z_>-4EVRP zn~^)c`M6Dq^Cr)MZjUapY05kq`S>2N#BWWRJHxTjkrqFP#J708*W%_Zkoh|pnszC@ zK*$qmR{qbMdVTc^;GY8etxKO5ls@tMMZMM!cxPHZSHW=_35)o!wPhHaHzdQu=CeHU zXQV>mroW|e#{oYL=#;lK?t-@lhpY3A#X@7&mXPy~kBr%>a9iKf?ROXO2Z4U&!ZqKP zxUsmHzlzHn(d1SYoP-s^NBCGC&3cW4L+xPNOngR=fe#&$J#4W!qnaY_c4Y8j95>QZ z(-OrQRWrv!J^oiHD`n}9nIB2_h}<8~&?Ns9FK&U{M%e+%%8UbyZMSYwi(`0o>{RQ& zw{<->1HTXG>bJE%zgPOi?m<__-GlCxvMn6lhZ`a10zHIVBeyeB+iAg&&W4#O$vd2x zP6it-FQtfwC<$yB%wkTaSkou-RBk4C>=!BZ8=eH*$Mq)!U`fDXqC1P|R+hYpw^MDq<}+vorbXemy`$&(UjqLO(C=ONmUz$Ul?f6OH-W&gjIZrt6=!Imf;y1 zQ1TcLgOpK>-h~g{hA|lktgJ=Nd#ZfI|2FV90p0Ave@1;DTL)CX+q<4HaF1CVmX9%0JOLKAZ5vl8b=EE_PBOQD zOUe~|U)Re>;3oi0d0)$Q+WURiOV7Ro-UF(NZo|VNbz5YJ(del#R(Fx}U^@DWW{LB* zc>z3D0HYB)T?WhJ%(n0e@d8y#UKzaBWIDk6gUgvYDm%?g6%NBR*33pxd7rxT5>*dJ zbv--?{G&j>P`_iOfBmZ(E1PNw9;D}E9dcff{GIV+KjvMK<&qDyzRAGn0Ofz6_1*J9 z-}79oe2kyhSR;2BO0G|a8V2*Zr87iw!)z<7AMoG#>fct3IUd_#I^n+*te_iX2Rqxp zBlS4+f%fxW1K#{QC7!>#{Di+tJ@)-e%3l&cZ`N(X1LCsB=C!d0sEFqI85bXalRv#J zLwvR}@sUNgv?r6(i=iWr0}pTwbEq>c83uh4G_1)YJkN_4CIf7UKaJrH=TXdXX8LpB z=W`fKw$R>#c~}g8$H8Qod7z!g=QVw)W*X*bH*F)3WLFRId)W}n%N$rBhB==7_OMOf zcFHD$*-qz$06ia;?G>z+!{p};SmN+aS|RjrKgSdx&Xhz<5yH)+fKixedu+bUGQ)P( zNai@^CDfjkNXV}#|AoOmqx4eB+bBz?KQ!qy`hCi3sLj7ijh=iwT{o(A--o)smjQn^ z(E1Nu{pLei-?b_)&T;1i>Na6ii0CHFgu%<_fm1yNsP~Zd^j5B_y|msMmhw z2YjTBl z0DXOuu3gpXl<_fzJZU{p94zZ|W(3WKa1K72>7BRsK%kF95peB+K6rjg>#Tr~GnN zeuu04!@$1^^!iDb-_%onaZmXzs{F{OEZ~A?>Q%ovw1f3;cCJ zH=Ja-Q)A_hFCks3+)h`yM}hwk=#!HycU(!V;E6r;5&VHHzoc82zXD!<)T{vqI>1A5_P%byf0e`Zhl(VuD)0?LbhvQ3fPWk4z5f%AyDd)d!Rb^uC11)i5oZSQ^MMw9sr}xS>ihWh zSVNP0DH==>7f>5ZNG67EHVp^QB#RT3x2kskQv28U0{=A7?_4+^DV(*+ua4ix1+a}f zs-<^bamsos@=BZuGz_!j1Lcs$c1A{GXti{)0hP(JEsJ@ruzxDNTd>yfhP{b41=s&8 z%43PpOKwyB{$IKtmH@vJ=(K-n`F^0jkL_PP^6qi+^(1O-r5~82xy2$Fk4MC_urkH< zPi8t^%g1whW5|mO=Aj-o6eK;J!s906VKj_;D;&8H%hNf4qwvVTHC`(4xj^~<)_7z7 zE%Ex>@9Du4T}>Wq2$JpP(t3ew2VHiHbC5}3%=aD$b?dp3*UVcpv(e~QvF(sH-5dr*Fv z!cX`LY#vbVR~moBR}z0;SKs)X8XI;9{PiMUKpTBk9`8>eJ6jl8HJw?2eXgBANHbqS zXOfnC)V%+d#=Qji{Xn<4aJv+4_rE1x^viy55w(+kL0_b_leQV+W3NGWwmYPDF=`&f z)AqxhL}p}%L6$_enI&+%9y^@nW{wLLKu5*P1wl531~YD;Iq=^dkH=%Bb2bS^(Ib?9 z#prOpiA|%^c&4rPBirv)KVtBvRkBTP*;3a^WHQkKFqj69Y?BSgOLm+~C?kIVi8{~^$)E_o*W zSIRR(-Md=!?>^*-HZ*Jzfj&{F=&y|i5xR7Di%Bl07;(@Lx3B%;n6V^`ubafUIo6xb z1L7M@<>KS1JkglPnNe!nsW!LsY zf3^Hal>D)K2*<@0iph_G?}e56AzmE+8HnF)kQYGwIZOmf2#Zrbyp zlIIMy4H&94iI5BUqm-V*XNZve(RStc{ZGp`2l!<`<^R+2ZC5vr`j2-F@>Nw<)z&oD zY^)Qv48mofq4^w2cEdz;BMS%cLP(~FID$_F3+x1cCL6(qh-VEx)6Vh}GLflzXnRP_ z`!2a&1^!*24_tDEz8<_>J&&2npTUSxbI5KmCLJu_84J@+p19P6XSMR;1@qZ7fDPJ0 zSsNqrRrXUUU&YtjzU~J8QlNcbYxy2f^7R{Uy+^+FRUn_(PcQoj>ut2Cw|7|BNrg^0 zQrv0CVy0<(hp|XvatdZ#0P%bQp9oZNjg&0mA>U}ZF8@Z#wMN;W zb^qx@uGm<~Yh{N`abNLYhWH4=pz)G@#!?4^+C=P#t5UEk>EXP*IYgLXckn4aeoSugulp5E*G(la)u+UWPVu=2k& z#K#D-yVW80z#J2Revyb7(^!!|F_wjrjg=`$mQ8bli z6Zz`yQ1d^?6Kj|60RJPP`>2+87?bkerQ!e{_Gk4W@5aW;t?I&1nYbvFFW%oW#mCKF z=!QvTpFLHC{IYnE8&0AVQHfsJC9fFJ3d z=y>5j_*kT13=a-9Is8{A$2-0W*1& zZ=QF8F_K+I>2_l(n?i4;b`}#q|CGXy2Pla?tNcIEJ7&-B0lppR5vJ?qh^m)G{oHGi z^-^84QMO{Z>?)iFwn9fWNT(C#MNSG^0G(~Bndmi*5FWmuA(53O6bno}js26dYNB4x zDf@3|xn=^t2xyt1<*GFXBUclqOOwxv?xrF@=x*?qzI4JC&QDW~LqiYY*k9W zI0Ku{xy8BPo5U{1uqpU|y<;uBOP|k6fWRdVVC3O|i0GLCQ++x(0U0dA0gn!TzYP8& z!^v{;@t8mLjPp}_fl;TLS|g{@D*1-d`H* zbl)2^(9ZbB2D^u+-bRz*cV`+KNO_mC1D3A8JAl6n=tq`rpZNWSo_ed>f+_n59uM0c z1hZ-412brMRc^PX+ugQ-2THMZyNtGbkK_3D<)#J^QCGxG5-XpIQ(^qnf#*)iTmB+$ zGs7u~oggu$a5Etlmq6=?dX>DX>_6bd{G#swe=pDjE;-&)a`fvL)i&bkRnc3zXzrxTSlzGkOd;*mT5toT6p)ti{6vh%ghvvIi1VQ z&8Z?jjhZ*#Qsdvz?Xn2?(}B)%wA|OL?_>AG568{3=t`_csaHoU>zkxg@h5pD{2m5Y z+9V$(fKy=Qf&}Pr`oQ&cSRT})*GS67U}c#s(+v5+yYtM0dM-`H_xZMs=Ku>BEORe3 zE}_=9s8K3T5R|>E_CH*5{}*_}1LNJJeH7k{k=jfk7Jz~zU z#|^8Kv32xXN*56IYWqOy5%Dros`Quw{9K@gUaiLpuNp7?%r|a5M9#@p+90+na>$-G zN}3B;4MsHCz*J({vcF5*{ZQ^Ah5I1zzXW>Hh5L-cePW@W&vLeG~Taq=lPW#Qu{y$UyrjxxEHfwS948sgU&|Y z#-@rBA|3MBNE+D#E4BS}9CSI$$qY_q8(BeK8X@PgZ&MY4xBO#e_x-xR-2;3(&?7E+ z4k>xos{N=){QO+GL(0*-H7d;WRp{TGL-v55^#Yv(HYI~ic1(}Yn$8*8=F2EApl6cu zPb9vRz-0_wNDU26R_~ z*7LE1xO#sh4o`wK^x&eh9rPXgB&8j69#{piIcz%2)-bC(E7)jHfaib}1)uym%1dc1 z?s3PbO7DP{rx1Cdi2*Ioc>yWUK^2ECdUODJ8s+UlFzw%#3&r(N|C}6z)sijFh>JMH zrVl)jOg7rV@USHeQ*HWe%b$&ADj|`NhJ}Qk;Khu_&r!C^$Y*0{66yGdl=q-Z-j{%X z6X;!+ymn%5dCT7GqrDo%B|%pfed875y9RAFegqbx4W=SCE&vlbxGt46&pHRVa_;pO z8|Qn{ympcu^5OP1UkNi8A7zL%y`@j38jkP%p6 z_sEeSlybz*|Ht27lS0%r%ae>1`7oG}769c!C!^#y#xT4*Y5AcMgU%$DOl_a-gUJ|t z%W1fOE9IyS>Tz`;@Yeuc=aS=IB}Z(0^)JVGA;<_20BHq2(jj|b^>S1Qk|qR6cc!v5 zAqcFoZ=`GqDgT%9|AM;T7)gvI0)>*a98;2{9M7wE+4EjM_JxR}jr&B_*mAO`n~_$& zl8wMDjeG)h^I~daNE=VcVy124p<>$%Vs?ikl#K%Yj!Ai1l63pr2>e|@2VC+TQu6%j z{eI=a(eHW`aI1V2@Jr~z-3ED>PX!O47(^+yCSY_a^hFiJ9uw z3)#B=tJc5Cdf((J;9mwh?2_vvC0Fboe0qHT2|e7wTuu_!@&fT57QN^zUMTKsB=N~? z49lRRE01Ouvs`%~wex>cj?$3s&kKRC0ICjYIW7oEIUZ5{c+V^G_u3M6eVe%HPAbP~A;%;&No41h2!8z-Q>a8eSIFqhN@HlN5>3zc#lP&g<@ z2k_4V{lO*2U)1;gtzYmtrHJepTQbIiNw&~3a#4J?d9Y6kH+=XfV z)VI24xwU3%)s{wqmn|NRBHndW#LYB<0b>#&!-3x-u}7DO@M4+c^vPAwWf8jaw2PxIgc#tk#Gn!$e#joEW~u z2ab4#U>Fm5?pqb!&ahtpUjzJ2KsUSa?pApHJ$J?n<@J^I4fq3zMQ!v5CEw$i7c6Xe zFeTdf_h?wx@Ba`Zoe`ccvGBeBb0Q12)mPymUW{)OBzvJ2M?yhes@z5Cx_@o} zelt)*y4L4H^?kqjC>t;x~ZHOdO+`PW=Vorfs9fEM^2`(?`VO_K|wX6Azi zfx?}5^qn<}C|eFQoUxcHe6cw>V5Vji8mXQD4barYhv5$$Gtsu8XC5*5D0U}hr_wdX z514bVeJA(B>S+d>&1#a~Vcr#<+tD(21!R33&d}}rA@H9A9m~-5K{921^taE6t-YY3 zv3#y;1nq^+btG;CMG{r}XX^2DF7TUxHfL(Qrp$rIPpp5fkPkFMCF5ZTc>%JVyug4VGnd!Fa-U?hgFQjT$NiT0 z_`dw9NW6zY-WD%;!N>zAG{o~oK-pCo-ht1+;NI3HlzCEeoHoXniuih$QfB%ySjfJ> zHa)f{l$gdsAv^3RWI1~V_u3|~iS#-O>ovN?*>0asNLcDso1^Rd0^qL(x;97a^~0Qj z=d~)V?0Pvk!jY*k9>=LLy(yprxKIysOpTR`FH6OZ*8t#XKe=lQlM|U@P4T9V&|I< zy>>j_78o}o4s0i_5$AiZVB(`xyeESIod)Ryvxs-iE2!R%FlwOfnPjV*b9p}a=Dq! z{8kPdVJ6@;@^x$?k*}6)rGG^0-w1pQ&}AwOOERQfK#sI_!8?NpAmn)mSbeTl*8%woQ#b9 z+d?ly=e4#5lK4rjAO!1@9o<0gi;TFySBq$5|#5zW{8o0kH= z59m8CIew(%SkqrztD4H{?Uk^iz=LC*6vqH1hs|Lkr`vE0Rq9PO3||80)V85Tek>o~ zlGZ%c|MPW!unM5>1Emyb{DOjk`-50MY^{vO+9Yxgn4sy>1nsp(F`qTpDB#QviFgKu zq%5NBUxD_|z6Ja(KzF!spH#U0#f5IH*&${)^%O=nMKLzQFnsgl+pA(T#!D`xT?Uzv z%{apZK_+)ZVq7Q97cLTD}zEhXRc(bj|mLQoh)^(<0Sh zg>b94)Wmv6B8u=A(L3gl%dvNCz@SQ|l?g&%QXq_MJb{^Z7G`fw^r4kbWG$2~VUw`D zib5&R{z5%&+JXNC(Bm$7o>lVn7cX;DLu13XW-wH%pu-4nx@0sAoDz^JO6~%0x(K7v z;{n{sxJ^eo6>e~du7@JvCj(6%qH${g5<%_0hYZ|KunfY_#$~ZU)ZsRIwS2z!D=-(> zGEdNK3xjrhVW9X~BKM19c=(RNl@eGwH}ml@#`QD-EE>$XKV?iN<%U=LP$}m@B?rp+ z9Pobv`m0OMQ-;d#W9Ki+#w+?G*5L2Ly^?gt+&0kjOVe6I%<5v2@Uzz;tsCg4R}=%+t|Dv;ZG2>ahgE)rtFSZ}S-DgNu4^5w z?7vIiZ-Dm?XC!I3mUrv$6U$rOu%o_5;#PW|*w4I%gT$>SY2hd_uIf@bdc9_;IWC2b z!r#HqG0uelVORmHN1G|;WYj`xGaR)^71z9N@s2HFg0*_p0KL#+6w-33S7fZzt7EwK zD_;iwHJ~?LdVQw!>Tlg3LQaE8RZpuPrn9_cAMK#zzmzjP1(r%@S^*4#h!43R>X}!& z6n5zlw4zl!CD1iR2HH2 zC{UBGfv@L03MeZ0t<1%ir$ zJkZl7vU%`t8Jms=7{$RJ2UGqyCbM}OTP@U?!m{{0wvMe~vuLiB%<_sb_s(RV$dfrn z{B(?DFk35y)k|ayN^bI6(5pj0O>8CDws2}doXpzEO~c8z>1=xewR147g>BCcfm39e zW&nr}6-fkl@y|{6SIQot)~19qZzqNiXOoSoo*Sq?&o_)8p>&$`U)raub^k~`FFp_a zD?qQ0)b;p@s>j&;9RGY+)Z=U!j%LobjT>dR3$9G0!Bc=TWas~t6Nbe>2t2xU@Z&(# z7Rt*+Inf!){*BW8Yz^?|0BsoM+HV>q<>+t!PW5|n(n{log@L)Jd3>VCP zz}X5B6RCTa@_$Eb|MxQBzX!B`w3hpRC3k=RuWY|)RNX~tr7y|YFE`-mY%$1fo>@?9 z3uuBhm4)d{V}Sv6cO_%niF`$8tNoAB+7C`01APi8dyK38#z;B(kAEj55l5Lu6vuqh z3J{`#yzEJ1r{IN$WwGd1V3!nbbd0tGt-wDF^m7;PHwyPaKkH&Q?ix%2KB8ELMF%G) z@(qPm(KS?j+#o-`Wa8u7SUp`9>GBl7j2hyT_)?Y#hU^SzxDfR?4l7}p(~5(I$YDW> zK{n>FVc@ZbsfQ*|jG>-x+D2lk-)G~l)kgL>2PM;3HeG@8mCTp=l^5%E|M|dg1KM4z z_4`4w)bFl-;=}f#A8s|lAGc!PY{iIcU_=ZL$M_f}EXnkycoO|y2PRCP5j4|aDM?u= zDO;e{zs1^Km}40U040yr@??&c^7Owid7M1;H9JiE+K>llb#rLW+eATPt_sqDDN%ZKdmkX$+!eq~!0u5L+uE4f%2S%0DNOa<%>) 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�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�^=x_djZxBCXo2QJQ2>^) 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 z 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